diff options
author | Vladimir Makarov <vmakarov@redhat.com> | 2008-10-06 15:34:26 +0000 |
---|---|---|
committer | Vladimir Makarov <vmakarov@gcc.gnu.org> | 2008-10-06 15:34:26 +0000 |
commit | 3517d3a0870e7081d4ded0fa4cc590c602713a8c (patch) | |
tree | 6208c8b2d1a94f1fa3c249de54b5c7b56339df26 | |
parent | e84319a3ffa34ad21ba267ec06d2dfc6fa180bc7 (diff) | |
download | gcc-3517d3a0870e7081d4ded0fa4cc590c602713a8c.zip gcc-3517d3a0870e7081d4ded0fa4cc590c602713a8c.tar.gz gcc-3517d3a0870e7081d4ded0fa4cc590c602713a8c.tar.bz2 |
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
-rw-r--r-- | gcc/ChangeLog | 13 | ||||
-rw-r--r-- | gcc/doc/rtl.texi | 8 | ||||
-rw-r--r-- | gcc/ira-lives.c | 142 |
3 files changed, 122 insertions, 41 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7a9752f..a873fd6 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +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> * config/i386/mingw32.h (REAL_LIBGCC_SPEC): Add thread cleanup diff --git a/gcc/doc/rtl.texi b/gcc/doc/rtl.texi index 148e19d..a12de21 100644 --- a/gcc/doc/rtl.texi +++ b/gcc/doc/rtl.texi @@ -2930,9 +2930,11 @@ constituent instructions might not. When a @code{clobber} expression for a register appears inside a @code{parallel} with other side effects, the register allocator guarantees that the register is unoccupied both before and after that -insn. However, the reload phase may allocate a register used for one of -the inputs unless the @samp{&} constraint is specified for the selected -alternative (@pxref{Modifiers}). You can clobber either a specific hard +insn if it is a hard register clobber or the @samp{&} constraint +is specified for at least one alternative (@pxref{Modifiers}) of the +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 latter two cases, GCC will allocate a hard register that is available there for use as a temporary. diff --git a/gcc/ira-lives.c b/gcc/ira-lives.c index 609708e..c1b2bdd 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,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 it is so, the function returns the class of the hard register. Otherwise it returns NO_REGS. */ @@ -580,6 +643,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 +762,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 +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++) 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); + + /* 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++; } |