rtl.texi: Removed reference to REG_NO_CONFLICT notes.

2008-05-14  Kenneth Zadeck <zadeck@naturalbridge.com>

	* doc/rtl.texi: Removed reference to REG_NO_CONFLICT notes.
	* optabs.c (expand_binop, expand_absneg_bit, expand_unop,
	expand_copysign_bit, ): Change call to emit_no_conflict_block to
	emit_insn and remove unneeded code to construct extra args.
	(emit_no_conflict_block): Removed.
	* optabls.h: (emit_no_conflict_block): Removed.
	* cse.c (cse_extended_basic_block): Remove search for
	REG_NO_CONFLICT note.  
	* global.c: Removed incorrect comment added in revision 117.
	* expr.c (convert_move): Change call to emit_no_conflict_block to
	emit_insn.
	* recog.c: Change comments so that they do not mention
	REG_NO_CONFLICT.
	* local_alloc.c (combine_regs): Removed last parameter.
	(no_conflict_p): Removed.
	(block_alloc): Removed note, no_conflict_combined_regno and set
	local vars. Removed all code to process REG_NO_CONFLICT blocks.
	(combine_regs): Removed already_dead and code to look for
	REG_NO_CONFLICT notes.
	* lower_subreg (remove_retval_note): Removed code to look for
	REG_NO_CONFLICT block.
	(resolve_reg_notes): Removed REG_NO_CONFLICT case.
	(resolve_clobber): Remove code to process libcalls that have
	REG_NO_CONFLICT notes.
	* loop_invariant.c (find_invariant_insn): Removed REG_NO_CONFLICT
	case.
	* combine.c (can_combine_p, distribute_notes):  Removed REG_NO_CONFLICT
	case.
	* config/cris/cris.md (movdi pattern): Changed
	emit_no_conflict_block to emit_insns.
	* config/mn10300/mn10300.md (absdf2, negdf2 patterns): Ditto.
	* config/m68k/m68k.md (negdf2, negxf2, absdf2, absxf2 patterns):
	Ditto. 
	* reg-notes.def (NO_CONFLICT): Removed.

From-SVN: r135289
This commit is contained in:
Kenneth Zadeck 2008-05-14 12:24:43 +00:00 committed by Kenneth Zadeck
parent cc44abe6a5
commit d70dcf2945
16 changed files with 70 additions and 373 deletions

View File

@ -1,3 +1,40 @@
2008-05-14 Kenneth Zadeck <zadeck@naturalbridge.com>
* doc/rtl.texi: Removed reference to REG_NO_CONFLICT notes.
* optabs.c (expand_binop, expand_absneg_bit, expand_unop,
expand_copysign_bit, ): Change call to emit_no_conflict_block to
emit_insn and remove unneeded code to construct extra args.
(emit_no_conflict_block): Removed.
* optabls.h: (emit_no_conflict_block): Removed.
* cse.c (cse_extended_basic_block): Remove search for
REG_NO_CONFLICT note.
* global.c: Removed incorrect comment added in revision 117.
* expr.c (convert_move): Change call to emit_no_conflict_block to
emit_insn.
* recog.c: Change comments so that they do not mention
REG_NO_CONFLICT.
* local_alloc.c (combine_regs): Removed last parameter.
(no_conflict_p): Removed.
(block_alloc): Removed note, no_conflict_combined_regno and set
local vars. Removed all code to process REG_NO_CONFLICT blocks.
(combine_regs): Removed already_dead and code to look for
REG_NO_CONFLICT notes.
* lower_subreg (remove_retval_note): Removed code to look for
REG_NO_CONFLICT block.
(resolve_reg_notes): Removed REG_NO_CONFLICT case.
(resolve_clobber): Remove code to process libcalls that have
REG_NO_CONFLICT notes.
* loop_invariant.c (find_invariant_insn): Removed REG_NO_CONFLICT
case.
* combine.c (can_combine_p, distribute_notes): Removed REG_NO_CONFLICT
case.
* config/cris/cris.md (movdi pattern): Changed
emit_no_conflict_block to emit_insns.
* config/mn10300/mn10300.md (absdf2, negdf2 patterns): Ditto.
* config/m68k/m68k.md (negdf2, negxf2, absdf2, absxf2 patterns):
Ditto.
* reg-notes.def (NO_CONFLICT): Removed.
2008-05-14 David S. Miller <davem@davemloft.net>
* config/sparc/sparc.c (sparc_profile_hook): If

