Commit 83d48fad by Vladimir Makarov Committed by Vladimir Makarov

re PR middle-end/37535 (gcc/libgcc2.c:404: internal compiler error: Floating point exception)

2008-09-25  Vladimir Makarov  <vmakarov@redhat.com>

	PR middle-end/37535

	* ira-lives.c (mark_reg_live, mark_reg_dead): New functions.
	(mark_ref_live, mark_ref_dead): Use them.
	(def_conflicts_with_inputs_p): Remove.
	(mark_early_clobbers): New function.
	(process_bb_node_lives): Call preprocess_constraints and
	mark_early_clobbers.

	* doc/rtx.texi (clobber): Change how RA deals with clobbers.

From-SVN: r140679
parent 3fcac00f
2008-09-25 Vladimir Makarov <vmakarov@redhat.com> 2008-09-25 Vladimir Makarov <vmakarov@redhat.com>
PR middle-end/37535
* ira-lives.c (mark_reg_live, mark_reg_dead): New functions.
(mark_ref_live, mark_ref_dead): Use them.
(def_conflicts_with_inputs_p): Remove.
(mark_early_clobbers): New function.
(process_bb_node_lives): Call preprocess_constraints and
mark_early_clobbers.
* doc/rtl.texi (clobber): Change how RA deals with clobbers.
2008-09-25 Vladimir Makarov <vmakarov@redhat.com>
PR middle-end/37448 PR middle-end/37448
* ira-int.h (IRA_ALLOCNO_TEMP): Rename to ALLOCNO_TEMP. * ira-int.h (IRA_ALLOCNO_TEMP): Rename to ALLOCNO_TEMP.
......
...@@ -2930,12 +2930,13 @@ constituent instructions might not. ...@@ -2930,12 +2930,13 @@ constituent instructions might not.
When a @code{clobber} expression for a register appears inside a When a @code{clobber} expression for a register appears inside a
@code{parallel} with other side effects, the register allocator @code{parallel} with other side effects, the register allocator
guarantees that the register is unoccupied both before and after that guarantees that the register is unoccupied both before and after that
insn. However, the reload phase may allocate a register used for one of insn if the @samp{&} constraint is specified for at least one
the inputs unless the @samp{&} constraint is specified for the selected alternative (@pxref{Modifiers}) of the clobber. However, the reload
alternative (@pxref{Modifiers}). You can clobber either a specific hard phase may allocate a register used for one of the inputs unless the
register, a pseudo register, or a @code{scratch} expression; in the @samp{&} constraint is specified for the selected alternative. You
latter two cases, GCC will allocate a hard register that is available can clobber either a specific hard register, a pseudo register, or a
there for use as a temporary. @code{scratch} expression; in the latter two cases, GCC will allocate
a hard register that is available there for use as a temporary.
For instructions that require a temporary register, you should use For instructions that require a temporary register, you should use
@code{scratch} instead of a pseudo-register because this will allow the @code{scratch} instead of a pseudo-register because this will allow the
......
...@@ -209,20 +209,15 @@ clear_allocno_live (ira_allocno_t a) ...@@ -209,20 +209,15 @@ clear_allocno_live (ira_allocno_t a)
sparseset_clear_bit (allocnos_live, ALLOCNO_NUM (a)); sparseset_clear_bit (allocnos_live, ALLOCNO_NUM (a));
} }
/* Mark the register referenced by use or def REF as live /* Mark the register REG as live. Store a 1 in hard_regs_live or
Store a 1 in hard_regs_live or allocnos_live for this register or allocnos_live for this register or the corresponding allocno,
the corresponding allocno, record how many consecutive hardware record how many consecutive hardware registers it actually
registers it actually needs. */ needs. */
static void static void
mark_ref_live (struct df_ref *ref) mark_reg_live (rtx reg)
{ {
rtx reg;
int regno; int regno;
reg = DF_REF_REG (ref);
if (GET_CODE (reg) == SUBREG)
reg = SUBREG_REG (reg);
gcc_assert (REG_P (reg)); gcc_assert (REG_P (reg));
regno = REGNO (reg); regno = REGNO (reg);
...@@ -269,32 +264,25 @@ mark_ref_live (struct df_ref *ref) ...@@ -269,32 +264,25 @@ mark_ref_live (struct df_ref *ref)
} }
} }
/* Return true if the definition described by DEF conflicts with the /* Mark the register referenced by use or def REF as live. */
instruction's inputs. */ static void
static bool mark_ref_live (struct df_ref *ref)
def_conflicts_with_inputs_p (struct df_ref *def)
{ {
/* Conservatively assume that the condition is true for all clobbers. */ rtx reg;
return DF_REF_FLAGS_IS_SET (def, DF_REF_MUST_CLOBBER);
reg = DF_REF_REG (ref);
if (GET_CODE (reg) == SUBREG)
reg = SUBREG_REG (reg);
mark_reg_live (reg);
} }
/* Mark the register referenced by definition DEF as dead, if the /* Mark the register REG as dead. Store a 0 in hard_regs_live or
definition is a total one. Store a 0 in hard_regs_live or
allocnos_live for the register. */ allocnos_live for the register. */
static void static void
mark_ref_dead (struct df_ref *def) mark_reg_dead (rtx reg)
{ {
unsigned int i;
rtx reg;
int regno; int regno;
if (DF_REF_FLAGS_IS_SET (def, DF_REF_PARTIAL)
|| DF_REF_FLAGS_IS_SET (def, DF_REF_CONDITIONAL))
return;
reg = DF_REF_REG (def);
if (GET_CODE (reg) == SUBREG)
reg = SUBREG_REG (reg);
gcc_assert (REG_P (reg)); gcc_assert (REG_P (reg));
regno = REGNO (reg); regno = REGNO (reg);
...@@ -312,6 +300,7 @@ mark_ref_dead (struct df_ref *def) ...@@ -312,6 +300,7 @@ mark_ref_dead (struct df_ref *def)
} }
else if (! TEST_HARD_REG_BIT (ira_no_alloc_regs, regno)) else if (! TEST_HARD_REG_BIT (ira_no_alloc_regs, regno))
{ {
unsigned int i;
int last = regno + hard_regno_nregs[regno][GET_MODE (reg)]; int last = regno + hard_regno_nregs[regno][GET_MODE (reg)];
enum reg_class cover_class; enum reg_class cover_class;
...@@ -343,6 +332,71 @@ mark_ref_dead (struct df_ref *def) ...@@ -343,6 +332,71 @@ mark_ref_dead (struct df_ref *def)
} }
} }
/* Mark the register referenced by definition DEF as dead, if the
definition is a total one. */
static void
mark_ref_dead (struct df_ref *def)
{
rtx reg;
if (DF_REF_FLAGS_IS_SET (def, DF_REF_PARTIAL)
|| DF_REF_FLAGS_IS_SET (def, DF_REF_CONDITIONAL))
return;
reg = DF_REF_REG (def);
if (GET_CODE (reg) == SUBREG)
reg = SUBREG_REG (reg);
mark_reg_dead (reg);
}
/* Mark early clobber registers of the current INSN as live (if
LIVE_P) or dead. Return true if there are such registers. */
static bool
mark_early_clobbers (rtx insn, bool live_p)
{
int alt;
int def;
struct df_ref **def_rec;
bool set_p = false;
bool asm_p = asm_noperands (PATTERN (insn)) >= 0;
if (asm_p)
for (def_rec = DF_INSN_DEFS (insn); *def_rec; def_rec++)
if (DF_REF_FLAGS_IS_SET (*def_rec, DF_REF_MUST_CLOBBER))
{
if (live_p)
mark_ref_live (*def_rec);
else
mark_ref_dead (*def_rec);
set_p = true;
}
for (def = 0; def < recog_data.n_operands; def++)
{
rtx dreg = recog_data.operand[def];
if (GET_CODE (dreg) == SUBREG)
dreg = SUBREG_REG (dreg);
if (! REG_P (dreg))
continue;
for (alt = 0; alt < recog_data.n_alternatives; alt++)
if ((recog_op_alt[def][alt].earlyclobber)
&& (recog_op_alt[def][alt].cl != NO_REGS))
break;
if (alt >= recog_data.n_alternatives)
continue;
if (live_p)
mark_reg_live (dreg);
else
mark_reg_dead (dreg);
set_p = true;
}
return set_p;
}
/* Checks that CONSTRAINTS permits to use only one hard register. If /* Checks that CONSTRAINTS permits to use only one hard register. If
it is so, the function returns the class of the hard register. it is so, the function returns the class of the hard register.
Otherwise it returns NO_REGS. */ Otherwise it returns NO_REGS. */
...@@ -580,6 +634,7 @@ process_bb_node_lives (ira_loop_tree_node_t loop_tree_node) ...@@ -580,6 +634,7 @@ process_bb_node_lives (ira_loop_tree_node_t loop_tree_node)
bitmap_iterator bi; bitmap_iterator bi;
bitmap reg_live_out; bitmap reg_live_out;
unsigned int px; unsigned int px;
bool set_p;
bb = loop_tree_node->bb; bb = loop_tree_node->bb;
if (bb != NULL) if (bb != NULL)
...@@ -698,6 +753,7 @@ process_bb_node_lives (ira_loop_tree_node_t loop_tree_node) ...@@ -698,6 +753,7 @@ process_bb_node_lives (ira_loop_tree_node_t loop_tree_node)
} }
extract_insn (insn); extract_insn (insn);
preprocess_constraints ();
process_single_reg_class_operands (false, freq); process_single_reg_class_operands (false, freq);
/* See which defined values die here. */ /* See which defined values die here. */
...@@ -733,19 +789,12 @@ process_bb_node_lives (ira_loop_tree_node_t loop_tree_node) ...@@ -733,19 +789,12 @@ process_bb_node_lives (ira_loop_tree_node_t loop_tree_node)
for (use_rec = DF_INSN_USES (insn); *use_rec; use_rec++) for (use_rec = DF_INSN_USES (insn); *use_rec; use_rec++)
mark_ref_live (*use_rec); mark_ref_live (*use_rec);
/* If any defined values conflict with the inputs, mark those set_p = mark_early_clobbers (insn, true);
defined values as live. */
for (def_rec = DF_INSN_DEFS (insn); *def_rec; def_rec++)
if (def_conflicts_with_inputs_p (*def_rec))
mark_ref_live (*def_rec);
process_single_reg_class_operands (true, freq); process_single_reg_class_operands (true, freq);
/* See which of the defined values we marked as live are dead if (set_p)
before the instruction. */ mark_early_clobbers (insn, false);
for (def_rec = DF_INSN_DEFS (insn); *def_rec; def_rec++)
if (def_conflicts_with_inputs_p (*def_rec))
mark_ref_dead (*def_rec);
curr_point++; curr_point++;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment