+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.
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).
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));
|| (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))
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++;
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
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 *);
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);
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. */
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. */
};
static void
-cse_insn (rtx insn, rtx libcall_insn)
+cse_insn (rtx insn)
{
rtx x = PATTERN (insn);
int i;
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)
{
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. */
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
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
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
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. */
{
basic_block bb;
rtx insn;
- rtx libcall_insn = NULL_RTX;
- int no_conflict = 0;
bb = ebb_data->path[path_entry].bb;
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
}
}
- /* 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. */
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.
{
int *counts;
rtx insn, prev;
- int in_libcall = 0, dead_libcall = 0;
int ndead = 0;
timevar_push (TV_DELETE_TRIVIALLY_DEAD);
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. */
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)
/* 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;
el->next = next;
el->loc = loc;
el->setting_insn = cselib_current_insn;
- el->in_libcall = cselib_current_insn_in_libcall;
return el;
}
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. */
&& 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;
}
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
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. */
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. */
}
-/* 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. */
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;
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. */
}
-/* 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. */
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);
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
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
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;
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;
}
rtx
emit_copy_of_insn_after (rtx insn, rtx after)
{
- rtx new;
- rtx note1, note2, link;
+ rtx new, link;
switch (GET_CODE (insn))
{
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;
}
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");
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 *);
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 *);
\f
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. */
{
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.
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);
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;
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
}
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 ",
}
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,
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. */
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;
for (reg_used = ®_use_table[0]; reg_use_count > 0;
reg_used++, reg_use_count--)
{
- if (do_local_cprop (reg_used->reg_rtx, insn, alter_jumps,
- libcall_sp))
+ if (do_local_cprop (reg_used->reg_rtx, insn, alter_jumps))
{
changed = true;
break;
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 ();
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)));
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);
<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
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))
{
/* 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
};
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
}
}
-/* 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. */
{
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);
emit_insn_before (insns, insn);
- move_libcall_note (insn, insns);
- remove_retval_note (insn);
delete_insn (insn);
return insns;
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;
}
insn = resolve_simple_move (set, insn);
if (insn != orig_insn)
{
- remove_retval_note (insn);
-
recog_memoized (insn);
extract_insn (insn);
i = apply_change_group ();
gcc_assert (i);
-
- remove_retval_note (insn);
}
}
}
/* 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
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))
{
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);
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;
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.
}
for (insn = head;; insn = NEXT_INSN (insn))
{
- rtx link, end_seq, r0, set;
-
if (INSN_P (insn))
{
/* And initialize deps_lists. */
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)
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. */
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;
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)
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++)
{
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)