OSDN Git Service

2008-09-25 Vladimir Makarov <vmakarov@redhat.com>
authorvmakarov <vmakarov@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 26 Sep 2008 00:43:11 +0000 (00:43 +0000)
committervmakarov <vmakarov@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 26 Sep 2008 00:43:11 +0000 (00:43 +0000)
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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@140679 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/doc/rtl.texi
gcc/ira-lives.c

index fa2f0cc..86d2c46 100644 (file)
@@ -1,5 +1,18 @@
 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
        
        * ira-int.h (IRA_ALLOCNO_TEMP): Rename to ALLOCNO_TEMP.
index 148e19d..984ee43 100644 (file)
@@ -2930,12 +2930,13 @@ 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
-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.
+insn if 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.
 
 For instructions that require a temporary register, you should use
 @code{scratch} instead of a pseudo-register because this will allow the
index 609708e..e49860f 100644 (file)
@@ -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++;
        }