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
|
@ -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>
|
2008-06-16 Eric B. Weddington <eric.weddington@atmel.com>
|
||||||
|
|
||||||
* config/avr/avr.c (avr_mcu_t): Add atmega32c1.
|
* 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 ();
|
before_call = get_last_insn ();
|
||||||
|
|
||||||
target = expand_call (exp, target, target == const0_rtx);
|
return 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Expand a call to the builtin binary math functions (pow and atan2).
|
/* Expand a call to the builtin binary math functions (pow and atan2).
|
||||||
|
|
|
@ -882,23 +882,6 @@ delete_noop_moves (void)
|
||||||
next = NEXT_INSN (insn);
|
next = NEXT_INSN (insn);
|
||||||
if (INSN_P (insn) && noop_move_p (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)
|
if (dump_file)
|
||||||
fprintf (dump_file, "deleting noop move %d\n", INSN_UID (insn));
|
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))
|
|| (succ && FIND_REG_INC_NOTE (succ, dest))
|
||||||
/* Don't substitute into a non-local goto, this confuses CFG. */
|
/* Don't substitute into a non-local goto, this confuses CFG. */
|
||||||
|| (JUMP_P (i3) && find_reg_note (i3, REG_NON_LOCAL_GOTO, NULL_RTX))
|
|| (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. */
|
/* Make sure that DEST is not used after SUCC but before I3. */
|
||||||
|| (succ && ! all_adjacent
|
|| (succ && ! all_adjacent
|
||||||
&& reg_used_between_p (dest, succ, i3))
|
&& 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)
|
if (cant_combine_insn_p (i3)
|
||||||
|| cant_combine_insn_p (i2)
|
|| cant_combine_insn_p (i2)
|
||||||
|| (i1 && cant_combine_insn_p (i1))
|
|| (i1 && cant_combine_insn_p (i1))
|
||||||
|| likely_spilled_retval_p (i3)
|
|| 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
|
|
||||||
)
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
combine_attempts++;
|
combine_attempts++;
|
||||||
|
@ -12547,48 +12513,6 @@ distribute_notes (rtx notes, rtx from_insn, rtx i3, rtx i2, rtx elim_i2,
|
||||||
to simply delete it. */
|
to simply delete it. */
|
||||||
break;
|
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:
|
case REG_DEAD:
|
||||||
/* If we replaced the right hand side of FROM_INSN with a
|
/* If we replaced the right hand side of FROM_INSN with a
|
||||||
REG_EQUAL note, the original use of the dying register
|
REG_EQUAL note, the original use of the dying register
|
||||||
|
|
162
gcc/cse.c
162
gcc/cse.c
|
@ -584,7 +584,7 @@ static rtx equiv_constant (rtx);
|
||||||
static void record_jump_equiv (rtx, bool);
|
static void record_jump_equiv (rtx, bool);
|
||||||
static void record_jump_cond (enum rtx_code, enum machine_mode, rtx, rtx,
|
static void record_jump_cond (enum rtx_code, enum machine_mode, rtx, rtx,
|
||||||
int);
|
int);
|
||||||
static void cse_insn (rtx, rtx);
|
static void cse_insn (rtx);
|
||||||
static void cse_prescan_path (struct cse_basic_block_data *);
|
static void cse_prescan_path (struct cse_basic_block_data *);
|
||||||
static void invalidate_from_clobbers (rtx);
|
static void invalidate_from_clobbers (rtx);
|
||||||
static rtx cse_process_notes (rtx, rtx, bool *);
|
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 void flush_hash_table (void);
|
||||||
static bool insn_live_p (rtx, int *);
|
static bool insn_live_p (rtx, int *);
|
||||||
static bool set_live_p (rtx, 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 int cse_change_cc_mode (rtx *, void *);
|
||||||
static void cse_change_cc_mode_insn (rtx, rtx);
|
static void cse_change_cc_mode_insn (rtx, rtx);
|
||||||
static void cse_change_cc_mode_insns (rtx, 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
|
First simplify sources and addresses of all assignments
|
||||||
in the instruction, using previously-computed equivalents values.
|
in the instruction, using previously-computed equivalents values.
|
||||||
Then install the new sources and destinations in the table
|
Then install the new sources and destinations in the table
|
||||||
of available values.
|
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. */
|
|
||||||
|
|
||||||
/* Data on one SET contained in the instruction. */
|
/* Data on one SET contained in the instruction. */
|
||||||
|
|
||||||
|
@ -3962,8 +3957,6 @@ struct set
|
||||||
ENUM_BITFIELD(machine_mode) mode : 8;
|
ENUM_BITFIELD(machine_mode) mode : 8;
|
||||||
/* A constant equivalent for SET_SRC, if any. */
|
/* A constant equivalent for SET_SRC, if any. */
|
||||||
rtx src_const;
|
rtx src_const;
|
||||||
/* Original SET_SRC value used for libcall notes. */
|
|
||||||
rtx orig_src;
|
|
||||||
/* Hash value of constant equivalent for SET_SRC. */
|
/* Hash value of constant equivalent for SET_SRC. */
|
||||||
unsigned src_const_hash;
|
unsigned src_const_hash;
|
||||||
/* Table entry for constant equivalent for SET_SRC, if any. */
|
/* Table entry for constant equivalent for SET_SRC, if any. */
|
||||||
|
@ -3973,7 +3966,7 @@ struct set
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cse_insn (rtx insn, rtx libcall_insn)
|
cse_insn (rtx insn)
|
||||||
{
|
{
|
||||||
rtx x = PATTERN (insn);
|
rtx x = PATTERN (insn);
|
||||||
int i;
|
int i;
|
||||||
|
@ -4170,7 +4163,6 @@ cse_insn (rtx insn, rtx libcall_insn)
|
||||||
rtx src = SET_SRC (sets[i].rtl);
|
rtx src = SET_SRC (sets[i].rtl);
|
||||||
rtx new = canon_reg (src, insn);
|
rtx new = canon_reg (src, insn);
|
||||||
|
|
||||||
sets[i].orig_src = src;
|
|
||||||
validate_change (insn, &SET_SRC (sets[i].rtl), new, 1);
|
validate_change (insn, &SET_SRC (sets[i].rtl), new, 1);
|
||||||
|
|
||||||
if (GET_CODE (dest) == ZERO_EXTRACT)
|
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);
|
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
|
/* The result of apply_change_group can be ignored; see
|
||||||
canon_reg. */
|
canon_reg. */
|
||||||
|
|
||||||
|
@ -5174,11 +5150,6 @@ cse_insn (rtx insn, rtx libcall_insn)
|
||||||
classp = sets[i].src_const_elt;
|
classp = sets[i].src_const_elt;
|
||||||
|
|
||||||
if (sets[i].src_elt == 0)
|
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;
|
||||||
|
|
||||||
|
@ -5194,9 +5165,6 @@ cse_insn (rtx insn, rtx libcall_insn)
|
||||||
elt->in_memory = sets[i].src_in_memory;
|
elt->in_memory = sets[i].src_in_memory;
|
||||||
sets[i].src_elt = classp = elt;
|
sets[i].src_elt = classp = elt;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
sets[i].src_elt = classp;
|
|
||||||
}
|
|
||||||
if (sets[i].src_const && sets[i].src_const_elt == 0
|
if (sets[i].src_const && sets[i].src_const_elt == 0
|
||||||
&& src != sets[i].src_const
|
&& src != sets[i].src_const
|
||||||
&& ! rtx_equal_p (sets[i].src_const, src))
|
&& ! rtx_equal_p (sets[i].src_const, src))
|
||||||
|
@ -5392,11 +5360,6 @@ cse_insn (rtx insn, rtx libcall_insn)
|
||||||
size of it, and can't be sure that other BLKmode values
|
size of it, and can't be sure that other BLKmode values
|
||||||
have the same or smaller size. */
|
have the same or smaller size. */
|
||||||
|| GET_MODE (dest) == BLKmode
|
|| 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
|
/* If we didn't put a REG_EQUAL value or a source into the hash
|
||||||
table, there is no point is recording DEST. */
|
table, there is no point is recording DEST. */
|
||||||
|| sets[i].src_elt == 0
|
|| 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
|
then be used in the sequel and we may be changing a two-operand insn
|
||||||
into a three-operand insn.
|
into a three-operand insn.
|
||||||
|
|
||||||
Also do not do this if we are operating on a copy of 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. */
|
|
||||||
|
|
||||||
if (n_sets == 1 && sets[0].rtl && REG_P (SET_DEST (sets[0].rtl))
|
if (n_sets == 1 && sets[0].rtl && REG_P (SET_DEST (sets[0].rtl))
|
||||||
&& NEXT_INSN (PREV_INSN (insn)) == insn
|
&& 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)));
|
int src_q = REG_QTY (REGNO (SET_SRC (sets[0].rtl)));
|
||||||
struct qty_table_elem *src_ent = &qty_table[src_q];
|
struct qty_table_elem *src_ent = &qty_table[src_q];
|
||||||
|
|
||||||
if ((src_ent->first_reg == REGNO (SET_DEST (sets[0].rtl)))
|
if (src_ent->first_reg == REGNO (SET_DEST (sets[0].rtl)))
|
||||||
&& ! find_reg_note (insn, REG_RETVAL, NULL_RTX))
|
|
||||||
{
|
{
|
||||||
/* Scan for the previous nonnote insn, but stop at a basic
|
/* Scan for the previous nonnote insn, but stop at a basic
|
||||||
block boundary. */
|
block boundary. */
|
||||||
|
@ -5993,8 +5951,6 @@ cse_extended_basic_block (struct cse_basic_block_data *ebb_data)
|
||||||
{
|
{
|
||||||
basic_block bb;
|
basic_block bb;
|
||||||
rtx insn;
|
rtx insn;
|
||||||
rtx libcall_insn = NULL_RTX;
|
|
||||||
int no_conflict = 0;
|
|
||||||
|
|
||||||
bb = ebb_data->path[path_entry].bb;
|
bb = ebb_data->path[path_entry].bb;
|
||||||
|
|
||||||
|
@ -6043,38 +5999,7 @@ cse_extended_basic_block (struct cse_basic_block_data *ebb_data)
|
||||||
df_notes_rescan (insn);
|
df_notes_rescan (insn);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Track when we are inside in LIBCALL block. Inside such
|
cse_insn (insn);
|
||||||
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;
|
|
||||||
|
|
||||||
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,
|
/* If we haven't already found an insn where we added a LABEL_REF,
|
||||||
check this one. */
|
check this one. */
|
||||||
|
@ -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
|
/* With non-call exceptions, we are not always able to update
|
||||||
the CFG properly inside cse_insn. So clean up possibly
|
the CFG properly inside cse_insn. So clean up possibly
|
||||||
redundant EH edges here. */
|
redundant EH edges here. */
|
||||||
|
@ -6479,57 +6401,6 @@ insn_live_p (rtx insn, int *counts)
|
||||||
return true;
|
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
|
/* 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.
|
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;
|
int *counts;
|
||||||
rtx insn, prev;
|
rtx insn, prev;
|
||||||
int in_libcall = 0, dead_libcall = 0;
|
|
||||||
int ndead = 0;
|
int ndead = 0;
|
||||||
|
|
||||||
timevar_push (TV_DELETE_TRIVIALLY_DEAD);
|
timevar_push (TV_DELETE_TRIVIALLY_DEAD);
|
||||||
|
@ -6568,20 +6438,6 @@ delete_trivially_dead_insns (rtx insns, int nreg)
|
||||||
if (!INSN_P (insn))
|
if (!INSN_P (insn))
|
||||||
continue;
|
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
|
/* If this is a dead insn, delete it and show registers in it aren't
|
||||||
|
@ -6593,12 +6449,6 @@ delete_trivially_dead_insns (rtx insns, int nreg)
|
||||||
delete_insn_and_edges (insn);
|
delete_insn_and_edges (insn);
|
||||||
ndead++;
|
ndead++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (in_libcall && find_reg_note (insn, REG_LIBCALL, NULL_RTX))
|
|
||||||
{
|
|
||||||
in_libcall = 0;
|
|
||||||
dead_libcall = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dump_file && ndead)
|
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.
|
/* 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. */
|
It is used in new_elt_loc_list to set SETTING_INSN. */
|
||||||
static rtx cselib_current_insn;
|
static rtx cselib_current_insn;
|
||||||
static bool cselib_current_insn_in_libcall;
|
|
||||||
|
|
||||||
/* Every new unknown value gets a unique number. */
|
/* Every new unknown value gets a unique number. */
|
||||||
static unsigned int next_unknown_value;
|
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->next = next;
|
||||||
el->loc = loc;
|
el->loc = loc;
|
||||||
el->setting_insn = cselib_current_insn;
|
el->setting_insn = cselib_current_insn;
|
||||||
el->in_libcall = cselib_current_insn_in_libcall;
|
|
||||||
return el;
|
return el;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1655,8 +1653,6 @@ cselib_process_insn (rtx insn)
|
||||||
int i;
|
int i;
|
||||||
rtx x;
|
rtx x;
|
||||||
|
|
||||||
if (find_reg_note (insn, REG_LIBCALL, NULL))
|
|
||||||
cselib_current_insn_in_libcall = true;
|
|
||||||
cselib_current_insn = insn;
|
cselib_current_insn = insn;
|
||||||
|
|
||||||
/* Forget everything at a CODE_LABEL, a volatile asm, or a setjmp. */
|
/* 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
|
&& GET_CODE (PATTERN (insn)) == ASM_OPERANDS
|
||||||
&& MEM_VOLATILE_P (PATTERN (insn))))
|
&& MEM_VOLATILE_P (PATTERN (insn))))
|
||||||
{
|
{
|
||||||
if (find_reg_note (insn, REG_RETVAL, NULL))
|
|
||||||
cselib_current_insn_in_libcall = false;
|
|
||||||
cselib_clear_table ();
|
cselib_clear_table ();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! INSN_P (insn))
|
if (! INSN_P (insn))
|
||||||
{
|
{
|
||||||
if (find_reg_note (insn, REG_RETVAL, NULL))
|
|
||||||
cselib_current_insn_in_libcall = false;
|
|
||||||
cselib_current_insn = 0;
|
cselib_current_insn = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1719,8 +1711,6 @@ cselib_process_insn (rtx insn)
|
||||||
if (GET_CODE (XEXP (x, 0)) == CLOBBER)
|
if (GET_CODE (XEXP (x, 0)) == CLOBBER)
|
||||||
cselib_invalidate_rtx (XEXP (XEXP (x, 0), 0));
|
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;
|
cselib_current_insn = 0;
|
||||||
|
|
||||||
if (n_useless_values > MAX_USELESS_VALUES
|
if (n_useless_values > MAX_USELESS_VALUES
|
||||||
|
@ -1769,7 +1759,6 @@ cselib_init (bool record_memory)
|
||||||
n_used_regs = 0;
|
n_used_regs = 0;
|
||||||
cselib_hash_table = htab_create (31, get_value_hash,
|
cselib_hash_table = htab_create (31, get_value_hash,
|
||||||
entry_and_rtx_equal_p, NULL);
|
entry_and_rtx_equal_p, NULL);
|
||||||
cselib_current_insn_in_libcall = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Called when the current user is done with cselib. */
|
/* Called when the current user is done with cselib. */
|
||||||
|
|
|
@ -47,8 +47,6 @@ struct elt_loc_list GTY(())
|
||||||
rtx loc;
|
rtx loc;
|
||||||
/* The insn that made the equivalence. */
|
/* The insn that made the equivalence. */
|
||||||
rtx setting_insn;
|
rtx setting_insn;
|
||||||
/* True when setting insn is inside libcall. */
|
|
||||||
bool in_libcall;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* A list of cselib_val structures. */
|
/* 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
|
/* Delete all REG_EQUAL notes of the registers INSN writes, to prevent
|
||||||
bad dangling REG_EQUAL notes. */
|
bad dangling REG_EQUAL notes. */
|
||||||
|
|
||||||
|
@ -316,29 +260,10 @@ delete_unmarked_insns (void)
|
||||||
FOR_BB_INSNS_SAFE (bb, insn, next)
|
FOR_BB_INSNS_SAFE (bb, insn, next)
|
||||||
if (INSN_P (insn))
|
if (INSN_P (insn))
|
||||||
{
|
{
|
||||||
rtx note = find_reg_note (insn, REG_LIBCALL, NULL_RTX);
|
|
||||||
|
|
||||||
/* Always delete no-op moves. */
|
/* Always delete no-op moves. */
|
||||||
if (noop_move_p (insn))
|
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. */
|
/* Otherwise rely only on the DCE algorithm. */
|
||||||
else if (marked_insn_p (insn))
|
else if (marked_insn_p (insn))
|
||||||
continue;
|
continue;
|
||||||
|
@ -353,41 +278,6 @@ delete_unmarked_insns (void)
|
||||||
for the destination regs in order to avoid dangling notes. */
|
for the destination regs in order to avoid dangling notes. */
|
||||||
delete_corresponding_reg_eq_notes (insn);
|
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
|
/* If a pure or const call is deleted, this may make the cfg
|
||||||
have unreachable blocks. We rememeber this and call
|
have unreachable blocks. We rememeber this and call
|
||||||
delete_unreachable_blocks at the end. */
|
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
|
/* Go through the instructions and mark those whose necessity is not
|
||||||
dependent on inter-instruction information. Make sure all other
|
dependent on inter-instruction information. Make sure all other
|
||||||
instructions are not marked. */
|
instructions are not marked. */
|
||||||
|
@ -458,10 +311,7 @@ prescan_insns_for_dce (bool fast)
|
||||||
FOR_BB_INSNS_SAFE (bb, insn, next)
|
FOR_BB_INSNS_SAFE (bb, insn, next)
|
||||||
if (INSN_P (insn))
|
if (INSN_P (insn))
|
||||||
{
|
{
|
||||||
rtx note = find_reg_note (insn, REG_LIBCALL, NULL_RTX);
|
if (deletable_insn_p (insn, fast))
|
||||||
if (note)
|
|
||||||
next = prescan_libcall_for_dce (insn, note, fast);
|
|
||||||
else if (deletable_insn_p (insn, fast))
|
|
||||||
mark_nonreg_stores (PATTERN (insn), insn, fast);
|
mark_nonreg_stores (PATTERN (insn), insn, fast);
|
||||||
else
|
else
|
||||||
mark_insn (insn, fast);
|
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.
|
the inverse note pointing back to the first insn.
|
||||||
|
|
||||||
@table @code
|
@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_SETTER
|
||||||
@findex REG_CC_USER
|
@findex REG_CC_USER
|
||||||
@item REG_CC_SETTER
|
@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
|
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
|
is used in place of the actual insn pattern. This is done in cases where
|
||||||
the pattern is either complex or misleading.
|
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
|
@end table
|
||||||
|
|
||||||
For convenience, the machine mode in an @code{insn_list} or
|
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 before = PREV_INSN (trial);
|
||||||
rtx after = NEXT_INSN (trial);
|
rtx after = NEXT_INSN (trial);
|
||||||
int has_barrier = 0;
|
int has_barrier = 0;
|
||||||
rtx tem, note_retval, note_libcall;
|
rtx note, seq, tem;
|
||||||
rtx note, seq;
|
|
||||||
int probability;
|
int probability;
|
||||||
rtx insn_last, insn;
|
rtx insn_last, insn;
|
||||||
int njumps = 0;
|
int njumps = 0;
|
||||||
|
@ -3296,30 +3295,6 @@ try_split (rtx pat, rtx trial, int last)
|
||||||
break;
|
break;
|
||||||
#endif
|
#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:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -5501,8 +5476,7 @@ init_emit_once (int line_numbers)
|
||||||
rtx
|
rtx
|
||||||
emit_copy_of_insn_after (rtx insn, rtx after)
|
emit_copy_of_insn_after (rtx insn, rtx after)
|
||||||
{
|
{
|
||||||
rtx new;
|
rtx new, link;
|
||||||
rtx note1, note2, link;
|
|
||||||
|
|
||||||
switch (GET_CODE (insn))
|
switch (GET_CODE (insn))
|
||||||
{
|
{
|
||||||
|
@ -5556,15 +5530,6 @@ emit_copy_of_insn_after (rtx insn, rtx after)
|
||||||
XEXP (link, 0), REG_NOTES (new));
|
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);
|
INSN_CODE (new) = INSN_CODE (insn);
|
||||||
return new;
|
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);
|
cancel_changes (0);
|
||||||
|
|
||||||
/* Can also record a simplified value in a REG_EQUAL note,
|
/* Can also record a simplified value in a REG_EQUAL note,
|
||||||
making a new one if one does not already exist.
|
making a new one if one does not already exist. */
|
||||||
Don't do this if the insn has a REG_RETVAL note, because the
|
if (set_reg_equal)
|
||||||
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))
|
|
||||||
{
|
{
|
||||||
if (dump_file)
|
if (dump_file)
|
||||||
fprintf (dump_file, " Setting REG_EQUAL note\n");
|
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_one_set (int, rtx);
|
||||||
static void record_set_info (rtx, const_rtx, void *);
|
static void record_set_info (rtx, const_rtx, void *);
|
||||||
static void compute_sets (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_set (rtx, rtx, struct hash_table *);
|
||||||
static void hash_scan_clobber (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 *);
|
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 void free_modify_mem_tables (void);
|
||||||
static rtx gcse_emit_move_after (rtx, rtx, rtx);
|
static rtx gcse_emit_move_after (rtx, rtx, rtx);
|
||||||
static void local_cprop_find_used_regs (rtx *, void *);
|
static void local_cprop_find_used_regs (rtx *, void *);
|
||||||
static bool do_local_cprop (rtx, rtx, bool, rtx*);
|
static bool do_local_cprop (rtx, rtx, bool);
|
||||||
static bool adjust_libcall_notes (rtx, rtx, rtx, rtx*);
|
|
||||||
static void local_cprop_pass (bool);
|
static void local_cprop_pass (bool);
|
||||||
static bool is_too_expensive (const char *);
|
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.
|
are also in the PARALLEL. Later.
|
||||||
|
|
||||||
If SET_P is nonzero, this is for the assignment hash table,
|
If SET_P is nonzero, this is for the assignment hash table,
|
||||||
otherwise it is for the expression 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. */
|
|
||||||
|
|
||||||
static void
|
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);
|
rtx pat = PATTERN (insn);
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (in_libcall_block)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* Pick out the sets of INSN and for other forms of instructions record
|
/* Pick out the sets of INSN and for other forms of instructions record
|
||||||
what's been modified. */
|
what's been modified. */
|
||||||
|
|
||||||
|
@ -2063,7 +2057,6 @@ compute_hash_table_work (struct hash_table *table)
|
||||||
{
|
{
|
||||||
rtx insn;
|
rtx insn;
|
||||||
unsigned int regno;
|
unsigned int regno;
|
||||||
int in_libcall_block;
|
|
||||||
|
|
||||||
/* First pass over the instructions records information used to
|
/* First pass over the instructions records information used to
|
||||||
determine when registers and memory are first and last set.
|
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);
|
BB_HEAD (current_bb), table);
|
||||||
|
|
||||||
/* The next pass builds the hash table. */
|
/* The next pass builds the hash table. */
|
||||||
in_libcall_block = 0;
|
|
||||||
FOR_BB_INSNS (current_bb, insn)
|
FOR_BB_INSNS (current_bb, insn)
|
||||||
if (INSN_P (insn))
|
if (INSN_P (insn))
|
||||||
{
|
hash_scan_insn (insn, table);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
free (reg_avail_info);
|
free (reg_avail_info);
|
||||||
|
@ -3077,11 +3061,11 @@ local_cprop_find_used_regs (rtx *xptr, void *data)
|
||||||
find_used_regs (xptr, data);
|
find_used_regs (xptr, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* LIBCALL_SP is a zero-terminated array of insns at the end of a libcall;
|
/* Try to perform local const/copy propagation on X in INSN.
|
||||||
their REG_EQUAL notes need updating. */
|
If ALTER_JUMPS is false, changing jump insns is not allowed. */
|
||||||
|
|
||||||
static bool
|
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;
|
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 this_rtx = l->loc;
|
||||||
rtx note;
|
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))
|
if (gcse_constant_p (this_rtx))
|
||||||
newcnst = this_rtx;
|
newcnst = this_rtx;
|
||||||
if (REG_P (this_rtx) && REGNO (this_rtx) >= FIRST_PSEUDO_REGISTER
|
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 (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)
|
if (dump_file != NULL)
|
||||||
{
|
{
|
||||||
fprintf (dump_file, "LOCAL CONST-PROP: Replacing reg %d in ",
|
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))
|
else if (newreg && newreg != x && try_replace_reg (x, newreg, insn))
|
||||||
{
|
{
|
||||||
adjust_libcall_notes (x, newreg, insn, libcall_sp);
|
|
||||||
if (dump_file != NULL)
|
if (dump_file != NULL)
|
||||||
{
|
{
|
||||||
fprintf (dump_file,
|
fprintf (dump_file,
|
||||||
|
@ -3159,47 +3128,6 @@ do_local_cprop (rtx x, rtx insn, bool alter_jumps, rtx *libcall_sp)
|
||||||
return false;
|
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).
|
/* Do local const/copy propagation (i.e. within each basic block).
|
||||||
If ALTER_JUMPS is true, allow propagating into jump insns, which
|
If ALTER_JUMPS is true, allow propagating into jump insns, which
|
||||||
could modify the CFG. */
|
could modify the CFG. */
|
||||||
|
@ -3210,29 +3138,16 @@ local_cprop_pass (bool alter_jumps)
|
||||||
basic_block bb;
|
basic_block bb;
|
||||||
rtx insn;
|
rtx insn;
|
||||||
struct reg_use *reg_used;
|
struct reg_use *reg_used;
|
||||||
rtx libcall_stack[MAX_NESTED_LIBCALLS + 1], *libcall_sp;
|
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
|
|
||||||
cselib_init (false);
|
cselib_init (false);
|
||||||
libcall_sp = &libcall_stack[MAX_NESTED_LIBCALLS];
|
|
||||||
*libcall_sp = 0;
|
|
||||||
FOR_EACH_BB (bb)
|
FOR_EACH_BB (bb)
|
||||||
{
|
{
|
||||||
FOR_BB_INSNS (bb, insn)
|
FOR_BB_INSNS (bb, insn)
|
||||||
{
|
{
|
||||||
if (INSN_P (insn))
|
if (INSN_P (insn))
|
||||||
{
|
{
|
||||||
rtx note = find_reg_note (insn, REG_LIBCALL, NULL_RTX);
|
rtx note = find_reg_equal_equiv_note (insn);
|
||||||
|
|
||||||
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);
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
reg_use_count = 0;
|
reg_use_count = 0;
|
||||||
|
@ -3244,8 +3159,7 @@ local_cprop_pass (bool alter_jumps)
|
||||||
for (reg_used = ®_use_table[0]; reg_use_count > 0;
|
for (reg_used = ®_use_table[0]; reg_use_count > 0;
|
||||||
reg_used++, reg_use_count--)
|
reg_used++, reg_use_count--)
|
||||||
{
|
{
|
||||||
if (do_local_cprop (reg_used->reg_rtx, insn, alter_jumps,
|
if (do_local_cprop (reg_used->reg_rtx, insn, alter_jumps))
|
||||||
libcall_sp))
|
|
||||||
{
|
{
|
||||||
changed = true;
|
changed = true;
|
||||||
break;
|
break;
|
||||||
|
@ -3259,10 +3173,8 @@ local_cprop_pass (bool alter_jumps)
|
||||||
cselib_process_insn (insn);
|
cselib_process_insn (insn);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Forget everything at the end of a basic block. Make sure we are
|
/* Forget everything at the end of a basic block. */
|
||||||
not inside a libcall, they should never cross basic blocks. */
|
|
||||||
cselib_clear_table ();
|
cselib_clear_table ();
|
||||||
gcc_assert (libcall_sp == &libcall_stack[MAX_NESTED_LIBCALLS]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cselib_finish ();
|
cselib_finish ();
|
||||||
|
@ -6376,7 +6288,7 @@ remove_reachable_equiv_notes (basic_block bb, struct ls_expr *smexpr)
|
||||||
static void
|
static void
|
||||||
replace_store_insn (rtx reg, rtx del, basic_block bb, struct ls_expr *smexpr)
|
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;
|
mem = smexpr->pattern;
|
||||||
insn = gen_move_insn (reg, SET_SRC (single_set (del)));
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Move the notes from the deleted insn to its replacement, and patch
|
/* Move the notes from the deleted insn to its replacement. */
|
||||||
up the LIBCALL notes. */
|
|
||||||
REG_NOTES (insn) = REG_NOTES (del);
|
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.
|
/* Emit the insn AFTER all the notes are transferred.
|
||||||
This is cheaper since we avoid df rescanning for the note change. */
|
This is cheaper since we avoid df rescanning for the note change. */
|
||||||
insn = emit_insn_after (insn, del);
|
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/>. */
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
/* This implements the loop invariant motion pass. It is very simple
|
/* This implements the loop invariant motion pass. It is very simple
|
||||||
(no calls, libcalls, etc.). This should be sufficient to cleanup things
|
(no calls, no loads/stores, etc.). This should be sufficient to cleanup
|
||||||
like address arithmetics -- other more complicated invariants should be
|
things like address arithmetics -- other more complicated invariants should
|
||||||
eliminated on tree level either in tree-ssa-loop-im.c or in tree-ssa-pre.c.
|
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
|
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
|
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;
|
bool simple = true;
|
||||||
struct invariant *inv;
|
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
|
#ifdef HAVE_cc0
|
||||||
/* We can't move a CC0 setter without the user. */
|
/* We can't move a CC0 setter without the user. */
|
||||||
if (sets_cc0_p (insn))
|
if (sets_cc0_p (insn))
|
||||||
|
|
|
@ -225,11 +225,9 @@ enum classify_move_insn
|
||||||
{
|
{
|
||||||
/* Not a simple move from one location to another. */
|
/* Not a simple move from one location to another. */
|
||||||
NOT_SIMPLE_MOVE,
|
NOT_SIMPLE_MOVE,
|
||||||
/* A simple move from one pseudo-register to another with no
|
/* A simple move from one pseudo-register to another. */
|
||||||
REG_RETVAL note. */
|
|
||||||
SIMPLE_PSEUDO_REG_MOVE,
|
SIMPLE_PSEUDO_REG_MOVE,
|
||||||
/* A simple move involving a non-pseudo-register, or from one
|
/* A simple move involving a non-pseudo-register. */
|
||||||
pseudo-register to another with a REG_RETVAL note. */
|
|
||||||
SIMPLE_MOVE
|
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,
|
If this is not a simple copy from one location to another,
|
||||||
then we can not decompose this register. If this is a simple
|
then we can not decompose this register. If this is a simple
|
||||||
copy from one pseudo-register to another, with no REG_RETVAL
|
copy from one pseudo-register to another, and the mode is right
|
||||||
note, and the mode is right, then we mark the register as
|
then we mark the register as decomposable.
|
||||||
decomposable. Otherwise we don't say anything about this
|
Otherwise we don't say anything about this register --
|
||||||
register--it could be decomposed, but whether that would be
|
it could be decomposed, but whether that would be
|
||||||
profitable depends upon how it is used elsewhere.
|
profitable depends upon how it is used elsewhere.
|
||||||
|
|
||||||
We only set bits in the bitmap for multi-word
|
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
|
/* Resolve any decomposed registers which appear in register notes on
|
||||||
INSN. */
|
INSN. */
|
||||||
|
|
||||||
|
@ -612,10 +569,7 @@ resolve_reg_notes (rtx insn)
|
||||||
{
|
{
|
||||||
int old_count = num_validated_changes ();
|
int old_count = num_validated_changes ();
|
||||||
if (for_each_rtx (&XEXP (note, 0), resolve_subreg_use, NULL))
|
if (for_each_rtx (&XEXP (note, 0), resolve_subreg_use, NULL))
|
||||||
{
|
|
||||||
remove_note (insn, note);
|
remove_note (insn, note);
|
||||||
remove_retval_note (insn);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
if (old_count != num_validated_changes ())
|
if (old_count != num_validated_changes ())
|
||||||
df_notes_rescan (insn);
|
df_notes_rescan (insn);
|
||||||
|
@ -870,8 +824,6 @@ resolve_simple_move (rtx set, rtx insn)
|
||||||
|
|
||||||
emit_insn_before (insns, insn);
|
emit_insn_before (insns, insn);
|
||||||
|
|
||||||
move_libcall_note (insn, insns);
|
|
||||||
remove_retval_note (insn);
|
|
||||||
delete_insn (insn);
|
delete_insn (insn);
|
||||||
|
|
||||||
return insns;
|
return insns;
|
||||||
|
@ -1156,34 +1108,8 @@ decompose_multiword_subregs (void)
|
||||||
cmi = NOT_SIMPLE_MOVE;
|
cmi = NOT_SIMPLE_MOVE;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bool retval;
|
if (find_pseudo_copy (set))
|
||||||
|
|
||||||
retval = find_reg_note (insn, REG_RETVAL, NULL_RTX) != NULL_RTX;
|
|
||||||
|
|
||||||
if (find_pseudo_copy (set) && !retval)
|
|
||||||
cmi = SIMPLE_PSEUDO_REG_MOVE;
|
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
|
else
|
||||||
cmi = SIMPLE_MOVE;
|
cmi = SIMPLE_MOVE;
|
||||||
}
|
}
|
||||||
|
@ -1277,8 +1203,6 @@ decompose_multiword_subregs (void)
|
||||||
insn = resolve_simple_move (set, insn);
|
insn = resolve_simple_move (set, insn);
|
||||||
if (insn != orig_insn)
|
if (insn != orig_insn)
|
||||||
{
|
{
|
||||||
remove_retval_note (insn);
|
|
||||||
|
|
||||||
recog_memoized (insn);
|
recog_memoized (insn);
|
||||||
extract_insn (insn);
|
extract_insn (insn);
|
||||||
|
|
||||||
|
@ -1319,8 +1243,6 @@ decompose_multiword_subregs (void)
|
||||||
|
|
||||||
i = apply_change_group ();
|
i = apply_change_group ();
|
||||||
gcc_assert (i);
|
gcc_assert (i);
|
||||||
|
|
||||||
remove_retval_note (insn);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,23 +52,9 @@ REG_NOTE (EQUIV)
|
||||||
|
|
||||||
/* Like REG_EQUIV except that the destination is only momentarily
|
/* Like REG_EQUIV except that the destination is only momentarily
|
||||||
equal to the specified rtx. Therefore, it cannot be used for
|
equal to the specified rtx. Therefore, it cannot be used for
|
||||||
substitution; but it can be used for cse. Together with a
|
substitution; but it can be used for cse. */
|
||||||
REG_RETVAL note, it means that the insn sets the full contents of
|
|
||||||
the libcall value. */
|
|
||||||
REG_NOTE (EQUAL)
|
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.
|
/* The register is always nonnegative during the containing loop.
|
||||||
This is used in branches so that decrement and branch instructions
|
This is used in branches so that decrement and branch instructions
|
||||||
terminating on zero can be matched. There must be an insn pattern
|
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
|
notes. Delete all CLOBBER insns, except those that refer to the return
|
||||||
value and the special mem:BLK CLOBBERs added to prevent the scheduler
|
value and the special mem:BLK CLOBBERs added to prevent the scheduler
|
||||||
from misarranging variable-array code, and simplify (subreg (reg))
|
from misarranging variable-array code, and simplify (subreg (reg))
|
||||||
operands. Also remove all REG_RETVAL and REG_LIBCALL notes since they
|
operands. Strip and regenerate REG_INC notes that may have been moved
|
||||||
are no longer useful or accurate. Strip and regenerate REG_INC notes
|
around. */
|
||||||
that may have been moved around. */
|
|
||||||
|
|
||||||
for (insn = first; insn; insn = NEXT_INSN (insn))
|
for (insn = first; insn; insn = NEXT_INSN (insn))
|
||||||
if (INSN_P (insn))
|
if (INSN_P (insn))
|
||||||
|
@ -1274,9 +1273,7 @@ reload (rtx first, int global)
|
||||||
{
|
{
|
||||||
if (REG_NOTE_KIND (*pnote) == REG_DEAD
|
if (REG_NOTE_KIND (*pnote) == REG_DEAD
|
||||||
|| REG_NOTE_KIND (*pnote) == REG_UNUSED
|
|| REG_NOTE_KIND (*pnote) == REG_UNUSED
|
||||||
|| REG_NOTE_KIND (*pnote) == REG_INC
|
|| REG_NOTE_KIND (*pnote) == REG_INC)
|
||||||
|| REG_NOTE_KIND (*pnote) == REG_RETVAL
|
|
||||||
|| REG_NOTE_KIND (*pnote) == REG_LIBCALL)
|
|
||||||
*pnote = XEXP (*pnote, 1);
|
*pnote = XEXP (*pnote, 1);
|
||||||
else
|
else
|
||||||
pnote = &XEXP (*pnote, 1);
|
pnote = &XEXP (*pnote, 1);
|
||||||
|
|
|
@ -1123,11 +1123,6 @@ noop_move_p (const_rtx insn)
|
||||||
if (find_reg_note (insn, REG_EQUAL, NULL_RTX))
|
if (find_reg_note (insn, REG_EQUAL, NULL_RTX))
|
||||||
return 0;
|
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))
|
if (GET_CODE (pat) == SET && set_noop_p (pat))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
|
|
@ -2121,16 +2121,6 @@ sched_analyze_insn (struct deps *deps, rtx x, rtx insn)
|
||||||
reg_pending_barrier = NOT_A_BARRIER;
|
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.
|
/* 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
|
This insn must be a simple move of a hard reg to a pseudo or
|
||||||
vice-versa.
|
vice-versa.
|
||||||
|
@ -2226,8 +2216,6 @@ sched_analyze (struct deps *deps, rtx head, rtx tail)
|
||||||
}
|
}
|
||||||
for (insn = head;; insn = NEXT_INSN (insn))
|
for (insn = head;; insn = NEXT_INSN (insn))
|
||||||
{
|
{
|
||||||
rtx link, end_seq, r0, set;
|
|
||||||
|
|
||||||
if (INSN_P (insn))
|
if (INSN_P (insn))
|
||||||
{
|
{
|
||||||
/* And initialize deps_lists. */
|
/* And initialize deps_lists. */
|
||||||
|
@ -2326,45 +2314,6 @@ sched_analyze (struct deps *deps, rtx head, rtx tail)
|
||||||
if (current_sched_info->use_cselib)
|
if (current_sched_info->use_cselib)
|
||||||
cselib_process_insn (insn);
|
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 (insn == tail)
|
||||||
{
|
{
|
||||||
if (current_sched_info->use_cselib)
|
if (current_sched_info->use_cselib)
|
||||||
|
@ -2452,7 +2401,6 @@ init_deps (struct deps *deps)
|
||||||
deps->last_function_call = 0;
|
deps->last_function_call = 0;
|
||||||
deps->sched_before_next_call = 0;
|
deps->sched_before_next_call = 0;
|
||||||
deps->in_post_call_group_p = not_post_call;
|
deps->in_post_call_group_p = not_post_call;
|
||||||
deps->libcall_block_tail_insn = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Free insn lists found in DEPS. */
|
/* Free insn lists found in DEPS. */
|
||||||
|
|
|
@ -307,12 +307,6 @@ struct deps
|
||||||
the call. */
|
the call. */
|
||||||
enum { not_post_call, post_call, post_call_initial } in_post_call_group_p;
|
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
|
/* The maximum register number for the following arrays. Before reload
|
||||||
this is max_reg_num; after reload it is FIRST_PSEUDO_REGISTER. */
|
this is max_reg_num; after reload it is FIRST_PSEUDO_REGISTER. */
|
||||||
int max_reg;
|
int max_reg;
|
||||||
|
|
10
gcc/see.c
10
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))
|
if (!reg_set_between_p (source_register, PREV_INSN (prev_insn), insn))
|
||||||
return NOT_RELEVANT;
|
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 we can't use copy_rtx on the reference it can't be a reference. */
|
||||||
if (GET_CODE (PATTERN (prev_insn)) == PARALLEL
|
if (GET_CODE (PATTERN (prev_insn)) == PARALLEL
|
||||||
&& asm_noperands (PATTERN (prev_insn)) >= 0)
|
&& asm_noperands (PATTERN (prev_insn)) >= 0)
|
||||||
|
@ -3690,10 +3684,6 @@ see_update_relevancy (void)
|
||||||
unsigned int uid = INSN_UID (insn);
|
unsigned int uid = INSN_UID (insn);
|
||||||
if (INSN_P (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++)
|
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++;
|
eq_use_link++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Recognize trivial noop moves and attempt to keep them as noop.
|
/* 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. */
|
|
||||||
|
|
||||||
if (set
|
if (set
|
||||||
&& SET_SRC (set) == DF_REF_REG (use)
|
&& SET_SRC (set) == DF_REF_REG (use)
|
||||||
|
|
Loading…
Reference in New Issue