Commit 3517d3a0 by Vladimir Makarov Committed by Vladimir Makarov

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

2008-10-06  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: r140906
parent e84319a3
2008-10-06 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.
2008-10-06 Danny Smith <dannysmith@users.sourceforge.net> 2008-10-06 Danny Smith <dannysmith@users.sourceforge.net>
* config/i386/mingw32.h (REAL_LIBGCC_SPEC): Add thread cleanup * config/i386/mingw32.h (REAL_LIBGCC_SPEC): Add thread cleanup
......
...@@ -2930,9 +2930,11 @@ constituent instructions might not. ...@@ -2930,9 +2930,11 @@ 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 it is a hard register clobber or the @samp{&} constraint
the inputs unless the @samp{&} constraint is specified for the selected is specified for at least one alternative (@pxref{Modifiers}) of the
alternative (@pxref{Modifiers}). You can clobber either a specific hard clobber. However, the reload phase may allocate a register used for
one of the inputs unless the @samp{&} constraint is specified for the
selected alternative. You can clobber either a specific hard
register, a pseudo register, or a @code{scratch} expression; in the register, a pseudo register, or a @code{scratch} expression; in the
latter two cases, GCC will allocate a hard register that is available latter two cases, GCC will allocate a hard register that is available
there for use as a temporary. there for use as a temporary.
......
...@@ -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,80 @@ mark_ref_dead (struct df_ref *def) ...@@ -343,6 +332,80 @@ 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;
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;
}
for (def_rec = DF_INSN_DEFS (insn); *def_rec; def_rec++)
if (DF_REF_FLAGS_IS_SET (*def_rec, DF_REF_MUST_CLOBBER))
{
rtx dreg = DF_REF_REG (*def_rec);
if (GET_CODE (dreg) == SUBREG)
dreg = SUBREG_REG (dreg);
if (! REG_P (dreg) || REGNO (dreg) >= FIRST_PSEUDO_REGISTER)
continue;
/* Hard register clobbers are believed to be early clobber
because there is no way to say that non-operand hard
register clobbers are not early ones. */
if (live_p)
mark_ref_live (*def_rec);
else
mark_ref_dead (*def_rec);
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 +643,7 @@ process_bb_node_lives (ira_loop_tree_node_t loop_tree_node) ...@@ -580,6 +643,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 +762,7 @@ process_bb_node_lives (ira_loop_tree_node_t loop_tree_node) ...@@ -698,6 +762,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 +798,20 @@ process_bb_node_lives (ira_loop_tree_node_t loop_tree_node) ...@@ -733,19 +798,20 @@ 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. */ {
for (def_rec = DF_INSN_DEFS (insn); *def_rec; def_rec++) mark_early_clobbers (insn, false);
if (def_conflicts_with_inputs_p (*def_rec))
mark_ref_dead (*def_rec); /* Mark each used value as live again. For example, a
hard register can be in clobber and in an insn
input. */
for (use_rec = DF_INSN_USES (insn); *use_rec; use_rec++)
mark_ref_live (*use_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