View File

@ -1653,7 +1653,7 @@ can_combine_p (rtx insn, rtx i3, rtx pred ATTRIBUTE_UNUSED, rtx succ,
/* Don't eliminate a store in the stack pointer. */
if (dest == stack_pointer_rtx
/* Don't combine with an insn that sets a register to itself if it has
a REG_EQUAL note. This may be part of a REG_NO_CONFLICT sequence. */
a REG_EQUAL note. This may be part of a LIBCALL sequence. */
|| (rtx_equal_p (src, dest) && find_reg_note (insn, REG_EQUAL, NULL_RTX))
/* Can't merge an ASM_OPERANDS. */
|| GET_CODE (src) == ASM_OPERANDS
@ -1696,10 +1696,6 @@ can_combine_p (rtx insn, rtx i3, rtx pred ATTRIBUTE_UNUSED, rtx succ,
&& use_crosses_set_p (src, DF_INSN_LUID (insn)))
|| (GET_CODE (src) == ASM_OPERANDS && MEM_VOLATILE_P (src))
|| GET_CODE (src) == UNSPEC_VOLATILE))
/* If there is a REG_NO_CONFLICT note for DEST in I3 or SUCC, we get
better register allocation by not doing the combine. */
|| find_reg_note (i3, REG_NO_CONFLICT, dest)
|| (succ && find_reg_note (succ, REG_NO_CONFLICT, dest))
/* Don't combine across a CALL_INSN, because that would possibly
change whether the life span of some REGs crosses calls or not,
and it is a pain to update that information.
@ -12460,7 +12456,6 @@ distribute_notes (rtx notes, rtx from_insn, rtx i3, rtx i2, rtx elim_i2,
break;
case REG_INC:
case REG_NO_CONFLICT:
/* These notes say something about how a register is used. They must
be present on any use of the register in I2 or I3. */
if (reg_mentioned_p (XEXP (note, 0), PATTERN (i3)))

View File

@ -547,9 +547,7 @@
gcc.c-torture/execute/961213-1.c shows that CSE2 gets confused by the
resulting subreg sets when using the construct from mcore (as of FSF
CVS, version -r 1.5), and it believes that the high part (the last one
emitted) is the final value. This construct from romp seems more
robust, especially considering the head comments from
emit_no_conflict_block. */
emitted) is the final value. */
if ((CONST_INT_P (operands[1]) || GET_CODE (operands[1]) == CONST_DOUBLE)
&& ! reload_completed
&& ! reload_in_progress)
@ -566,7 +564,7 @@
insns = get_insns ();
end_sequence ();
emit_no_conflict_block (insns, op0, op1, 0, op1);
emit_insn (insns);
DONE;
}
})

View File

@ -4092,7 +4092,7 @@
insns = get_insns ();
end_sequence ();
emit_no_conflict_block (insns, operands[0], operands[1], 0, 0);
emit_insn (insns);
DONE;
}
})
@ -4126,7 +4126,7 @@
insns = get_insns ();
end_sequence ();
emit_no_conflict_block (insns, operands[0], operands[1], 0, 0);
emit_insn (insns);
DONE;
}
})
@ -4245,7 +4245,7 @@
insns = get_insns ();
end_sequence ();
emit_no_conflict_block (insns, operands[0], operands[1], 0, 0);
emit_insn (insns);
DONE;
}
})
@ -4279,7 +4279,7 @@
insns = get_insns ();
end_sequence ();
emit_no_conflict_block (insns, operands[0], operands[1], 0, 0);
emit_insn (insns);
DONE;
}
})

View File

@ -2203,7 +2203,7 @@
insns = get_insns ();
end_sequence ();
emit_no_conflict_block (insns, operands[0], operands[1], 0, 0);
emit_insn (insns);
DONE;
}")
@ -2272,7 +2272,7 @@
insns = get_insns ();
end_sequence ();
emit_no_conflict_block (insns, operands[0], operands[1], 0, 0);
emit_insn (insns);
DONE;
}")

