summaryrefslogtreecommitdiff
path: root/gcc/ira-lives.c
diff options
context:
space:
mode:
authorVladimir Makarov <vmakarov@redhat.com>2008-09-26 00:43:11 +0000
committerVladimir Makarov <vmakarov@gcc.gnu.org>2008-09-26 00:43:11 +0000
commit83d48fad1f3dc5d869fd3f567293ef12bf495392 (patch)
tree623650abb3bee835f51cbee9bd50331745975687 /gcc/ira-lives.c
parent3fcac00fec7d8643bb723d5921858a61d8db38ac (diff)
downloadgcc-83d48fad1f3dc5d869fd3f567293ef12bf495392.tar.gz
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
Diffstat (limited to 'gcc/ira-lives.c')
-rw-r--r--gcc/ira-lives.c125
1 files changed, 87 insertions, 38 deletions
diff --git a/gcc/ira-lives.c b/gcc/ira-lives.c
index 609708e9069..e49860fa927 100644
--- a/gcc/ira-lives.c
+++ b/gcc/ira-lives.c
@@ -209,20 +209,15 @@ clear_allocno_live (ira_allocno_t a)
sparseset_clear_bit (allocnos_live, ALLOCNO_NUM (a));
}
-/* Mark the register referenced by use or def REF as live
- Store a 1 in hard_regs_live or allocnos_live for this register or
- the corresponding allocno, record how many consecutive hardware
- registers it actually needs. */
-
+/* Mark the register REG as live. Store a 1 in hard_regs_live or
+ allocnos_live for this register or the corresponding allocno,
+ record how many consecutive hardware registers it actually
+ needs. */
static void
-mark_ref_live (struct df_ref *ref)
+mark_reg_live (rtx reg)
{
- rtx reg;
int regno;
- reg = DF_REF_REG (ref);
- if (GET_CODE (reg) == SUBREG)
- reg = SUBREG_REG (reg);
gcc_assert (REG_P (reg));
regno = REGNO (reg);
@@ -269,32 +264,25 @@ mark_ref_live (struct df_ref *ref)
}
}
-/* Return true if the definition described by DEF conflicts with the
- instruction's inputs. */
-static bool
-def_conflicts_with_inputs_p (struct df_ref *def)
+/* Mark the register referenced by use or def REF as live. */
+static void
+mark_ref_live (struct df_ref *ref)
{
- /* Conservatively assume that the condition is true for all clobbers. */
- return DF_REF_FLAGS_IS_SET (def, DF_REF_MUST_CLOBBER);
+ rtx reg;
+
+ 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
- definition is a total one. Store a 0 in hard_regs_live or
+/* Mark the register REG as dead. Store a 0 in hard_regs_live or
allocnos_live for the register. */
static void
-mark_ref_dead (struct df_ref *def)
+mark_reg_dead (rtx reg)
{
- unsigned int i;
- rtx reg;
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));
regno = REGNO (reg);
@@ -312,6 +300,7 @@ mark_ref_dead (struct df_ref *def)
}
else if (! TEST_HARD_REG_BIT (ira_no_alloc_regs, regno))
{
+ unsigned int i;
int last = regno + hard_regno_nregs[regno][GET_MODE (reg)];
enum reg_class cover_class;
@@ -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
it is so, the function returns the class of the hard register.
Otherwise it returns NO_REGS. */
@@ -580,6 +634,7 @@ process_bb_node_lives (ira_loop_tree_node_t loop_tree_node)
bitmap_iterator bi;
bitmap reg_live_out;
unsigned int px;
+ bool set_p;
bb = loop_tree_node->bb;
if (bb != NULL)
@@ -698,6 +753,7 @@ process_bb_node_lives (ira_loop_tree_node_t loop_tree_node)
}
extract_insn (insn);
+ preprocess_constraints ();
process_single_reg_class_operands (false, freq);
/* See which defined values die here. */
@@ -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++)
mark_ref_live (*use_rec);
- /* If any defined values conflict with the inputs, mark those
- 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);
+ set_p = mark_early_clobbers (insn, true);
process_single_reg_class_operands (true, freq);
- /* See which of the defined values we marked as live are dead
- before the instruction. */
- for (def_rec = DF_INSN_DEFS (insn); *def_rec; def_rec++)
- if (def_conflicts_with_inputs_p (*def_rec))
- mark_ref_dead (*def_rec);
+ if (set_p)
+ mark_early_clobbers (insn, false);
curr_point++;
}