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:
parent
cc44abe6a5
commit
d70dcf2945
@ -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
|
||||
|
@ -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)))
|
||||
|
@ -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;
|
||||
}
|
||||
})
|
||||
|
@ -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;
|
||||
}
|
||||
})
|
||||
|
@ -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;
|
||||
}")
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
25
gcc/global.c
25
gcc/global.c
@ -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
|
||||
|
@ -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. */
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
156
gcc/optabs.c
156
gcc/optabs.c
@ -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.
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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))
|
||||
{
|
||||
|
@ -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)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user