View File

@ -6059,8 +6059,6 @@ cse_extended_basic_block (struct cse_basic_block_data *ebb_data)
else
no_conflict = -1;
}
else if (find_reg_note (insn, REG_NO_CONFLICT, NULL_RTX))
no_conflict = 1;
}
cse_insn (insn, libcall_insn);

View File

@ -3641,23 +3641,6 @@ instructions, such as the m68k dbra, can be matched.
The @code{REG_NONNEG} note is added to insns only if the machine
description has a @samp{decrement_and_branch_until_zero} pattern.
@findex REG_NO_CONFLICT
@item REG_NO_CONFLICT
This insn does not cause a conflict between @var{op} and the item
being set by this insn even though it might appear that it does.
In other words, if the destination register and @var{op} could
otherwise be assigned the same register, this insn does not
prevent that assignment.
Insns with this note are usually part of a block that begins with a
@code{clobber} insn specifying a multi-word pseudo register (which will
be the output of the block), a group of insns that each set one word of
the value and have the @code{REG_NO_CONFLICT} note attached, and a final
insn that copies the output to itself with an attached @code{REG_EQUAL}
note giving the expression being computed. This block is encapsulated
with @code{REG_LIBCALL} and @code{REG_RETVAL} notes on the first and
last insns, respectively.
@findex REG_LABEL_OPERAND
@item REG_LABEL_OPERAND
This insn uses @var{op}, a @code{code_label} or a @code{note} of type

View File

@ -625,8 +625,7 @@ convert_move (rtx to, rtx from, int unsignedp)
insns = get_insns ();
end_sequence ();
emit_no_conflict_block (insns, to, from, NULL_RTX,
gen_rtx_fmt_e (equiv_code, to_mode, copy_rtx (from)));
emit_insn (insns);
return;
}

View File

@ -131,31 +131,6 @@ static int local_reg_live_length[FIRST_PSEUDO_REGISTER];
#define SET_REGBIT(TABLE, I, J) SET_HARD_REG_BIT (allocno[I].TABLE, J)
/* This is turned off because it doesn't work right for DImode.
(And it is only used for DImode, so the other cases are worthless.)
The problem is that it isn't true that there is NO possibility of conflict;
only that there is no conflict if the two pseudos get the exact same regs.
If they were allocated with a partial overlap, there would be a conflict.
We can't safely turn off the conflict unless we have another way to
prevent the partial overlap.
Idea: change hard_reg_conflicts so that instead of recording which
hard regs the allocno may not overlap, it records where the allocno
may not start. Change both where it is used and where it is updated.
Then there is a way to record that (reg:DI 108) may start at 10
but not at 9 or 11. There is still the question of how to record
this semi-conflict between two pseudos. */
#if 0
/* Reg pairs for which conflict after the current insn
is inhibited by a REG_NO_CONFLICT note.
If the table gets full, we ignore any other notes--that is conservative. */
#define NUM_NO_CONFLICT_PAIRS 4
/* Number of pairs in use in this insn. */
int n_no_conflict_pairs;
static struct { int allocno1, allocno2;}
no_conflict_pairs[NUM_NO_CONFLICT_PAIRS];
#endif /* 0 */
/* Return true if *LOC contains an asm. */
static int

View File

