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:
Steven Bosscher 2008-06-17 05:57:04 +00:00
parent e989f2d107
commit 4a8cae8370
20 changed files with 109 additions and 833 deletions

View File

@ -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.

View File

@ -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).

View File

@ -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
View File

@ -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)

View File

@ -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. */

View File

@ -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
View File

@ -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);

View File

@ -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

View File

@ -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;
}

View File

@ -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");

View File

@ -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 = &reg_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);

View File

@ -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))

View File

@ -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);
}
}
}

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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. */

View File

@ -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;

View File

@ -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++)
{

View File

@ -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)