Remove libcall notes.
* see.c (see_analyse_one_def): Do not look for REG_LIBCALL and REG_RETVAL notes. (see_update_relevancy): Likewise. * fwprop.c (try_fwprop_subst): Likewise. * rtlanal.c (noop_move_p): Likewise. * builtins.c (expand_buitlin_mathfn): Don't try to add REG_EQUAL notes to non-existing libcall blocks. * cse.c (cse_insn): Change prototype. Don't update libcall notes. Remove orig_set. (cse_extended_basic_block): Don't track libcall and no-conflict notes. (dead_libcall_p): Remove. (delete_trivially_dead_insns): Don't use it. * web.c (union_defs): Remove comment about keeping nops. * gcse.c (hash_scan_insn): Don't take libcall pointers. (compute_hash_table_work): Don't track libcall notes. (do_local_cprop): Don't take libcall pointers. Don't update libcall notes. (adjust_libcall_notes): Deleted. (local_cprop_pass): Remove stack for nested libcalls (which shouldn't ever have existed in the first place). (replace_store_insn): Don't try to remove libcall notes. * lower-subreg.c (move_libcall_note, move_retval_note): Deleted. (resolve_reg_notes): Don't call them. (resolve_simple_move): Likewise. (decompose_multiword_subregs): Remove block handling REG_RETVAL notes. Don't remove REG_RETVAL notes. * emit-rtl.c (try_split): Don't update libcall notes. (emit_copy_of_insn_after): Dito. * cselib.c (cselib_current_insn_in_libcall): Remove. (cselib_process_insn): Don't set/clear it. (new_elt_loc_list): Don't record it. (cselib_init): Don't initialize it. * cselib.c (struct elt_loc_list): Remove in_libcall field. * loop-invariant.c (find_invariant_insn): Don't look for libcall notes. * sched-deps.c (sched_analyze_insn): Don't group libcall blocks. (sched_analyze): Don't set up deps->libcall_block_tail_insn. (init_deps): Don't initialize it. * sched-int.h (struct deps): Rremove libcall_block_tail_insn field. * combine.c (delete_noop_moves): Don't update libcall notes. (can_combine_p): Remove now pointless #if 0 block. (try_combine): Remove another obsolete #if 0 block. (distribute_notes): Don't distribute libcall notes. * reg-notes.def (REG_LIBCALL, REG_RETVAL): Remove. * dce.c (libcall_dead_p): Remove. (delete_unmarked_insns): Don't handle libcall blocks. (preserve_libcall_for_dce): Remove. (prescan_insns_for_dce): Don't special-case libcall block insns. * reload1 (reload): Don't handle libcall notes. * doc/rtl.texi (REG_LIBCALL, REG_RETVAL, REG_LIBCALL_ID): Remove documentation. From-SVN: r136861
This commit is contained in:
parent
e989f2d107
commit
4a8cae8370
20 changed files with 109 additions and 833 deletions
|
@ -1,3 +1,57 @@
|
|||
2008-06-17 Steven Bosscher <steven@gcc.gnu.org>
|
||||
|
||||
* see.c (see_analyse_one_def): Do not look for REG_LIBCALL and
|
||||
REG_RETVAL notes.
|
||||
(see_update_relevancy): Likewise.
|
||||
* fwprop.c (try_fwprop_subst): Likewise.
|
||||
* rtlanal.c (noop_move_p): Likewise.
|
||||
* builtins.c (expand_buitlin_mathfn): Don't try to add REG_EQUAL
|
||||
notes to non-existing libcall blocks.
|
||||
* cse.c (cse_insn): Change prototype. Don't update libcall notes.
|
||||
Remove orig_set.
|
||||
(cse_extended_basic_block): Don't track libcall and no-conflict notes.
|
||||
(dead_libcall_p): Remove.
|
||||
(delete_trivially_dead_insns): Don't use it.
|
||||
* web.c (union_defs): Remove comment about keeping nops.
|
||||
* gcse.c (hash_scan_insn): Don't take libcall pointers.
|
||||
(compute_hash_table_work): Don't track libcall notes.
|
||||
(do_local_cprop): Don't take libcall pointers. Don't update
|
||||
libcall notes.
|
||||
(adjust_libcall_notes): Deleted.
|
||||
(local_cprop_pass): Remove stack for nested libcalls (which shouldn't
|
||||
ever have existed in the first place).
|
||||
(replace_store_insn): Don't try to remove libcall notes.
|
||||
* lower-subreg.c (move_libcall_note, move_retval_note): Deleted.
|
||||
(resolve_reg_notes): Don't call them.
|
||||
(resolve_simple_move): Likewise.
|
||||
(decompose_multiword_subregs): Remove block handling REG_RETVAL notes.
|
||||
Don't remove REG_RETVAL notes.
|
||||
* emit-rtl.c (try_split): Don't update libcall notes.
|
||||
(emit_copy_of_insn_after): Dito.
|
||||
* cselib.c (cselib_current_insn_in_libcall): Remove.
|
||||
(cselib_process_insn): Don't set/clear it.
|
||||
(new_elt_loc_list): Don't record it.
|
||||
(cselib_init): Don't initialize it.
|
||||
* cselib.c (struct elt_loc_list): Remove in_libcall field.
|
||||
* loop-invariant.c (find_invariant_insn): Don't look for libcall
|
||||
notes.
|
||||
* sched-deps.c (sched_analyze_insn): Don't group libcall blocks.
|
||||
(sched_analyze): Don't set up deps->libcall_block_tail_insn.
|
||||
(init_deps): Don't initialize it.
|
||||
* sched-int.h (struct deps): Rremove libcall_block_tail_insn field.
|
||||
* combine.c (delete_noop_moves): Don't update libcall notes.
|
||||
(can_combine_p): Remove now pointless #if 0 block.
|
||||
(try_combine): Remove another obsolete #if 0 block.
|
||||
(distribute_notes): Don't distribute libcall notes.
|
||||
* reg-notes.def (REG_LIBCALL, REG_RETVAL): Remove.
|
||||
* dce.c (libcall_dead_p): Remove.
|
||||
(delete_unmarked_insns): Don't handle libcall blocks.
|
||||
(preserve_libcall_for_dce): Remove.
|
||||
(prescan_insns_for_dce): Don't special-case libcall block insns.
|
||||
* reload1 (reload): Don't handle libcall notes.
|
||||
* doc/rtl.texi (REG_LIBCALL, REG_RETVAL, REG_LIBCALL_ID): Remove
|
||||
documentation.
|
||||
|
||||
2008-06-16 Eric B. Weddington <eric.weddington@atmel.com>
|
||||
|
||||
* config/avr/avr.c (avr_mcu_t): Add atmega32c1.
|
||||
|
|
|
@ -1945,48 +1945,7 @@ expand_builtin_mathfn (tree exp, rtx target, rtx subtarget)
|
|||
|
||||
before_call = get_last_insn ();
|
||||
|
||||
target = expand_call (exp, target, target == const0_rtx);
|
||||
|
||||
/* If this is a sqrt operation and we don't care about errno, try to
|
||||
attach a REG_EQUAL note with a SQRT rtx to the emitted libcall.
|
||||
This allows the semantics of the libcall to be visible to the RTL
|
||||
optimizers. */
|
||||
if (builtin_optab == sqrt_optab && !errno_set)
|
||||
{
|
||||
/* Search backwards through the insns emitted by expand_call looking
|
||||
for the instruction with the REG_RETVAL note. */
|
||||
rtx last = get_last_insn ();
|
||||
while (last != before_call)
|
||||
{
|
||||
if (find_reg_note (last, REG_RETVAL, NULL))
|
||||
{
|
||||
rtx note = find_reg_note (last, REG_EQUAL, NULL);
|
||||
/* Check that the REQ_EQUAL note is an EXPR_LIST with
|
||||
two elements, i.e. symbol_ref(sqrt) and the operand. */
|
||||
if (note
|
||||
&& GET_CODE (note) == EXPR_LIST
|
||||
&& GET_CODE (XEXP (note, 0)) == EXPR_LIST
|
||||
&& XEXP (XEXP (note, 0), 1) != NULL_RTX
|
||||
&& XEXP (XEXP (XEXP (note, 0), 1), 1) == NULL_RTX)
|
||||
{
|
||||
rtx operand = XEXP (XEXP (XEXP (note, 0), 1), 0);
|
||||
/* Check operand is a register with expected mode. */
|
||||
if (operand
|
||||
&& REG_P (operand)
|
||||
&& GET_MODE (operand) == mode)
|
||||
{
|
||||
/* Replace the REG_EQUAL note with a SQRT rtx. */
|
||||
rtx equiv = gen_rtx_SQRT (mode, operand);
|
||||
set_unique_reg_note (last, REG_EQUAL, equiv);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
last = PREV_INSN (last);
|
||||
}
|
||||
}
|
||||
|
||||
return target;
|
||||
return expand_call (exp, target, target == const0_rtx);
|
||||
}
|
||||
|
||||
/* Expand a call to the builtin binary math functions (pow and atan2).
|
||||
|
|
|
@ -882,23 +882,6 @@ delete_noop_moves (void)
|
|||
next = NEXT_INSN (insn);
|
||||
if (INSN_P (insn) && noop_move_p (insn))
|
||||
{
|
||||
rtx note;
|
||||
|
||||
/* If we're about to remove the first insn of a libcall
|
||||
then move the libcall note to the next real insn and
|
||||
update the retval note. */
|
||||
if ((note = find_reg_note (insn, REG_LIBCALL, NULL_RTX))
|
||||
&& XEXP (note, 0) != insn)
|
||||
{
|
||||
rtx new_libcall_insn = next_real_insn (insn);
|
||||
rtx retval_note = find_reg_note (XEXP (note, 0),
|
||||
REG_RETVAL, NULL_RTX);
|
||||
REG_NOTES (new_libcall_insn)
|
||||
= gen_rtx_INSN_LIST (REG_LIBCALL, XEXP (note, 0),
|
||||
REG_NOTES (new_libcall_insn));
|
||||
XEXP (retval_note, 0) = new_libcall_insn;
|
||||
}
|
||||
|
||||
if (dump_file)
|
||||
fprintf (dump_file, "deleting noop move %d\n", INSN_UID (insn));
|
||||
|
||||
|
@ -1676,14 +1659,6 @@ can_combine_p (rtx insn, rtx i3, rtx pred ATTRIBUTE_UNUSED, rtx succ,
|
|||
|| (succ && FIND_REG_INC_NOTE (succ, dest))
|
||||
/* Don't substitute into a non-local goto, this confuses CFG. */
|
||||
|| (JUMP_P (i3) && find_reg_note (i3, REG_NON_LOCAL_GOTO, NULL_RTX))
|
||||
#if 0
|
||||
/* Don't combine the end of a libcall into anything. */
|
||||
/* ??? This gives worse code, and appears to be unnecessary, since no
|
||||
pass after flow uses REG_LIBCALL/REG_RETVAL notes. Local-alloc does
|
||||
use REG_RETVAL notes for noconflict blocks, but other code here
|
||||
makes sure that those insns don't disappear. */
|
||||
|| find_reg_note (insn, REG_RETVAL, NULL_RTX)
|
||||
#endif
|
||||
/* Make sure that DEST is not used after SUCC but before I3. */
|
||||
|| (succ && ! all_adjacent
|
||||
&& reg_used_between_p (dest, succ, i3))
|
||||
|
@ -2241,16 +2216,7 @@ try_combine (rtx i3, rtx i2, rtx i1, int *new_direct_jump_p)
|
|||
if (cant_combine_insn_p (i3)
|
||||
|| cant_combine_insn_p (i2)
|
||||
|| (i1 && cant_combine_insn_p (i1))
|
||||
|| likely_spilled_retval_p (i3)
|
||||
/* We also can't do anything if I3 has a
|
||||
REG_LIBCALL note since we don't want to disrupt the contiguity of a
|
||||
libcall. */
|
||||
#if 0
|
||||
/* ??? This gives worse code, and appears to be unnecessary, since no
|
||||
pass after flow uses REG_LIBCALL/REG_RETVAL notes. */
|
||||
|| find_reg_note (i3, REG_LIBCALL, NULL_RTX)
|
||||
#endif
|
||||
)
|
||||
|| likely_spilled_retval_p (i3))
|
||||
return 0;
|
||||
|
||||
combine_attempts++;
|
||||
|
@ -12547,48 +12513,6 @@ distribute_notes (rtx notes, rtx from_insn, rtx i3, rtx i2, rtx elim_i2,
|
|||
to simply delete it. */
|
||||
break;
|
||||
|
||||
case REG_RETVAL:
|
||||
/* If the insn previously containing this note still exists,
|
||||
put it back where it was. Otherwise move it to the previous
|
||||
insn. Adjust the corresponding REG_LIBCALL note. */
|
||||
if (!NOTE_P (from_insn))
|
||||
place = from_insn;
|
||||
else
|
||||
{
|
||||
tem = find_reg_note (XEXP (note, 0), REG_LIBCALL, NULL_RTX);
|
||||
place = prev_real_insn (from_insn);
|
||||
if (tem && place)
|
||||
XEXP (tem, 0) = place;
|
||||
/* If we're deleting the last remaining instruction of a
|
||||
libcall sequence, don't add the notes. */
|
||||
else if (XEXP (note, 0) == from_insn)
|
||||
tem = place = 0;
|
||||
/* Don't add the dangling REG_RETVAL note. */
|
||||
else if (! tem)
|
||||
place = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case REG_LIBCALL:
|
||||
/* This is handled similarly to REG_RETVAL. */
|
||||
if (!NOTE_P (from_insn))
|
||||
place = from_insn;
|
||||
else
|
||||
{
|
||||
tem = find_reg_note (XEXP (note, 0), REG_RETVAL, NULL_RTX);
|
||||
place = next_real_insn (from_insn);
|
||||
if (tem && place)
|
||||
XEXP (tem, 0) = place;
|
||||
/* If we're deleting the last remaining instruction of a
|
||||
libcall sequence, don't add the notes. */
|
||||
else if (XEXP (note, 0) == from_insn)
|
||||
tem = place = 0;
|
||||
/* Don't add the dangling REG_LIBCALL note. */
|
||||
else if (! tem)
|
||||
place = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case REG_DEAD:
|
||||
/* If we replaced the right hand side of FROM_INSN with a
|
||||
REG_EQUAL note, the original use of the dying register
|
||||
|
|
186
gcc/cse.c
186
gcc/cse.c
|
@ -584,7 +584,7 @@ static rtx equiv_constant (rtx);
|
|||
static void record_jump_equiv (rtx, bool);
|
||||
static void record_jump_cond (enum rtx_code, enum machine_mode, rtx, rtx,
|
||||
int);
|
||||
static void cse_insn (rtx, rtx);
|
||||
static void cse_insn (rtx);
|
||||
static void cse_prescan_path (struct cse_basic_block_data *);
|
||||
static void invalidate_from_clobbers (rtx);
|
||||
static rtx cse_process_notes (rtx, rtx, bool *);
|
||||
|
@ -599,7 +599,6 @@ static int check_dependence (rtx *, void *);
|
|||
static void flush_hash_table (void);
|
||||
static bool insn_live_p (rtx, int *);
|
||||
static bool set_live_p (rtx, rtx, int *);
|
||||
static bool dead_libcall_p (rtx, int *);
|
||||
static int cse_change_cc_mode (rtx *, void *);
|
||||
static void cse_change_cc_mode_insn (rtx, rtx);
|
||||
static void cse_change_cc_mode_insns (rtx, rtx, rtx);
|
||||
|
@ -3929,11 +3928,7 @@ record_jump_cond (enum rtx_code code, enum machine_mode mode, rtx op0,
|
|||
First simplify sources and addresses of all assignments
|
||||
in the instruction, using previously-computed equivalents values.
|
||||
Then install the new sources and destinations in the table
|
||||
of available values.
|
||||
|
||||
If LIBCALL_INSN is nonzero, don't record any equivalence made in
|
||||
the insn. It means that INSN is inside libcall block. In this
|
||||
case LIBCALL_INSN is the corresponding insn with REG_LIBCALL. */
|
||||
of available values. */
|
||||
|
||||
/* Data on one SET contained in the instruction. */
|
||||
|
||||
|
@ -3962,8 +3957,6 @@ struct set
|
|||
ENUM_BITFIELD(machine_mode) mode : 8;
|
||||
/* A constant equivalent for SET_SRC, if any. */
|
||||
rtx src_const;
|
||||
/* Original SET_SRC value used for libcall notes. */
|
||||
rtx orig_src;
|
||||
/* Hash value of constant equivalent for SET_SRC. */
|
||||
unsigned src_const_hash;
|
||||
/* Table entry for constant equivalent for SET_SRC, if any. */
|
||||
|
@ -3973,7 +3966,7 @@ struct set
|
|||
};
|
||||
|
||||
static void
|
||||
cse_insn (rtx insn, rtx libcall_insn)
|
||||
cse_insn (rtx insn)
|
||||
{
|
||||
rtx x = PATTERN (insn);
|
||||
int i;
|
||||
|
@ -4170,7 +4163,6 @@ cse_insn (rtx insn, rtx libcall_insn)
|
|||
rtx src = SET_SRC (sets[i].rtl);
|
||||
rtx new = canon_reg (src, insn);
|
||||
|
||||
sets[i].orig_src = src;
|
||||
validate_change (insn, &SET_SRC (sets[i].rtl), new, 1);
|
||||
|
||||
if (GET_CODE (dest) == ZERO_EXTRACT)
|
||||
|
@ -4821,22 +4813,6 @@ cse_insn (rtx insn, rtx libcall_insn)
|
|||
{
|
||||
rtx new = canon_reg (SET_SRC (sets[i].rtl), insn);
|
||||
|
||||
/* If we just made a substitution inside a libcall, then we
|
||||
need to make the same substitution in any notes attached
|
||||
to the RETVAL insn. */
|
||||
if (libcall_insn
|
||||
&& (REG_P (sets[i].orig_src)
|
||||
|| GET_CODE (sets[i].orig_src) == SUBREG
|
||||
|| MEM_P (sets[i].orig_src)))
|
||||
{
|
||||
rtx note = find_reg_equal_equiv_note (libcall_insn);
|
||||
if (note != 0)
|
||||
XEXP (note, 0) = simplify_replace_rtx (XEXP (note, 0),
|
||||
sets[i].orig_src,
|
||||
copy_rtx (new));
|
||||
df_notes_rescan (libcall_insn);
|
||||
}
|
||||
|
||||
/* The result of apply_change_group can be ignored; see
|
||||
canon_reg. */
|
||||
|
||||
|
@ -5175,27 +5151,19 @@ cse_insn (rtx insn, rtx libcall_insn)
|
|||
|
||||
if (sets[i].src_elt == 0)
|
||||
{
|
||||
/* Don't put a hard register source into the table if this is
|
||||
the last insn of a libcall. In this case, we only need
|
||||
to put src_eqv_elt in src_elt. */
|
||||
if (! find_reg_note (insn, REG_RETVAL, NULL_RTX))
|
||||
{
|
||||
struct table_elt *elt;
|
||||
struct table_elt *elt;
|
||||
|
||||
/* Note that these insert_regs calls cannot remove
|
||||
any of the src_elt's, because they would have failed to
|
||||
match if not still valid. */
|
||||
if (insert_regs (src, classp, 0))
|
||||
{
|
||||
rehash_using_reg (src);
|
||||
sets[i].src_hash = HASH (src, mode);
|
||||
}
|
||||
elt = insert (src, classp, sets[i].src_hash, mode);
|
||||
elt->in_memory = sets[i].src_in_memory;
|
||||
sets[i].src_elt = classp = elt;
|
||||
/* Note that these insert_regs calls cannot remove
|
||||
any of the src_elt's, because they would have failed to
|
||||
match if not still valid. */
|
||||
if (insert_regs (src, classp, 0))
|
||||
{
|
||||
rehash_using_reg (src);
|
||||
sets[i].src_hash = HASH (src, mode);
|
||||
}
|
||||
else
|
||||
sets[i].src_elt = classp;
|
||||
elt = insert (src, classp, sets[i].src_hash, mode);
|
||||
elt->in_memory = sets[i].src_in_memory;
|
||||
sets[i].src_elt = classp = elt;
|
||||
}
|
||||
if (sets[i].src_const && sets[i].src_const_elt == 0
|
||||
&& src != sets[i].src_const
|
||||
|
@ -5392,11 +5360,6 @@ cse_insn (rtx insn, rtx libcall_insn)
|
|||
size of it, and can't be sure that other BLKmode values
|
||||
have the same or smaller size. */
|
||||
|| GET_MODE (dest) == BLKmode
|
||||
/* Don't record values of destinations set inside a libcall block
|
||||
since we might delete the libcall. Things should have been set
|
||||
up so we won't want to reuse such a value, but we play it safe
|
||||
here. */
|
||||
|| libcall_insn
|
||||
/* If we didn't put a REG_EQUAL value or a source into the hash
|
||||
table, there is no point is recording DEST. */
|
||||
|| sets[i].src_elt == 0
|
||||
|
@ -5540,11 +5503,7 @@ cse_insn (rtx insn, rtx libcall_insn)
|
|||
then be used in the sequel and we may be changing a two-operand insn
|
||||
into a three-operand insn.
|
||||
|
||||
Also do not do this if we are operating on a copy of INSN.
|
||||
|
||||
Also don't do this if INSN ends a libcall; this would cause an unrelated
|
||||
register to be set in the middle of a libcall, and we then get bad code
|
||||
if the libcall is deleted. */
|
||||
Also do not do this if we are operating on a copy of INSN. */
|
||||
|
||||
if (n_sets == 1 && sets[0].rtl && REG_P (SET_DEST (sets[0].rtl))
|
||||
&& NEXT_INSN (PREV_INSN (insn)) == insn
|
||||
|
@ -5555,8 +5514,7 @@ cse_insn (rtx insn, rtx libcall_insn)
|
|||
int src_q = REG_QTY (REGNO (SET_SRC (sets[0].rtl)));
|
||||
struct qty_table_elem *src_ent = &qty_table[src_q];
|
||||
|
||||
if ((src_ent->first_reg == REGNO (SET_DEST (sets[0].rtl)))
|
||||
&& ! find_reg_note (insn, REG_RETVAL, NULL_RTX))
|
||||
if (src_ent->first_reg == REGNO (SET_DEST (sets[0].rtl)))
|
||||
{
|
||||
/* Scan for the previous nonnote insn, but stop at a basic
|
||||
block boundary. */
|
||||
|
@ -5993,8 +5951,6 @@ cse_extended_basic_block (struct cse_basic_block_data *ebb_data)
|
|||
{
|
||||
basic_block bb;
|
||||
rtx insn;
|
||||
rtx libcall_insn = NULL_RTX;
|
||||
int no_conflict = 0;
|
||||
|
||||
bb = ebb_data->path[path_entry].bb;
|
||||
|
||||
|
@ -6043,39 +5999,8 @@ cse_extended_basic_block (struct cse_basic_block_data *ebb_data)
|
|||
df_notes_rescan (insn);
|
||||
}
|
||||
|
||||
/* Track when we are inside in LIBCALL block. Inside such
|
||||
a block we do not want to record destinations. The last
|
||||
insn of a LIBCALL block is not considered to be part of
|
||||
the block, since its destination is the result of the
|
||||
block and hence should be recorded. */
|
||||
if (REG_NOTES (insn) != 0)
|
||||
{
|
||||
rtx p;
|
||||
cse_insn (insn);
|
||||
|
||||
if ((p = find_reg_note (insn, REG_LIBCALL, NULL_RTX)))
|
||||
libcall_insn = XEXP (p, 0);
|
||||
else if (find_reg_note (insn, REG_RETVAL, NULL_RTX))
|
||||
{
|
||||
/* Keep libcall_insn for the last SET insn of
|
||||
a no-conflict block to prevent changing the
|
||||
destination. */
|
||||
if (!no_conflict)
|
||||
libcall_insn = NULL_RTX;
|
||||
else
|
||||
no_conflict = -1;
|
||||
}
|
||||
}
|
||||
|
||||
cse_insn (insn, libcall_insn);
|
||||
|
||||
/* If we kept libcall_insn for a no-conflict bock,
|
||||
clear it here. */
|
||||
if (no_conflict == -1)
|
||||
{
|
||||
libcall_insn = NULL_RTX;
|
||||
no_conflict = 0;
|
||||
}
|
||||
|
||||
/* If we haven't already found an insn where we added a LABEL_REF,
|
||||
check this one. */
|
||||
if (INSN_P (insn) && !recorded_label_ref
|
||||
|
@ -6112,9 +6037,6 @@ cse_extended_basic_block (struct cse_basic_block_data *ebb_data)
|
|||
}
|
||||
}
|
||||
|
||||
/* Make sure that libcalls don't span multiple basic blocks. */
|
||||
gcc_assert (libcall_insn == NULL_RTX);
|
||||
|
||||
/* With non-call exceptions, we are not always able to update
|
||||
the CFG properly inside cse_insn. So clean up possibly
|
||||
redundant EH edges here. */
|
||||
|
@ -6479,57 +6401,6 @@ insn_live_p (rtx insn, int *counts)
|
|||
return true;
|
||||
}
|
||||
|
||||
/* Return true if libcall is dead as a whole. */
|
||||
|
||||
static bool
|
||||
dead_libcall_p (rtx insn, int *counts)
|
||||
{
|
||||
rtx note, set, new;
|
||||
|
||||
/* See if there's a REG_EQUAL note on this insn and try to
|
||||
replace the source with the REG_EQUAL expression.
|
||||
|
||||
We assume that insns with REG_RETVALs can only be reg->reg
|
||||
copies at this point. */
|
||||
note = find_reg_note (insn, REG_EQUAL, NULL_RTX);
|
||||
if (!note)
|
||||
return false;
|
||||
|
||||
set = single_set (insn);
|
||||
if (!set)
|
||||
return false;
|
||||
|
||||
new = simplify_rtx (XEXP (note, 0));
|
||||
if (!new)
|
||||
new = XEXP (note, 0);
|
||||
|
||||
/* While changing insn, we must update the counts accordingly. */
|
||||
count_reg_usage (insn, counts, NULL_RTX, -1);
|
||||
|
||||
if (validate_change (insn, &SET_SRC (set), new, 0))
|
||||
{
|
||||
count_reg_usage (insn, counts, NULL_RTX, 1);
|
||||
remove_note (insn, find_reg_note (insn, REG_RETVAL, NULL_RTX));
|
||||
remove_note (insn, note);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (CONSTANT_P (new))
|
||||
{
|
||||
new = force_const_mem (GET_MODE (SET_DEST (set)), new);
|
||||
if (new && validate_change (insn, &SET_SRC (set), new, 0))
|
||||
{
|
||||
count_reg_usage (insn, counts, NULL_RTX, 1);
|
||||
remove_note (insn, find_reg_note (insn, REG_RETVAL, NULL_RTX));
|
||||
remove_note (insn, note);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
count_reg_usage (insn, counts, NULL_RTX, 1);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Scan all the insns and delete any that are dead; i.e., they store a register
|
||||
that is never used or they copy a register to itself.
|
||||
|
||||
|
@ -6543,7 +6414,6 @@ delete_trivially_dead_insns (rtx insns, int nreg)
|
|||
{
|
||||
int *counts;
|
||||
rtx insn, prev;
|
||||
int in_libcall = 0, dead_libcall = 0;
|
||||
int ndead = 0;
|
||||
|
||||
timevar_push (TV_DELETE_TRIVIALLY_DEAD);
|
||||
|
@ -6568,21 +6438,7 @@ delete_trivially_dead_insns (rtx insns, int nreg)
|
|||
if (!INSN_P (insn))
|
||||
continue;
|
||||
|
||||
/* Don't delete any insns that are part of a libcall block unless
|
||||
we can delete the whole libcall block.
|
||||
|
||||
Flow or loop might get confused if we did that. Remember
|
||||
that we are scanning backwards. */
|
||||
if (find_reg_note (insn, REG_RETVAL, NULL_RTX))
|
||||
{
|
||||
in_libcall = 1;
|
||||
live_insn = 1;
|
||||
dead_libcall = dead_libcall_p (insn, counts);
|
||||
}
|
||||
else if (in_libcall)
|
||||
live_insn = ! dead_libcall;
|
||||
else
|
||||
live_insn = insn_live_p (insn, counts);
|
||||
live_insn = insn_live_p (insn, counts);
|
||||
|
||||
/* If this is a dead insn, delete it and show registers in it aren't
|
||||
being used. */
|
||||
|
@ -6593,12 +6449,6 @@ delete_trivially_dead_insns (rtx insns, int nreg)
|
|||
delete_insn_and_edges (insn);
|
||||
ndead++;
|
||||
}
|
||||
|
||||
if (in_libcall && find_reg_note (insn, REG_LIBCALL, NULL_RTX))
|
||||
{
|
||||
in_libcall = 0;
|
||||
dead_libcall = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (dump_file && ndead)
|
||||
|
|
11
gcc/cselib.c
11
gcc/cselib.c
|
@ -78,7 +78,6 @@ static htab_t cselib_hash_table;
|
|||
/* This is a global so we don't have to pass this through every function.
|
||||
It is used in new_elt_loc_list to set SETTING_INSN. */
|
||||
static rtx cselib_current_insn;
|
||||
static bool cselib_current_insn_in_libcall;
|
||||
|
||||
/* Every new unknown value gets a unique number. */
|
||||
static unsigned int next_unknown_value;
|
||||
|
@ -160,7 +159,6 @@ new_elt_loc_list (struct elt_loc_list *next, rtx loc)
|
|||
el->next = next;
|
||||
el->loc = loc;
|
||||
el->setting_insn = cselib_current_insn;
|
||||
el->in_libcall = cselib_current_insn_in_libcall;
|
||||
return el;
|
||||
}
|
||||
|
||||
|
@ -1655,8 +1653,6 @@ cselib_process_insn (rtx insn)
|
|||
int i;
|
||||
rtx x;
|
||||
|
||||
if (find_reg_note (insn, REG_LIBCALL, NULL))
|
||||
cselib_current_insn_in_libcall = true;
|
||||
cselib_current_insn = insn;
|
||||
|
||||
/* Forget everything at a CODE_LABEL, a volatile asm, or a setjmp. */
|
||||
|
@ -1667,16 +1663,12 @@ cselib_process_insn (rtx insn)
|
|||
&& GET_CODE (PATTERN (insn)) == ASM_OPERANDS
|
||||
&& MEM_VOLATILE_P (PATTERN (insn))))
|
||||
{
|
||||
if (find_reg_note (insn, REG_RETVAL, NULL))
|
||||
cselib_current_insn_in_libcall = false;
|
||||
cselib_clear_table ();
|
||||
return;
|
||||
}
|
||||
|
||||
if (! INSN_P (insn))
|
||||
{
|
||||
if (find_reg_note (insn, REG_RETVAL, NULL))
|
||||
cselib_current_insn_in_libcall = false;
|
||||
cselib_current_insn = 0;
|
||||
return;
|
||||
}
|
||||
|
@ -1719,8 +1711,6 @@ cselib_process_insn (rtx insn)
|
|||
if (GET_CODE (XEXP (x, 0)) == CLOBBER)
|
||||
cselib_invalidate_rtx (XEXP (XEXP (x, 0), 0));
|
||||
|
||||
if (find_reg_note (insn, REG_RETVAL, NULL))
|
||||
cselib_current_insn_in_libcall = false;
|
||||
cselib_current_insn = 0;
|
||||
|
||||
if (n_useless_values > MAX_USELESS_VALUES
|
||||
|
@ -1769,7 +1759,6 @@ cselib_init (bool record_memory)
|
|||
n_used_regs = 0;
|
||||
cselib_hash_table = htab_create (31, get_value_hash,
|
||||
entry_and_rtx_equal_p, NULL);
|
||||
cselib_current_insn_in_libcall = false;
|
||||
}
|
||||
|
||||
/* Called when the current user is done with cselib. */
|
||||
|
|
|
@ -47,8 +47,6 @@ struct elt_loc_list GTY(())
|
|||
rtx loc;
|
||||
/* The insn that made the equivalence. */
|
||||
rtx setting_insn;
|
||||
/* True when setting insn is inside libcall. */
|
||||
bool in_libcall;
|
||||
};
|
||||
|
||||
/* A list of cselib_val structures. */
|
||||
|
|
152
gcc/dce.c
152
gcc/dce.c
|
@ -214,62 +214,6 @@ mark_nonreg_stores (rtx body, rtx insn, bool fast)
|
|||
}
|
||||
|
||||
|
||||
/* Return true if the entire libcall sequence starting at INSN is dead.
|
||||
NOTE is the REG_LIBCALL note attached to INSN.
|
||||
|
||||
A libcall sequence is a block of insns with no side-effects, i.e.
|
||||
that is only used for its return value. The terminology derives
|
||||
from that of a call, but a libcall sequence need not contain one.
|
||||
It is only defined by a pair of REG_LIBCALL/REG_RETVAL notes.
|
||||
|
||||
From a dataflow viewpoint, a libcall sequence has the property that
|
||||
no UD chain can enter it from the outside. As a consequence, if a
|
||||
libcall sequence has a dead return value, it is effectively dead.
|
||||
This is both enforced by CSE (cse_extended_basic_block) and relied
|
||||
upon by delete_trivially_dead_insns.
|
||||
|
||||
However, in practice, the return value business is a tricky one and
|
||||
only checking the liveness of the last insn is not sufficient to
|
||||
decide whether the whole sequence is dead (e.g. PR middle-end/19551)
|
||||
so we check the liveness of every insn starting from the call. */
|
||||
|
||||
static bool
|
||||
libcall_dead_p (rtx insn, rtx note)
|
||||
{
|
||||
rtx last = XEXP (note, 0);
|
||||
|
||||
/* Find the call insn. */
|
||||
while (insn != last && !CALL_P (insn))
|
||||
insn = NEXT_INSN (insn);
|
||||
|
||||
/* If there is none, do nothing special, since ordinary death handling
|
||||
can understand these insns. */
|
||||
if (!CALL_P (insn))
|
||||
return false;
|
||||
|
||||
/* If this is a call that returns a value via an invisible pointer, the
|
||||
dataflow engine cannot see it so it has been marked unconditionally.
|
||||
Skip it unless it has been made the last insn in the libcall, for
|
||||
example by the combiner, in which case we're left with no easy way
|
||||
of asserting its liveness. */
|
||||
if (!single_set (insn))
|
||||
{
|
||||
if (insn == last)
|
||||
return false;
|
||||
insn = NEXT_INSN (insn);
|
||||
}
|
||||
|
||||
while (insn != NEXT_INSN (last))
|
||||
{
|
||||
if (INSN_P (insn) && marked_insn_p (insn))
|
||||
return false;
|
||||
insn = NEXT_INSN (insn);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* Delete all REG_EQUAL notes of the registers INSN writes, to prevent
|
||||
bad dangling REG_EQUAL notes. */
|
||||
|
||||
|
@ -316,29 +260,10 @@ delete_unmarked_insns (void)
|
|||
FOR_BB_INSNS_SAFE (bb, insn, next)
|
||||
if (INSN_P (insn))
|
||||
{
|
||||
rtx note = find_reg_note (insn, REG_LIBCALL, NULL_RTX);
|
||||
|
||||
/* Always delete no-op moves. */
|
||||
if (noop_move_p (insn))
|
||||
;
|
||||
|
||||
/* Try to delete libcall sequences as a whole. */
|
||||
else if (note && libcall_dead_p (insn, note))
|
||||
{
|
||||
rtx last = XEXP (note, 0);
|
||||
|
||||
if (!dbg_cnt (dce))
|
||||
continue;
|
||||
|
||||
if (dump_file)
|
||||
fprintf (dump_file, "DCE: Deleting libcall %d-%d\n",
|
||||
INSN_UID (insn), INSN_UID (last));
|
||||
|
||||
next = NEXT_INSN (last);
|
||||
delete_insn_chain_and_edges (insn, last);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Otherwise rely only on the DCE algorithm. */
|
||||
else if (marked_insn_p (insn))
|
||||
continue;
|
||||
|
@ -353,41 +278,6 @@ delete_unmarked_insns (void)
|
|||
for the destination regs in order to avoid dangling notes. */
|
||||
delete_corresponding_reg_eq_notes (insn);
|
||||
|
||||
/* If we're about to delete the first insn of a libcall, then
|
||||
move the REG_LIBCALL note to the next real insn and update
|
||||
the REG_RETVAL note. */
|
||||
if (note && (XEXP (note, 0) != insn))
|
||||
{
|
||||
rtx new_libcall_insn = next_real_insn (insn);
|
||||
rtx retval_note = find_reg_note (XEXP (note, 0),
|
||||
REG_RETVAL, NULL_RTX);
|
||||
/* If the RETVAL and LIBCALL notes would land on the same
|
||||
insn just remove them. */
|
||||
if (XEXP (note, 0) == new_libcall_insn)
|
||||
remove_note (new_libcall_insn, retval_note);
|
||||
else
|
||||
{
|
||||
REG_NOTES (new_libcall_insn)
|
||||
= gen_rtx_INSN_LIST (REG_LIBCALL, XEXP (note, 0),
|
||||
REG_NOTES (new_libcall_insn));
|
||||
XEXP (retval_note, 0) = new_libcall_insn;
|
||||
}
|
||||
}
|
||||
|
||||
/* If the insn contains a REG_RETVAL note and is dead, but the
|
||||
libcall as a whole is not dead, then we want to remove the
|
||||
insn, but not the whole libcall sequence. However, we also
|
||||
need to remove the dangling REG_LIBCALL note in order to
|
||||
avoid mismatched notes. We could find a new location for
|
||||
the REG_RETVAL note, but it hardly seems worth the effort. */
|
||||
note = find_reg_note (insn, REG_RETVAL, NULL_RTX);
|
||||
if (note && (XEXP (note, 0) != insn))
|
||||
{
|
||||
rtx libcall_note
|
||||
= find_reg_note (XEXP (note, 0), REG_LIBCALL, NULL_RTX);
|
||||
remove_note (XEXP (note, 0), libcall_note);
|
||||
}
|
||||
|
||||
/* If a pure or const call is deleted, this may make the cfg
|
||||
have unreachable blocks. We rememeber this and call
|
||||
delete_unreachable_blocks at the end. */
|
||||
|
@ -404,43 +294,6 @@ delete_unmarked_insns (void)
|
|||
}
|
||||
|
||||
|
||||
/* Helper function for prescan_insns_for_dce: prescan the entire libcall
|
||||
sequence starting at INSN and return the insn following the libcall.
|
||||
NOTE is the REG_LIBCALL note attached to INSN. */
|
||||
|
||||
static rtx
|
||||
prescan_libcall_for_dce (rtx insn, rtx note, bool fast)
|
||||
{
|
||||
rtx last = XEXP (note, 0);
|
||||
|
||||
/* A libcall is never necessary on its own but we need to mark the stores
|
||||
to a non-register destination. */
|
||||
while (insn != last && !CALL_P (insn))
|
||||
{
|
||||
if (INSN_P (insn))
|
||||
mark_nonreg_stores (PATTERN (insn), insn, fast);
|
||||
insn = NEXT_INSN (insn);
|
||||
}
|
||||
|
||||
/* If this is a call that returns a value via an invisible pointer, the
|
||||
dataflow engine cannot see it so it has to be marked unconditionally. */
|
||||
if (CALL_P (insn) && !single_set (insn))
|
||||
{
|
||||
mark_insn (insn, fast);
|
||||
insn = NEXT_INSN (insn);
|
||||
}
|
||||
|
||||
while (insn != NEXT_INSN (last))
|
||||
{
|
||||
if (INSN_P (insn))
|
||||
mark_nonreg_stores (PATTERN (insn), insn, fast);
|
||||
insn = NEXT_INSN (insn);
|
||||
}
|
||||
|
||||
return insn;
|
||||
}
|
||||
|
||||
|
||||
/* Go through the instructions and mark those whose necessity is not
|
||||
dependent on inter-instruction information. Make sure all other
|
||||
instructions are not marked. */
|
||||
|
@ -458,10 +311,7 @@ prescan_insns_for_dce (bool fast)
|
|||
FOR_BB_INSNS_SAFE (bb, insn, next)
|
||||
if (INSN_P (insn))
|
||||
{
|
||||
rtx note = find_reg_note (insn, REG_LIBCALL, NULL_RTX);
|
||||
if (note)
|
||||
next = prescan_libcall_for_dce (insn, note, fast);
|
||||
else if (deletable_insn_p (insn, fast))
|
||||
if (deletable_insn_p (insn, fast))
|
||||
mark_nonreg_stores (PATTERN (insn), insn, fast);
|
||||
else
|
||||
mark_insn (insn, fast);
|
||||
|
|
|
@ -3754,31 +3754,6 @@ insn has one of a pair of notes that points to a second insn, which has
|
|||
the inverse note pointing back to the first insn.
|
||||
|
||||
@table @code
|
||||
@findex REG_RETVAL
|
||||
@item REG_RETVAL
|
||||
This insn copies the value of a multi-insn sequence (for example, a
|
||||
library call), and @var{op} is the first insn of the sequence (for a
|
||||
library call, the first insn that was generated to set up the arguments
|
||||
for the library call).
|
||||
|
||||
Loop optimization uses this note to treat such a sequence as a single
|
||||
operation for code motion purposes and flow analysis uses this note to
|
||||
delete such sequences whose results are dead.
|
||||
|
||||
A @code{REG_EQUAL} note will also usually be attached to this insn to
|
||||
provide the expression being computed by the sequence.
|
||||
|
||||
These notes will be deleted after reload, since they are no longer
|
||||
accurate or useful.
|
||||
|
||||
@findex REG_LIBCALL
|
||||
@item REG_LIBCALL
|
||||
This is the inverse of @code{REG_RETVAL}: it is placed on the first
|
||||
insn of a multi-insn sequence, and it points to the last one.
|
||||
|
||||
These notes are deleted after reload, since they are no longer useful or
|
||||
accurate.
|
||||
|
||||
@findex REG_CC_SETTER
|
||||
@findex REG_CC_USER
|
||||
@item REG_CC_SETTER
|
||||
|
@ -3836,12 +3811,6 @@ of the JUMP@. The format is a bitmask of ATTR_FLAG_* values.
|
|||
This is used on an RTX_FRAME_RELATED_P insn wherein the attached expression
|
||||
is used in place of the actual insn pattern. This is done in cases where
|
||||
the pattern is either complex or misleading.
|
||||
|
||||
@findex REG_LIBCALL_ID
|
||||
@item REG_LIBCALL_ID
|
||||
This is used to specify that an insn is part of a libcall. Each libcall
|
||||
in a function has a unique id, and all the insns that are part of that
|
||||
libcall will have a REG_LIBCALL_ID note attached with the same ID.
|
||||
@end table
|
||||
|
||||
For convenience, the machine mode in an @code{insn_list} or
|
||||
|
|
|
@ -3160,8 +3160,7 @@ try_split (rtx pat, rtx trial, int last)
|
|||
rtx before = PREV_INSN (trial);
|
||||
rtx after = NEXT_INSN (trial);
|
||||
int has_barrier = 0;
|
||||
rtx tem, note_retval, note_libcall;
|
||||
rtx note, seq;
|
||||
rtx note, seq, tem;
|
||||
int probability;
|
||||
rtx insn_last, insn;
|
||||
int njumps = 0;
|
||||
|
@ -3296,30 +3295,6 @@ try_split (rtx pat, rtx trial, int last)
|
|||
break;
|
||||
#endif
|
||||
|
||||
case REG_LIBCALL:
|
||||
/* Relink the insns with REG_LIBCALL note and with REG_RETVAL note
|
||||
after split. */
|
||||
REG_NOTES (insn_last)
|
||||
= gen_rtx_INSN_LIST (REG_LIBCALL,
|
||||
XEXP (note, 0),
|
||||
REG_NOTES (insn_last));
|
||||
|
||||
note_retval = find_reg_note (XEXP (note, 0), REG_RETVAL, NULL);
|
||||
XEXP (note_retval, 0) = insn_last;
|
||||
break;
|
||||
|
||||
case REG_RETVAL:
|
||||
/* Relink the insns with REG_LIBCALL note and with REG_RETVAL note
|
||||
after split. */
|
||||
REG_NOTES (insn_last)
|
||||
= gen_rtx_INSN_LIST (REG_RETVAL,
|
||||
XEXP (note, 0),
|
||||
REG_NOTES (insn_last));
|
||||
|
||||
note_libcall = find_reg_note (XEXP (note, 0), REG_LIBCALL, NULL);
|
||||
XEXP (note_libcall, 0) = insn_last;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -5501,8 +5476,7 @@ init_emit_once (int line_numbers)
|
|||
rtx
|
||||
emit_copy_of_insn_after (rtx insn, rtx after)
|
||||
{
|
||||
rtx new;
|
||||
rtx note1, note2, link;
|
||||
rtx new, link;
|
||||
|
||||
switch (GET_CODE (insn))
|
||||
{
|
||||
|
@ -5556,15 +5530,6 @@ emit_copy_of_insn_after (rtx insn, rtx after)
|
|||
XEXP (link, 0), REG_NOTES (new));
|
||||
}
|
||||
|
||||
/* Fix the libcall sequences. */
|
||||
if ((note1 = find_reg_note (new, REG_RETVAL, NULL_RTX)) != NULL)
|
||||
{
|
||||
rtx p = new;
|
||||
while ((note2 = find_reg_note (p, REG_LIBCALL, NULL_RTX)) == NULL)
|
||||
p = PREV_INSN (p);
|
||||
XEXP (note1, 0) = p;
|
||||
XEXP (note2, 0) = new;
|
||||
}
|
||||
INSN_CODE (new) = INSN_CODE (insn);
|
||||
return new;
|
||||
}
|
||||
|
|
|
@ -776,11 +776,8 @@ try_fwprop_subst (struct df_ref *use, rtx *loc, rtx new, rtx def_insn, bool set_
|
|||
cancel_changes (0);
|
||||
|
||||
/* Can also record a simplified value in a REG_EQUAL note,
|
||||
making a new one if one does not already exist.
|
||||
Don't do this if the insn has a REG_RETVAL note, because the
|
||||
combined presence means that the REG_EQUAL note refers to the
|
||||
(full) contents of the libcall value. */
|
||||
if (set_reg_equal && !find_reg_note (insn, REG_RETVAL, NULL_RTX))
|
||||
making a new one if one does not already exist. */
|
||||
if (set_reg_equal)
|
||||
{
|
||||
if (dump_file)
|
||||
fprintf (dump_file, " Setting REG_EQUAL note\n");
|
||||
|
|
130
gcc/gcse.c
130
gcc/gcse.c
|
@ -519,7 +519,7 @@ static void free_reg_set_mem (void);
|
|||
static void record_one_set (int, rtx);
|
||||
static void record_set_info (rtx, const_rtx, void *);
|
||||
static void compute_sets (void);
|
||||
static void hash_scan_insn (rtx, struct hash_table *, int);
|
||||
static void hash_scan_insn (rtx, struct hash_table *);
|
||||
static void hash_scan_set (rtx, rtx, struct hash_table *);
|
||||
static void hash_scan_clobber (rtx, rtx, struct hash_table *);
|
||||
static void hash_scan_call (rtx, rtx, struct hash_table *);
|
||||
|
@ -635,8 +635,7 @@ static void clear_modify_mem_tables (void);
|
|||
static void free_modify_mem_tables (void);
|
||||
static rtx gcse_emit_move_after (rtx, rtx, rtx);
|
||||
static void local_cprop_find_used_regs (rtx *, void *);
|
||||
static bool do_local_cprop (rtx, rtx, bool, rtx*);
|
||||
static bool adjust_libcall_notes (rtx, rtx, rtx, rtx*);
|
||||
static bool do_local_cprop (rtx, rtx, bool);
|
||||
static void local_cprop_pass (bool);
|
||||
static bool is_too_expensive (const char *);
|
||||
|
||||
|
@ -1838,19 +1837,14 @@ hash_scan_call (rtx x ATTRIBUTE_UNUSED, rtx insn ATTRIBUTE_UNUSED,
|
|||
are also in the PARALLEL. Later.
|
||||
|
||||
If SET_P is nonzero, this is for the assignment hash table,
|
||||
otherwise it is for the expression hash table.
|
||||
If IN_LIBCALL_BLOCK nonzero, we are in a libcall block, and should
|
||||
not record any expressions. */
|
||||
otherwise it is for the expression hash table. */
|
||||
|
||||
static void
|
||||
hash_scan_insn (rtx insn, struct hash_table *table, int in_libcall_block)
|
||||
hash_scan_insn (rtx insn, struct hash_table *table)
|
||||
{
|
||||
rtx pat = PATTERN (insn);
|
||||
int i;
|
||||
|
||||
if (in_libcall_block)
|
||||
return;
|
||||
|
||||
/* Pick out the sets of INSN and for other forms of instructions record
|
||||
what's been modified. */
|
||||
|
||||
|
@ -2063,7 +2057,6 @@ compute_hash_table_work (struct hash_table *table)
|
|||
{
|
||||
rtx insn;
|
||||
unsigned int regno;
|
||||
int in_libcall_block;
|
||||
|
||||
/* First pass over the instructions records information used to
|
||||
determine when registers and memory are first and last set.
|
||||
|
@ -2094,18 +2087,9 @@ compute_hash_table_work (struct hash_table *table)
|
|||
BB_HEAD (current_bb), table);
|
||||
|
||||
/* The next pass builds the hash table. */
|
||||
in_libcall_block = 0;
|
||||
FOR_BB_INSNS (current_bb, insn)
|
||||
if (INSN_P (insn))
|
||||
{
|
||||
if (find_reg_note (insn, REG_LIBCALL, NULL_RTX))
|
||||
in_libcall_block = 1;
|
||||
else if (table->set_p && find_reg_note (insn, REG_RETVAL, NULL_RTX))
|
||||
in_libcall_block = 0;
|
||||
hash_scan_insn (insn, table, in_libcall_block);
|
||||
if (!table->set_p && find_reg_note (insn, REG_RETVAL, NULL_RTX))
|
||||
in_libcall_block = 0;
|
||||
}
|
||||
hash_scan_insn (insn, table);
|
||||
}
|
||||
|
||||
free (reg_avail_info);
|
||||
|
@ -3077,11 +3061,11 @@ local_cprop_find_used_regs (rtx *xptr, void *data)
|
|||
find_used_regs (xptr, data);
|
||||
}
|
||||
|
||||
/* LIBCALL_SP is a zero-terminated array of insns at the end of a libcall;
|
||||
their REG_EQUAL notes need updating. */
|
||||
/* Try to perform local const/copy propagation on X in INSN.
|
||||
If ALTER_JUMPS is false, changing jump insns is not allowed. */
|
||||
|
||||
static bool
|
||||
do_local_cprop (rtx x, rtx insn, bool alter_jumps, rtx *libcall_sp)
|
||||
do_local_cprop (rtx x, rtx insn, bool alter_jumps)
|
||||
{
|
||||
rtx newreg = NULL, newcnst = NULL;
|
||||
|
||||
|
@ -3102,10 +3086,6 @@ do_local_cprop (rtx x, rtx insn, bool alter_jumps, rtx *libcall_sp)
|
|||
rtx this_rtx = l->loc;
|
||||
rtx note;
|
||||
|
||||
/* Don't CSE non-constant values out of libcall blocks. */
|
||||
if (l->in_libcall && ! CONSTANT_P (this_rtx))
|
||||
continue;
|
||||
|
||||
if (gcse_constant_p (this_rtx))
|
||||
newcnst = this_rtx;
|
||||
if (REG_P (this_rtx) && REGNO (this_rtx) >= FIRST_PSEUDO_REGISTER
|
||||
|
@ -3120,16 +3100,6 @@ do_local_cprop (rtx x, rtx insn, bool alter_jumps, rtx *libcall_sp)
|
|||
}
|
||||
if (newcnst && constprop_register (insn, x, newcnst, alter_jumps))
|
||||
{
|
||||
/* If we find a case where we can't fix the retval REG_EQUAL notes
|
||||
match the new register, we either have to abandon this replacement
|
||||
or fix delete_trivially_dead_insns to preserve the setting insn,
|
||||
or make it delete the REG_EQUAL note, and fix up all passes that
|
||||
require the REG_EQUAL note there. */
|
||||
bool adjusted;
|
||||
|
||||
adjusted = adjust_libcall_notes (x, newcnst, insn, libcall_sp);
|
||||
gcc_assert (adjusted);
|
||||
|
||||
if (dump_file != NULL)
|
||||
{
|
||||
fprintf (dump_file, "LOCAL CONST-PROP: Replacing reg %d in ",
|
||||
|
@ -3144,7 +3114,6 @@ do_local_cprop (rtx x, rtx insn, bool alter_jumps, rtx *libcall_sp)
|
|||
}
|
||||
else if (newreg && newreg != x && try_replace_reg (x, newreg, insn))
|
||||
{
|
||||
adjust_libcall_notes (x, newreg, insn, libcall_sp);
|
||||
if (dump_file != NULL)
|
||||
{
|
||||
fprintf (dump_file,
|
||||
|
@ -3159,47 +3128,6 @@ do_local_cprop (rtx x, rtx insn, bool alter_jumps, rtx *libcall_sp)
|
|||
return false;
|
||||
}
|
||||
|
||||
/* LIBCALL_SP is a zero-terminated array of insns at the end of a libcall;
|
||||
their REG_EQUAL notes need updating to reflect that OLDREG has been
|
||||
replaced with NEWVAL in INSN. Return true if all substitutions could
|
||||
be made. */
|
||||
static bool
|
||||
adjust_libcall_notes (rtx oldreg, rtx newval, rtx insn, rtx *libcall_sp)
|
||||
{
|
||||
rtx end;
|
||||
|
||||
while ((end = *libcall_sp++))
|
||||
{
|
||||
rtx note = find_reg_equal_equiv_note (end);
|
||||
|
||||
if (! note)
|
||||
continue;
|
||||
|
||||
if (REG_P (newval))
|
||||
{
|
||||
if (reg_set_between_p (newval, PREV_INSN (insn), end))
|
||||
{
|
||||
do
|
||||
{
|
||||
note = find_reg_equal_equiv_note (end);
|
||||
if (! note)
|
||||
continue;
|
||||
if (reg_mentioned_p (newval, XEXP (note, 0)))
|
||||
return false;
|
||||
}
|
||||
while ((end = *libcall_sp++));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
XEXP (note, 0) = simplify_replace_rtx (XEXP (note, 0), oldreg, newval);
|
||||
df_notes_rescan (end);
|
||||
insn = end;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#define MAX_NESTED_LIBCALLS 9
|
||||
|
||||
/* Do local const/copy propagation (i.e. within each basic block).
|
||||
If ALTER_JUMPS is true, allow propagating into jump insns, which
|
||||
could modify the CFG. */
|
||||
|
@ -3210,29 +3138,16 @@ local_cprop_pass (bool alter_jumps)
|
|||
basic_block bb;
|
||||
rtx insn;
|
||||
struct reg_use *reg_used;
|
||||
rtx libcall_stack[MAX_NESTED_LIBCALLS + 1], *libcall_sp;
|
||||
bool changed = false;
|
||||
|
||||
cselib_init (false);
|
||||
libcall_sp = &libcall_stack[MAX_NESTED_LIBCALLS];
|
||||
*libcall_sp = 0;
|
||||
FOR_EACH_BB (bb)
|
||||
{
|
||||
FOR_BB_INSNS (bb, insn)
|
||||
{
|
||||
if (INSN_P (insn))
|
||||
{
|
||||
rtx note = find_reg_note (insn, REG_LIBCALL, NULL_RTX);
|
||||
|
||||
if (note)
|
||||
{
|
||||
gcc_assert (libcall_sp != libcall_stack);
|
||||
*--libcall_sp = XEXP (note, 0);
|
||||
}
|
||||
note = find_reg_note (insn, REG_RETVAL, NULL_RTX);
|
||||
if (note)
|
||||
libcall_sp++;
|
||||
note = find_reg_equal_equiv_note (insn);
|
||||
rtx note = find_reg_equal_equiv_note (insn);
|
||||
do
|
||||
{
|
||||
reg_use_count = 0;
|
||||
|
@ -3244,8 +3159,7 @@ local_cprop_pass (bool alter_jumps)
|
|||
for (reg_used = ®_use_table[0]; reg_use_count > 0;
|
||||
reg_used++, reg_use_count--)
|
||||
{
|
||||
if (do_local_cprop (reg_used->reg_rtx, insn, alter_jumps,
|
||||
libcall_sp))
|
||||
if (do_local_cprop (reg_used->reg_rtx, insn, alter_jumps))
|
||||
{
|
||||
changed = true;
|
||||
break;
|
||||
|
@ -3259,10 +3173,8 @@ local_cprop_pass (bool alter_jumps)
|
|||
cselib_process_insn (insn);
|
||||
}
|
||||
|
||||
/* Forget everything at the end of a basic block. Make sure we are
|
||||
not inside a libcall, they should never cross basic blocks. */
|
||||
/* Forget everything at the end of a basic block. */
|
||||
cselib_clear_table ();
|
||||
gcc_assert (libcall_sp == &libcall_stack[MAX_NESTED_LIBCALLS]);
|
||||
}
|
||||
|
||||
cselib_finish ();
|
||||
|
@ -6376,7 +6288,7 @@ remove_reachable_equiv_notes (basic_block bb, struct ls_expr *smexpr)
|
|||
static void
|
||||
replace_store_insn (rtx reg, rtx del, basic_block bb, struct ls_expr *smexpr)
|
||||
{
|
||||
rtx insn, mem, note, set, ptr, pair;
|
||||
rtx insn, mem, note, set, ptr;
|
||||
|
||||
mem = smexpr->pattern;
|
||||
insn = gen_move_insn (reg, SET_SRC (single_set (del)));
|
||||
|
@ -6388,25 +6300,9 @@ replace_store_insn (rtx reg, rtx del, basic_block bb, struct ls_expr *smexpr)
|
|||
break;
|
||||
}
|
||||
|
||||
/* Move the notes from the deleted insn to its replacement, and patch
|
||||
up the LIBCALL notes. */
|
||||
/* Move the notes from the deleted insn to its replacement. */
|
||||
REG_NOTES (insn) = REG_NOTES (del);
|
||||
|
||||
note = find_reg_note (insn, REG_RETVAL, NULL_RTX);
|
||||
if (note)
|
||||
{
|
||||
pair = XEXP (note, 0);
|
||||
note = find_reg_note (pair, REG_LIBCALL, NULL_RTX);
|
||||
XEXP (note, 0) = insn;
|
||||
}
|
||||
note = find_reg_note (insn, REG_LIBCALL, NULL_RTX);
|
||||
if (note)
|
||||
{
|
||||
pair = XEXP (note, 0);
|
||||
note = find_reg_note (pair, REG_RETVAL, NULL_RTX);
|
||||
XEXP (note, 0) = insn;
|
||||
}
|
||||
|
||||
/* Emit the insn AFTER all the notes are transferred.
|
||||
This is cheaper since we avoid df rescanning for the note change. */
|
||||
insn = emit_insn_after (insn, del);
|
||||
|
|
|
@ -18,9 +18,9 @@ along with GCC; see the file COPYING3. If not see
|
|||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* This implements the loop invariant motion pass. It is very simple
|
||||
(no calls, libcalls, etc.). This should be sufficient to cleanup things
|
||||
like address arithmetics -- other more complicated invariants should be
|
||||
eliminated on tree level either in tree-ssa-loop-im.c or in tree-ssa-pre.c.
|
||||
(no calls, no loads/stores, etc.). This should be sufficient to cleanup
|
||||
things like address arithmetics -- other more complicated invariants should
|
||||
be eliminated on GIMPLE either in tree-ssa-loop-im.c or in tree-ssa-pre.c.
|
||||
|
||||
We proceed loop by loop -- it is simpler than trying to handle things
|
||||
globally and should not lose much. First we inspect all sets inside loop
|
||||
|
@ -795,11 +795,6 @@ find_invariant_insn (rtx insn, bool always_reached, bool always_executed)
|
|||
bool simple = true;
|
||||
struct invariant *inv;
|
||||
|
||||
/* Until we get rid of LIBCALLS. */
|
||||
if (find_reg_note (insn, REG_RETVAL, NULL_RTX)
|
||||
|| find_reg_note (insn, REG_LIBCALL, NULL_RTX))
|
||||
return;
|
||||
|
||||
#ifdef HAVE_cc0
|
||||
/* We can't move a CC0 setter without the user. */
|
||||
if (sets_cc0_p (insn))
|
||||
|
|
|
@ -225,11 +225,9 @@ enum classify_move_insn
|
|||
{
|
||||
/* Not a simple move from one location to another. */
|
||||
NOT_SIMPLE_MOVE,
|
||||
/* A simple move from one pseudo-register to another with no
|
||||
REG_RETVAL note. */
|
||||
/* A simple move from one pseudo-register to another. */
|
||||
SIMPLE_PSEUDO_REG_MOVE,
|
||||
/* A simple move involving a non-pseudo-register, or from one
|
||||
pseudo-register to another with a REG_RETVAL note. */
|
||||
/* A simple move involving a non-pseudo-register. */
|
||||
SIMPLE_MOVE
|
||||
};
|
||||
|
||||
|
@ -304,10 +302,10 @@ find_decomposable_subregs (rtx *px, void *data)
|
|||
|
||||
If this is not a simple copy from one location to another,
|
||||
then we can not decompose this register. If this is a simple
|
||||
copy from one pseudo-register to another, with no REG_RETVAL
|
||||
note, and the mode is right, then we mark the register as
|
||||
decomposable. Otherwise we don't say anything about this
|
||||
register--it could be decomposed, but whether that would be
|
||||
copy from one pseudo-register to another, and the mode is right
|
||||
then we mark the register as decomposable.
|
||||
Otherwise we don't say anything about this register --
|
||||
it could be decomposed, but whether that would be
|
||||
profitable depends upon how it is used elsewhere.
|
||||
|
||||
We only set bits in the bitmap for multi-word
|
||||
|
@ -558,47 +556,6 @@ move_eh_region_note (rtx insn, rtx insns)
|
|||
}
|
||||
}
|
||||
|
||||
/* If there is a REG_LIBCALL note on OLD_START, move it to NEW_START,
|
||||
and link the corresponding REG_RETVAL note to NEW_START. */
|
||||
|
||||
static void
|
||||
move_libcall_note (rtx old_start, rtx new_start)
|
||||
{
|
||||
rtx note0, note1, end;
|
||||
|
||||
note0 = find_reg_note (old_start, REG_LIBCALL, NULL);
|
||||
if (note0 == NULL_RTX)
|
||||
return;
|
||||
|
||||
remove_note (old_start, note0);
|
||||
end = XEXP (note0, 0);
|
||||
note1 = find_reg_note (end, REG_RETVAL, NULL);
|
||||
|
||||
XEXP (note0, 1) = REG_NOTES (new_start);
|
||||
REG_NOTES (new_start) = note0;
|
||||
XEXP (note1, 0) = new_start;
|
||||
}
|
||||
|
||||
/* Remove any REG_RETVAL note, the corresponding REG_LIBCALL note, and
|
||||
any markers for a no-conflict block. We have decomposed the
|
||||
registers so the non-conflict is now obvious. */
|
||||
|
||||
static void
|
||||
remove_retval_note (rtx insn1)
|
||||
{
|
||||
rtx note0, insn0, note1;
|
||||
|
||||
note1 = find_reg_note (insn1, REG_RETVAL, NULL);
|
||||
if (note1 == NULL_RTX)
|
||||
return;
|
||||
|
||||
insn0 = XEXP (note1, 0);
|
||||
note0 = find_reg_note (insn0, REG_LIBCALL, NULL);
|
||||
|
||||
remove_note (insn0, note0);
|
||||
remove_note (insn1, note1);
|
||||
}
|
||||
|
||||
/* Resolve any decomposed registers which appear in register notes on
|
||||
INSN. */
|
||||
|
||||
|
@ -612,10 +569,7 @@ resolve_reg_notes (rtx insn)
|
|||
{
|
||||
int old_count = num_validated_changes ();
|
||||
if (for_each_rtx (&XEXP (note, 0), resolve_subreg_use, NULL))
|
||||
{
|
||||
remove_note (insn, note);
|
||||
remove_retval_note (insn);
|
||||
}
|
||||
remove_note (insn, note);
|
||||
else
|
||||
if (old_count != num_validated_changes ())
|
||||
df_notes_rescan (insn);
|
||||
|
@ -870,8 +824,6 @@ resolve_simple_move (rtx set, rtx insn)
|
|||
|
||||
emit_insn_before (insns, insn);
|
||||
|
||||
move_libcall_note (insn, insns);
|
||||
remove_retval_note (insn);
|
||||
delete_insn (insn);
|
||||
|
||||
return insns;
|
||||
|
@ -1156,34 +1108,8 @@ decompose_multiword_subregs (void)
|
|||
cmi = NOT_SIMPLE_MOVE;
|
||||
else
|
||||
{
|
||||
bool retval;
|
||||
|
||||
retval = find_reg_note (insn, REG_RETVAL, NULL_RTX) != NULL_RTX;
|
||||
|
||||
if (find_pseudo_copy (set) && !retval)
|
||||
if (find_pseudo_copy (set))
|
||||
cmi = SIMPLE_PSEUDO_REG_MOVE;
|
||||
else if (retval
|
||||
&& REG_P (SET_SRC (set))
|
||||
&& HARD_REGISTER_P (SET_SRC (set)))
|
||||
{
|
||||
rtx note;
|
||||
|
||||
/* We don't want to decompose an assignment which
|
||||
copies the value returned by a libcall to a
|
||||
pseudo-register. Doing that will lose the RETVAL
|
||||
note with no real gain. */
|
||||
cmi = NOT_SIMPLE_MOVE;
|
||||
|
||||
/* If we have a RETVAL note, there should be an
|
||||
EQUAL note. We don't want to decompose any
|
||||
registers which that EQUAL note refers to
|
||||
directly. If we do, we will no longer know the
|
||||
value of the libcall. */
|
||||
note = find_reg_equal_equiv_note (insn);
|
||||
if (note != NULL_RTX)
|
||||
for_each_rtx (&XEXP (note, 0), find_decomposable_subregs,
|
||||
&cmi);
|
||||
}
|
||||
else
|
||||
cmi = SIMPLE_MOVE;
|
||||
}
|
||||
|
@ -1277,8 +1203,6 @@ decompose_multiword_subregs (void)
|
|||
insn = resolve_simple_move (set, insn);
|
||||
if (insn != orig_insn)
|
||||
{
|
||||
remove_retval_note (insn);
|
||||
|
||||
recog_memoized (insn);
|
||||
extract_insn (insn);
|
||||
|
||||
|
@ -1319,8 +1243,6 @@ decompose_multiword_subregs (void)
|
|||
|
||||
i = apply_change_group ();
|
||||
gcc_assert (i);
|
||||
|
||||
remove_retval_note (insn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,23 +52,9 @@ REG_NOTE (EQUIV)
|
|||
|
||||
/* Like REG_EQUIV except that the destination is only momentarily
|
||||
equal to the specified rtx. Therefore, it cannot be used for
|
||||
substitution; but it can be used for cse. Together with a
|
||||
REG_RETVAL note, it means that the insn sets the full contents of
|
||||
the libcall value. */
|
||||
substitution; but it can be used for cse. */
|
||||
REG_NOTE (EQUAL)
|
||||
|
||||
/* This insn copies the return-value of a library call out of the hard
|
||||
reg for return values. This note is actually an INSN_LIST and it
|
||||
points to the first insn involved in setting up arguments for the
|
||||
call. flow.c uses this to delete the entire library call when its
|
||||
result is dead. */
|
||||
REG_NOTE (RETVAL)
|
||||
|
||||
/* The inverse of REG_RETVAL: it goes on the first insn of the library
|
||||
call and points at the one that has the REG_RETVAL. This note is
|
||||
also an INSN_LIST. */
|
||||
REG_NOTE (LIBCALL)
|
||||
|
||||
/* The register is always nonnegative during the containing loop.
|
||||
This is used in branches so that decrement and branch instructions
|
||||
terminating on zero can be matched. There must be an insn pattern
|
||||
|
|
|
@ -1219,9 +1219,8 @@ reload (rtx first, int global)
|
|||
notes. Delete all CLOBBER insns, except those that refer to the return
|
||||
value and the special mem:BLK CLOBBERs added to prevent the scheduler
|
||||
from misarranging variable-array code, and simplify (subreg (reg))
|
||||
operands. Also remove all REG_RETVAL and REG_LIBCALL notes since they
|
||||
are no longer useful or accurate. Strip and regenerate REG_INC notes
|
||||
that may have been moved around. */
|
||||
operands. Strip and regenerate REG_INC notes that may have been moved
|
||||
around. */
|
||||
|
||||
for (insn = first; insn; insn = NEXT_INSN (insn))
|
||||
if (INSN_P (insn))
|
||||
|
@ -1274,9 +1273,7 @@ reload (rtx first, int global)
|
|||
{
|
||||
if (REG_NOTE_KIND (*pnote) == REG_DEAD
|
||||
|| REG_NOTE_KIND (*pnote) == REG_UNUSED
|
||||
|| REG_NOTE_KIND (*pnote) == REG_INC
|
||||
|| REG_NOTE_KIND (*pnote) == REG_RETVAL
|
||||
|| REG_NOTE_KIND (*pnote) == REG_LIBCALL)
|
||||
|| REG_NOTE_KIND (*pnote) == REG_INC)
|
||||
*pnote = XEXP (*pnote, 1);
|
||||
else
|
||||
pnote = &XEXP (*pnote, 1);
|
||||
|
|
|
@ -1123,11 +1123,6 @@ noop_move_p (const_rtx insn)
|
|||
if (find_reg_note (insn, REG_EQUAL, NULL_RTX))
|
||||
return 0;
|
||||
|
||||
/* For now treat an insn with a REG_RETVAL note as a
|
||||
special insn which should not be considered a no-op. */
|
||||
if (find_reg_note (insn, REG_RETVAL, NULL_RTX))
|
||||
return 0;
|
||||
|
||||
if (GET_CODE (pat) == SET && set_noop_p (pat))
|
||||
return 1;
|
||||
|
||||
|
|
|
@ -2121,16 +2121,6 @@ sched_analyze_insn (struct deps *deps, rtx x, rtx insn)
|
|||
reg_pending_barrier = NOT_A_BARRIER;
|
||||
}
|
||||
|
||||
/* If we are currently in a libcall scheduling group, then mark the
|
||||
current insn as being in a scheduling group and that it can not
|
||||
be moved into a different basic block. */
|
||||
|
||||
if (deps->libcall_block_tail_insn)
|
||||
{
|
||||
SCHED_GROUP_P (insn) = 1;
|
||||
CANT_MOVE (insn) = 1;
|
||||
}
|
||||
|
||||
/* If a post-call group is still open, see if it should remain so.
|
||||
This insn must be a simple move of a hard reg to a pseudo or
|
||||
vice-versa.
|
||||
|
@ -2226,8 +2216,6 @@ sched_analyze (struct deps *deps, rtx head, rtx tail)
|
|||
}
|
||||
for (insn = head;; insn = NEXT_INSN (insn))
|
||||
{
|
||||
rtx link, end_seq, r0, set;
|
||||
|
||||
if (INSN_P (insn))
|
||||
{
|
||||
/* And initialize deps_lists. */
|
||||
|
@ -2326,45 +2314,6 @@ sched_analyze (struct deps *deps, rtx head, rtx tail)
|
|||
if (current_sched_info->use_cselib)
|
||||
cselib_process_insn (insn);
|
||||
|
||||
/* Now that we have completed handling INSN, check and see if it is
|
||||
a CLOBBER beginning a libcall block. If it is, record the
|
||||
end of the libcall sequence.
|
||||
|
||||
We want to schedule libcall blocks as a unit before reload. While
|
||||
this restricts scheduling, it preserves the meaning of a libcall
|
||||
block.
|
||||
|
||||
As a side effect, we may get better code due to decreased register
|
||||
pressure as well as less chance of a foreign insn appearing in
|
||||
a libcall block. */
|
||||
if (!reload_completed
|
||||
/* Note we may have nested libcall sequences. We only care about
|
||||
the outermost libcall sequence. */
|
||||
&& deps->libcall_block_tail_insn == 0
|
||||
/* The sequence must start with a clobber of a register. */
|
||||
&& NONJUMP_INSN_P (insn)
|
||||
&& GET_CODE (PATTERN (insn)) == CLOBBER
|
||||
&& (r0 = XEXP (PATTERN (insn), 0), REG_P (r0))
|
||||
&& REG_P (XEXP (PATTERN (insn), 0))
|
||||
/* The CLOBBER must also have a REG_LIBCALL note attached. */
|
||||
&& (link = find_reg_note (insn, REG_LIBCALL, NULL_RTX)) != 0
|
||||
&& (end_seq = XEXP (link, 0)) != 0
|
||||
/* The insn referenced by the REG_LIBCALL note must be a
|
||||
simple nop copy with the same destination as the register
|
||||
mentioned in the clobber. */
|
||||
&& (set = single_set (end_seq)) != 0
|
||||
&& SET_DEST (set) == r0 && SET_SRC (set) == r0
|
||||
/* And finally the insn referenced by the REG_LIBCALL must
|
||||
also contain a REG_EQUAL note and a REG_RETVAL note. */
|
||||
&& find_reg_note (end_seq, REG_EQUAL, NULL_RTX) != 0
|
||||
&& find_reg_note (end_seq, REG_RETVAL, NULL_RTX) != 0)
|
||||
deps->libcall_block_tail_insn = XEXP (link, 0);
|
||||
|
||||
/* If we have reached the end of a libcall block, then close the
|
||||
block. */
|
||||
if (deps->libcall_block_tail_insn == insn)
|
||||
deps->libcall_block_tail_insn = 0;
|
||||
|
||||
if (insn == tail)
|
||||
{
|
||||
if (current_sched_info->use_cselib)
|
||||
|
@ -2452,7 +2401,6 @@ init_deps (struct deps *deps)
|
|||
deps->last_function_call = 0;
|
||||
deps->sched_before_next_call = 0;
|
||||
deps->in_post_call_group_p = not_post_call;
|
||||
deps->libcall_block_tail_insn = 0;
|
||||
}
|
||||
|
||||
/* Free insn lists found in DEPS. */
|
||||
|
|
|
@ -307,12 +307,6 @@ struct deps
|
|||
the call. */
|
||||
enum { not_post_call, post_call, post_call_initial } in_post_call_group_p;
|
||||
|
||||
/* Set to the tail insn of the outermost libcall block.
|
||||
|
||||
When nonzero, we will mark each insn processed by sched_analyze_insn
|
||||
with SCHED_GROUP_P to ensure libcalls are scheduled as a unit. */
|
||||
rtx libcall_block_tail_insn;
|
||||
|
||||
/* The maximum register number for the following arrays. Before reload
|
||||
this is max_reg_num; after reload it is FIRST_PSEUDO_REGISTER. */
|
||||
int max_reg;
|
||||
|
|
12
gcc/see.c
12
gcc/see.c
|
@ -3489,12 +3489,6 @@ see_analyze_one_def (rtx insn, enum machine_mode *source_mode,
|
|||
if (!reg_set_between_p (source_register, PREV_INSN (prev_insn), insn))
|
||||
return NOT_RELEVANT;
|
||||
|
||||
if (find_reg_note (prev_insn, REG_LIBCALL, NULL_RTX))
|
||||
return NOT_RELEVANT;
|
||||
|
||||
if (find_reg_note (prev_insn, REG_RETVAL, NULL_RTX))
|
||||
return NOT_RELEVANT;
|
||||
|
||||
/* If we can't use copy_rtx on the reference it can't be a reference. */
|
||||
if (GET_CODE (PATTERN (prev_insn)) == PARALLEL
|
||||
&& asm_noperands (PATTERN (prev_insn)) >= 0)
|
||||
|
@ -3690,11 +3684,7 @@ see_update_relevancy (void)
|
|||
unsigned int uid = INSN_UID (insn);
|
||||
if (INSN_P (insn))
|
||||
{
|
||||
if (find_reg_note (insn, REG_LIBCALL, NULL_RTX)
|
||||
|| find_reg_note (insn, REG_RETVAL, NULL_RTX))
|
||||
et = NOT_RELEVANT;
|
||||
else
|
||||
et = RELEVANT_USE;
|
||||
et = RELEVANT_USE;
|
||||
|
||||
for (use_rec = DF_INSN_UID_USES (uid); *use_rec; use_rec++)
|
||||
{
|
||||
|
|
|
@ -152,9 +152,7 @@ union_defs (struct df_ref *use, struct web_entry *def_entry,
|
|||
eq_use_link++;
|
||||
}
|
||||
|
||||
/* Recognize trivial noop moves and attempt to keep them as noop.
|
||||
While most of noop moves should be removed, we still keep some
|
||||
of them at libcall boundaries and such. */
|
||||
/* Recognize trivial noop moves and attempt to keep them as noop. */
|
||||
|
||||
if (set
|
||||
&& SET_SRC (set) == DF_REF_REG (use)
|
||||
|
|
Loading…
Add table
Reference in a new issue