@ -305,7 +305,7 @@ static int qty_sugg_compare (int, int);
static int qty_sugg_compare_1 (const void *, const void *);
static int qty_compare (int, int);
static int qty_compare_1 (const void *, const void *);
static int combine_regs (rtx, rtx, int, int, rtx, int);
static int combine_regs (rtx, rtx, int, int, rtx);
static int reg_meets_class_p (int, enum reg_class);
static void update_qty_class (int, int);
static void reg_is_set (rtx, const_rtx, void *);
@ -315,7 +315,6 @@ static int find_free_reg (enum reg_class, enum machine_mode, int, int, int,
int, int);
static void mark_life (int, enum machine_mode, int);
static void post_mark_life (int, enum machine_mode, int, int, int);
static int no_conflict_p (rtx, rtx, rtx);
static int requires_inout (const char *);
/* Allocate a new quantity (new within current basic block)
@ -1271,12 +1270,11 @@ block_alloc (int b)
{
int i, q;
rtx insn;
rtx note, hard_reg;
rtx hard_reg;
int insn_number = 0;
int insn_count = 0;
int max_uid = get_max_uid ();
int *qty_order;
int no_conflict_combined_regno = -1;
struct df_ref ** def_rec;
/* Count the instructions in the basic block. */
@ -1326,7 +1324,7 @@ block_alloc (int b)
if (INSN_P (insn))
{
rtx link, set;
rtx link;
int win = 0;
rtx r0, r1 = NULL_RTX;
int combined_regno = -1;
@ -1433,63 +1431,13 @@ block_alloc (int b)
if (REG_P (r1) || GET_CODE (r1) == SUBREG)
win = combine_regs (r1, r0, may_save_copy,
insn_number, insn, 0);
insn_number, insn);
}
if (win)
break;
}
}
/* Recognize an insn sequence with an ultimate result
which can safely overlap one of the inputs.
The sequence begins with a CLOBBER of its result,
and ends with an insn that copies the result to itself
and has a REG_EQUAL note for an equivalent formula.
That note indicates what the inputs are.
The result and the input can overlap if each insn in
the sequence either doesn't mention the input
or has a REG_NO_CONFLICT note to inhibit the conflict.
We do the combining test at the CLOBBER so that the
destination register won't have had a quantity number
assigned, since that would prevent combining. */
if (optimize
&& GET_CODE (PATTERN (insn)) == CLOBBER
&& (r0 = XEXP (PATTERN (insn), 0),
REG_P (r0))
&& (link = find_reg_note (insn, REG_LIBCALL, NULL_RTX)) != 0
&& XEXP (link, 0) != 0
&& NONJUMP_INSN_P (XEXP (link, 0))
&& (set = single_set (XEXP (link, 0))) != 0
&& SET_DEST (set) == r0 && SET_SRC (set) == r0
&& (note = find_reg_note (XEXP (link, 0), REG_EQUAL,
NULL_RTX)) != 0)
{
if (r1 = XEXP (note, 0), REG_P (r1)
/* Check that we have such a sequence. */
&& no_conflict_p (insn, r0, r1))
win = combine_regs (r1, r0, 1, insn_number, insn, 1);
else if (GET_RTX_FORMAT (GET_CODE (XEXP (note, 0)))[0] == 'e'
&& (r1 = XEXP (XEXP (note, 0), 0),
REG_P (r1) || GET_CODE (r1) == SUBREG)
&& no_conflict_p (insn, r0, r1))
win = combine_regs (r1, r0, 0, insn_number, insn, 1);
/* Here we care if the operation to be computed is
commutative. */
else if (COMMUTATIVE_P (XEXP (note, 0))
&& (r1 = XEXP (XEXP (note, 0), 1),
(REG_P (r1) || GET_CODE (r1) == SUBREG))
&& no_conflict_p (insn, r0, r1))
win = combine_regs (r1, r0, 0, insn_number, insn, 1);
/* If we did combine something, show the register number
in question so that we know to ignore its death. */
if (win)
no_conflict_combined_regno = REGNO (r1);
}
/* If registers were just tied, set COMBINED_REGNO
to the number of the register used in this insn
that was tied to the register set in this insn.
@ -1502,16 +1450,12 @@ block_alloc (int b)
combined_regno = REGNO (r1);
}
/* Mark the death of everything that dies in this instruction,
except for anything that was just combined. */
/* Mark the death of everything that dies in this instruction. */
for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
if (REG_NOTE_KIND (link) == REG_DEAD
&& REG_P (XEXP (link, 0))
&& combined_regno != (int) REGNO (XEXP (link, 0))
&& (no_conflict_combined_regno != (int) REGNO (XEXP (link, 0))
|| ! find_reg_note (insn, REG_NO_CONFLICT,
XEXP (link, 0))))
&& combined_regno != (int) REGNO (XEXP (link, 0)))
wipe_dead_reg (XEXP (link, 0), 0);
/* Allocate qty numbers for all registers local to this block
@ -1530,14 +1474,6 @@ block_alloc (int b)
if (REG_NOTE_KIND (link) == REG_UNUSED
&& REG_P (XEXP (link, 0)))
wipe_dead_reg (XEXP (link, 0), 1);
/* If this is an insn that has a REG_RETVAL note pointing at a
CLOBBER insn, we have reached the end of a REG_NO_CONFLICT
block, so clear any register number that combined within it. */
if ((note = find_reg_note (insn, REG_RETVAL, NULL_RTX)) != 0
&& NONJUMP_INSN_P (XEXP (note, 0))
&& GET_CODE (PATTERN (XEXP (note, 0))) == CLOBBER)
no_conflict_combined_regno = -1;
}
/* Set the registers live after INSN_NUMBER. Note that we never
@ -1833,10 +1769,6 @@ qty_sugg_compare_1 (const void *q1p, const void *q2p)
If we really combined them, we could lose if the pseudo lives
across an insn that clobbers the hard reg (eg, movmem).
ALREADY_DEAD is nonzero if USEDREG is known to be dead even though
there is no REG_DEAD note on INSN. This occurs during the processing
of REG_NO_CONFLICT blocks.
MAY_SAVE_COPY is nonzero if this insn is simply copying USEDREG to
SETREG or if the input and output must share a register.
In that case, we record a hard reg suggestion in QTY_PHYS_COPY_SUGG.
@ -1845,7 +1777,7 @@ qty_sugg_compare_1 (const void *q1p, const void *q2p)
static int
combine_regs (rtx usedreg, rtx setreg, int may_save_copy, int insn_number,
rtx insn, int already_dead)
rtx insn)
{
int ureg, sreg;
int offset = 0;
@ -1935,11 +1867,6 @@ combine_regs (rtx usedreg, rtx setreg, int may_save_copy, int insn_number,
&& usize < qty[reg_qty[ureg]].size)
/* Can't combine if SREG is not a register we can allocate. */
|| (sreg >= FIRST_PSEUDO_REGISTER && reg_qty[sreg] == -1)
/* Don't combine with a pseudo mentioned in a REG_NO_CONFLICT note.
These have already been taken care of. This probably wouldn't
combine anyway, but don't take any chances. */
|| (ureg >= FIRST_PSEUDO_REGISTER
&& find_reg_note (insn, REG_NO_CONFLICT, usedreg))
/* Don't tie something to itself. In most cases it would make no
difference, but it would screw up if the reg being tied to itself
also dies in this insn. */
@ -2015,7 +1942,7 @@ combine_regs (rtx usedreg, rtx setreg, int may_save_copy, int insn_number,
if this is the last use of UREG, provided the classes they want
are compatible. */
if ((already_dead || find_regno_note (insn, REG_DEAD, ureg))
if (find_regno_note (insn, REG_DEAD, ureg)
&& reg_meets_class_p (sreg, qty[reg_qty[ureg]].min_class))
{
/* Add SREG to UREG's quantity. */
@ -2395,51 +2322,6 @@ post_mark_life (int regno, enum machine_mode mode, int life, int birth,
}
}
/* INSN is the CLOBBER insn that starts a REG_NO_NOCONFLICT block, R0
is the register being clobbered, and R1 is a register being used in
the equivalent expression.
If R1 dies in the block and has a REG_NO_CONFLICT note on every insn
in which it is used, return 1.
Otherwise, return 0. */
static int
no_conflict_p (rtx insn, rtx r0 ATTRIBUTE_UNUSED, rtx r1)
{
int ok = 0;
rtx note = find_reg_note (insn, REG_LIBCALL, NULL_RTX);
rtx p, last;
/* If R1 is a hard register, return 0 since we handle this case
when we scan the insns that actually use it. */
if (note == 0
|| (REG_P (r1) && REGNO (r1) < FIRST_PSEUDO_REGISTER)
|| (GET_CODE (r1) == SUBREG && REG_P (SUBREG_REG (r1))
&& REGNO (SUBREG_REG (r1)) < FIRST_PSEUDO_REGISTER))
return 0;
last = XEXP (note, 0);
for (p = NEXT_INSN (insn); p && p != last; p = NEXT_INSN (p))
if (INSN_P (p))
{
if (find_reg_note (p, REG_DEAD, r1))
ok = 1;
/* There must be a REG_NO_CONFLICT note on every insn, otherwise
some earlier optimization pass has inserted instructions into
the sequence, and it is not safe to perform this optimization.
Note that emit_no_conflict_block always ensures that this is
true when these sequences are created. */
if (! find_reg_note (p, REG_NO_CONFLICT, r1))
return 0;
}
return ok;
}
/* Return the number of alternatives for which the constraint string P
indicates that the operand must be equal to operand 0 and that no register
is acceptable. */

View File

@ -797,8 +797,7 @@ find_invariant_insn (rtx insn, bool always_reached, bool always_executed)
/* Until we get rid of LIBCALLS. */
if (find_reg_note (insn, REG_RETVAL, NULL_RTX)
|| find_reg_note (insn, REG_LIBCALL, NULL_RTX)
|| find_reg_note (insn, REG_NO_CONFLICT, NULL_RTX))
|| find_reg_note (insn, REG_LIBCALL, NULL_RTX))
return;
#ifdef HAVE_cc0

View File

@ -586,7 +586,7 @@ move_libcall_note (rtx old_start, rtx new_start)
static void
remove_retval_note (rtx insn1)
{
rtx note0, insn0, note1, insn;
rtx note0, insn0, note1;
note1 = find_reg_note (insn1, REG_RETVAL, NULL);
if (note1 == NULL_RTX)
@ -597,19 +597,6 @@ remove_retval_note (rtx insn1)
remove_note (insn0, note0);
remove_note (insn1, note1);
for (insn = insn0; insn != insn1; insn = NEXT_INSN (insn))
{
while (1)
{
rtx note;
note = find_reg_note (insn, REG_NO_CONFLICT, NULL);
if (note == NULL_RTX)
break;
remove_note (insn, note);
}
}
}
/* Resolve any decomposed registers which appear in register notes on
@ -642,7 +629,6 @@ resolve_reg_notes (rtx insn)
note = *pnote;
switch (REG_NOTE_KIND (note))
{
case REG_NO_CONFLICT:
case REG_DEAD:
case REG_UNUSED:
if (resolve_reg_p (XEXP (note, 0)))
@ -897,7 +883,7 @@ resolve_simple_move (rtx set, rtx insn)
static bool
resolve_clobber (rtx pat, rtx insn)
{
rtx reg, note;
rtx reg;
enum machine_mode orig_mode;
unsigned int words, i;
int ret;
@ -906,17 +892,6 @@ resolve_clobber (rtx pat, rtx insn)
if (!resolve_reg_p (reg) && !resolve_subreg_p (reg))
return false;
/* If this clobber has a REG_LIBCALL note, then it is the initial
clobber added by emit_no_conflict_block. We were able to
decompose the register, so we no longer need the clobber. */
note = find_reg_note (insn, REG_LIBCALL, NULL_RTX);
if (note != NULL_RTX)
{
remove_retval_note (XEXP (note, 0));
delete_insn (insn);
return true;
}
orig_mode = GET_MODE (reg);
words = GET_MODE_SIZE (orig_mode);
words = (words + UNITS_PER_WORD - 1) / UNITS_PER_WORD;

View File

@ -1151,8 +1151,7 @@ expand_doubleword_shift (enum machine_mode op1_mode, optab binoptab,
If we want to multiply two two-word values and have normal and widening
multiplies of single-word values, we can do this with three smaller
multiplications. Note that we do not make a REG_NO_CONFLICT block here
because we are not operating on one word at a time.
multiplications.
The multiplication proceeds as follows:
_______________________
@ -1750,7 +1749,7 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1,
else
equiv_value = 0;
emit_no_conflict_block (insns, target, op0, op1, equiv_value);
emit_insn (insns);
return target;
}
}
@ -1785,7 +1784,7 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1,
|| (shift_mask == BITS_PER_WORD - 1
&& double_shift_mask == BITS_PER_WORD * 2 - 1))
{
rtx insns, equiv_value;
rtx insns;
rtx into_target, outof_target;
rtx into_input, outof_input;
int left_shift, outof_word;
@ -1819,8 +1818,7 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1,
insns = get_insns ();
end_sequence ();
equiv_value = gen_rtx_fmt_ee (binoptab->code, mode, op0, op1);
emit_no_conflict_block (insns, target, op0, op1, equiv_value);
emit_insn (insns);
return target;
}
end_sequence ();
@ -1935,11 +1933,6 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1,
if (inter != 0)
{
/* One may be tempted to wrap the insns in a REG_NO_CONFLICT
block to help the register allocator a bit. But a multi-word
rotate will need all the input bits when setting the output
bits, so there clearly is a conflict between the input and
output registers. So we can't use a no-conflict block here. */
emit_insn (insns);
return target;
}
@ -3012,8 +3005,7 @@ expand_absneg_bit (enum rtx_code code, enum machine_mode mode,
insns = get_insns ();
end_sequence ();
temp = gen_rtx_fmt_e (code, mode, copy_rtx (op0));
emit_no_conflict_block (insns, target, op0, NULL_RTX, temp);
emit_insn (insns);
}
else
{
@ -3213,9 +3205,7 @@ expand_unop (enum machine_mode mode, optab unoptab, rtx op0, rtx target,
insns = get_insns ();
end_sequence ();
emit_no_conflict_block (insns, target, op0, NULL_RTX,
gen_rtx_fmt_e (unoptab->code, mode,
copy_rtx (op0)));
emit_insn (insns);
return target;
}
@ -3665,7 +3655,7 @@ expand_copysign_bit (enum machine_mode mode, rtx op0, rtx op1, rtx target,
insns = get_insns ();
end_sequence ();
emit_no_conflict_block (insns, target, op0, op1, NULL_RTX);
emit_insn (insns);
}
else
{
@ -3777,10 +3767,9 @@ struct no_conflict_data
bool must_stay;
};
/* Called via note_stores by emit_no_conflict_block and emit_libcall_block.
Set P->must_stay if the currently examined clobber / store has to stay
in the list of insns that constitute the actual no_conflict block /
libcall block. */
/* Called via note_stores by emit_libcall_block. Set P->must_stay if
the currently examined clobber / store has to stay in the list of
insns that constitute the actual libcall block. */
static void
no_conflict_move_test (rtx dest, const_rtx set, void *p0)
{
@ -3844,131 +3833,6 @@ maybe_encapsulate_block (rtx first, rtx last, rtx equiv)
}
}
/* Emit code to perform a series of operations on a multi-word quantity, one
word at a time.
Such a block is preceded by a CLOBBER of the output, consists of multiple
insns, each setting one word of the output, and followed by a SET copying
the output to itself.
Each of the insns setting words of the output receives a REG_NO_CONFLICT
note indicating that it doesn't conflict with the (also multi-word)
inputs. The entire block is surrounded by REG_LIBCALL and REG_RETVAL
notes.
INSNS is a block of code generated to perform the operation, not including
the CLOBBER and final copy. All insns that compute intermediate values
are first emitted, followed by the block as described above.
TARGET, OP0, and OP1 are the output and inputs of the operations,
respectively. OP1 may be zero for a unary operation.
EQUIV, if nonzero, is an expression to be placed into a REG_EQUAL note
on the last insn.
If TARGET is not a register, INSNS is simply emitted with no special
processing. Likewise if anything in INSNS is not an INSN or if
there is a libcall block inside INSNS.
The final insn emitted is returned. */
rtx
emit_no_conflict_block (rtx insns, rtx target, rtx op0, rtx op1, rtx equiv)
{
rtx prev, next, first, last, insn;
if (!REG_P (target) || reload_in_progress)
return emit_insn (insns);
else
for (insn = insns; insn; insn = NEXT_INSN (insn))
if (!NONJUMP_INSN_P (insn)
|| find_reg_note (insn, REG_LIBCALL, NULL_RTX))
return emit_insn (insns);
/* First emit all insns that do not store into words of the output and remove
these from the list. */
for (insn = insns; insn; insn = next)
{
rtx note;
struct no_conflict_data data;
next = NEXT_INSN (insn);
/* Some ports (cris) create a libcall regions at their own. We must
avoid any potential nesting of LIBCALLs. */
if ((note = find_reg_note (insn, REG_LIBCALL, NULL)) != NULL)
remove_note (insn, note);
if ((note = find_reg_note (insn, REG_RETVAL, NULL)) != NULL)
remove_note (insn, note);
data.target = target;
data.first = insns;
data.insn = insn;
data.must_stay = 0;
note_stores (PATTERN (insn), no_conflict_move_test, &data);
if (! data.must_stay)
{
if (PREV_INSN (insn))
NEXT_INSN (PREV_INSN (insn)) = next;
else
insns = next;
if (next)
PREV_INSN (next) = PREV_INSN (insn);
add_insn (insn);
}
}
prev = get_last_insn ();
/* Now write the CLOBBER of the output, followed by the setting of each
of the words, followed by the final copy. */
if (target != op0 && target != op1)
emit_insn (gen_rtx_CLOBBER (VOIDmode, target));
for (insn = insns; insn; insn = next)
{
next = NEXT_INSN (insn);
add_insn (insn);
if (op1 && REG_P (op1))
REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_NO_CONFLICT, op1,
REG_NOTES (insn));
if (op0 && REG_P (op0))
REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_NO_CONFLICT, op0,
REG_NOTES (insn));
}
if (optab_handler (mov_optab, GET_MODE (target))->insn_code
!= CODE_FOR_nothing)
{
last = emit_move_insn (target, target);
if (equiv)
set_unique_reg_note (last, REG_EQUAL, equiv);
}
else
{
last = get_last_insn ();
/* Remove any existing REG_EQUAL note from "last", or else it will
be mistaken for a note referring to the full contents of the
alleged libcall value when found together with the REG_RETVAL
note added below. An existing note can come from an insn
expansion at "last". */
remove_note (last, find_reg_note (last, REG_EQUAL, NULL_RTX));
}
if (prev == 0)
first = get_insns ();
else
first = NEXT_INSN (prev);
maybe_encapsulate_block (first, last, equiv);
return last;
}
/* Emit code to make a call to a constant function or a library call.

View File

@ -710,10 +710,6 @@ extern void emit_unop_insn (int, rtx, rtx, enum rtx_code);
REG_LIBCALL_ID notes to all insns in block. */
extern void maybe_encapsulate_block (rtx, rtx, rtx);
/* Emit code to perform a series of operations on a multi-word quantity, one
word at a time. */
extern rtx emit_no_conflict_block (rtx, rtx, rtx, rtx, rtx);
/* Emit one rtl insn to compare two rtx's. */
extern void emit_cmp_insn (rtx, rtx, enum rtx_code, rtx, enum machine_mode,
int);

View File

@ -2646,7 +2646,7 @@ split_all_insns (void)
/* Don't split no-op move insns. These should silently
disappear later in final. Splitting such insns would
break the code that handles REG_NO_CONFLICT blocks. */
break the code that handles LIBCALL blocks. */
if (set && set_noop_p (set))
{
/* Nops get in the way while scheduling, so delete them
@ -2701,7 +2701,7 @@ split_all_insns_noflow (void)
{
/* Don't split no-op move insns. These should silently
disappear later in final. Splitting such insns would
break the code that handles REG_NO_CONFLICT blocks. */
break the code that handles LIBCALL blocks. */
rtx set = single_set (insn);
if (set && set_noop_p (set))
{

View File

@ -76,10 +76,6 @@ REG_NOTE (LIBCALL)
will never be added to any instructions. */
REG_NOTE (NONNEG)
/* There is no conflict *after this insn* between the register in the
note and the destination of this insn. */
REG_NOTE (NO_CONFLICT)
/* Identifies a register set in this insn and never used. */
REG_NOTE (UNUSED)