diff mbox

patch to fix PR59133

Message ID 528D1CB1.6070404@redhat.com
State New
Headers show

Commit Message

Vladimir Makarov Nov. 20, 2013, 8:33 p.m. UTC
The following patch fixes

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59133

The problem was in creation a new additional pseudo by RTL 
infrastructure and assigning it a wrong class.

The patch was bootstrapped and tested on x86/x86-64 and ppc64.

Committed as rev. 205141.

2013-11-20  Vladimir Makarov  <vmakarov@redhat.com>

         PR rtl-optimization/59133
         * lra.c (expand_reg_data): Add new argument.  Set up ALL_REGS for
         new pseudos.
         (lra_create_new_reg_with_unique_value): Pass new argument value.
         (lra_emit_add, lra_emit_move): Ditto.
         * lra-constraints.c (in_class_p): Add check for move for a new
         insn.
         (change_class): Rename to lra_change_class.  Move to lra-int.h.
         (get_reload_reg, narrow_reload_pseudo_class): Adjust calls of
         change_class.
         (process_addr_reg, process_addr): Ditto.
         (curr_insn_transform): Ditto.  Add check on old pseudo for
         optional reload.
         * lra-int.h (lra_get_regno_hard_regno): Move below.
         (lra_change_class): Renamed change_class from lra.c.

2013-11-20  Vladimir Makarov  <vmakarov@redhat.com>

         PR rtl-optimization/59133
         * gcc.target/i386/pr59133.c: New.
diff mbox

Patch

Index: lra-constraints.c
===================================================================
--- lra-constraints.c	(revision 204792)
+++ lra-constraints.c	(working copy)
@@ -269,7 +269,11 @@  in_class_p (rtx reg, enum reg_class cl,
 	 typically moves that have many alternatives, and restricting
 	 reload pseudos for one alternative may lead to situations
 	 where other reload pseudos are no longer allocatable.  */
-      || INSN_UID (curr_insn) >= new_insn_uid_start)
+      || (INSN_UID (curr_insn) >= new_insn_uid_start
+	  && curr_insn_set != NULL
+	  && (OBJECT_P (SET_SRC (curr_insn_set))
+	      || (GET_CODE (SET_SRC (curr_insn_set)) == SUBREG
+		  && OBJECT_P (SUBREG_REG (SET_SRC (curr_insn_set)))))))
     /* When we don't know what class will be used finally for reload
        pseudos, we use ALL_REGS.  */
     return ((regno >= new_regno_start && rclass == ALL_REGS)
@@ -381,21 +385,6 @@  init_curr_insn_input_reloads (void)
   curr_insn_input_reloads_num = 0;
 }
 
-/* Change class of pseudo REGNO to NEW_CLASS.  Print info about it
-   using TITLE.	 Output a new line if NL_P.  */
-static void
-change_class (int regno, enum reg_class new_class,
-	      const char *title, bool nl_p)
-{
-  lra_assert (regno >= FIRST_PSEUDO_REGISTER);
-  if (lra_dump_file != NULL)
-    fprintf (lra_dump_file, "%s to class %s for r%d",
-	     title, reg_class_names[new_class], regno);
-  setup_reg_classes (regno, new_class, NO_REGS, new_class);
-  if (lra_dump_file != NULL && nl_p)
-    fprintf (lra_dump_file, "\n");
-}
-
 /* Create a new pseudo using MODE, RCLASS, ORIGINAL or reuse already
    created input reload pseudo (only if TYPE is not OP_OUT).  The
    result pseudo is returned through RESULT_REG.  Return TRUE if we
@@ -442,7 +431,7 @@  get_reload_reg (enum op_type type, enum
 	      dump_value_slim (lra_dump_file, original, 1);
 	    }
 	  if (new_class != lra_get_allocno_class (regno))
-	    change_class (regno, new_class, ", change", false);
+	    lra_change_class (regno, new_class, ", change to", false);
 	  if (lra_dump_file != NULL)
 	    fprintf (lra_dump_file, "\n");
 	  return false;
@@ -667,7 +656,7 @@  narrow_reload_pseudo_class (rtx reg, enu
   if (! REG_P (reg) || (int) REGNO (reg) < new_regno_start)
     return;
   if (in_class_p (reg, cl, &rclass) && rclass != cl)
-    change_class (REGNO (reg), rclass, "      Change", true);
+    lra_change_class (REGNO (reg), rclass, "      Change to", true);
 }
 
 /* Generate reloads for matching OUT and INS (array of input operand
@@ -1133,7 +1122,7 @@  process_addr_reg (rtx *loc, rtx *before,
 	}
       else if (new_class != NO_REGS && rclass != new_class)
 	{
-	  change_class (regno, new_class, "	   Change", true);
+	  lra_change_class (regno, new_class, "	   Change to", true);
 	  return false;
 	}
       else
@@ -2796,7 +2785,7 @@  process_address (int nop, rtx *before, r
 	      regno = REGNO (*ad.base_term);
 	      if (regno >= FIRST_PSEUDO_REGISTER
 		  && cl != lra_get_allocno_class (regno))
-		change_class (regno, cl, "      Change", true);
+		lra_change_class (regno, cl, "      Change to", true);
 	      new_reg = SET_SRC (set);
 	      delete_insns_since (PREV_INSN (last_insn));
 	    }
@@ -3316,7 +3305,7 @@  curr_insn_transform (void)
 	    if (new_class != NO_REGS && get_reg_class (regno) != new_class)
 	      {
 		lra_assert (ok_p);
-		change_class (regno, new_class, "      Change", true);
+		lra_change_class (regno, new_class, "      Change to", true);
 	      }
 	  }
       }
@@ -3395,7 +3384,7 @@  curr_insn_transform (void)
 	      && lra_former_scratch_operand_p (curr_insn, i))
 	    {
 	      int regno = REGNO (op);
-	      change_class (regno, NO_REGS, "      Change", true);
+	      lra_change_class (regno, NO_REGS, "      Change to", true);
 	      if (lra_get_regno_hard_regno (regno) >= 0)
 		/* We don't have to mark all insn affected by the
 		   spilled pseudo as there is only one such insn, the
@@ -3410,6 +3399,7 @@  curr_insn_transform (void)
 	      && lra_undo_inheritance_iter < LRA_MAX_INHERITANCE_PASSES
 	      && goal_alt[i] != NO_REGS && REG_P (op)
 	      && (regno = REGNO (op)) >= FIRST_PSEUDO_REGISTER
+	      && regno < new_regno_start
 	      && ! lra_former_scratch_p (regno)
 	      && reg_renumber[regno] < 0
 	      && (curr_insn_set == NULL_RTX
Index: lra-int.h
===================================================================
--- lra-int.h	(revision 204792)
+++ lra-int.h	(working copy)
@@ -33,16 +33,6 @@  along with GCC; see the file COPYING3.	I
    base and index registers might require a reload too.	 */
 #define LRA_MAX_INSN_RELOADS (MAX_RECOG_OPERANDS * 3)
 
-/* Return the hard register which given pseudo REGNO assigned to.
-   Negative value means that the register got memory or we don't know
-   allocation yet.  */
-static inline int
-lra_get_regno_hard_regno (int regno)
-{
-  resize_reg_info ();
-  return reg_renumber[regno];
-}
-
 typedef struct lra_live_range *lra_live_range_t;
 
 /* The structure describes program points where a given pseudo lives.
@@ -394,6 +384,31 @@  extern void lra_eliminate_reg_if_possibl
 
 
 
+/* Return the hard register which given pseudo REGNO assigned to.
+   Negative value means that the register got memory or we don't know
+   allocation yet.  */
+static inline int
+lra_get_regno_hard_regno (int regno)
+{
+  resize_reg_info ();
+  return reg_renumber[regno];
+}
+
+/* Change class of pseudo REGNO to NEW_CLASS.  Print info about it
+   using TITLE.  Output a new line if NL_P.  */
+static void inline
+lra_change_class (int regno, enum reg_class new_class,
+		  const char *title, bool nl_p)
+{
+  lra_assert (regno >= FIRST_PSEUDO_REGISTER);
+  if (lra_dump_file != NULL)
+    fprintf (lra_dump_file, "%s class %s for r%d",
+	     title, reg_class_names[new_class], regno);
+  setup_reg_classes (regno, new_class, NO_REGS, new_class);
+  if (lra_dump_file != NULL && nl_p)
+    fprintf (lra_dump_file, "\n");
+}
+
 /* Update insn operands which are duplication of NOP operand.  The
    insn is represented by its LRA internal representation ID.  */
 static inline void
Index: lra.c
===================================================================
--- lra.c	(revision 204792)
+++ lra.c	(working copy)
@@ -130,11 +130,13 @@  static void invalidate_insn_data_regno_i
 
 /* Expand all regno related info needed for LRA.  */
 static void
-expand_reg_data (void)
+expand_reg_data (int old)
 {
   resize_reg_info ();
   expand_reg_info ();
   ira_expand_reg_equiv ();
+  for (int i = (int) max_reg_num () - 1; i >= old; i--)
+    lra_change_class (i, ALL_REGS, "      Set", true);
 }
 
 /* Create and return a new reg of ORIGINAL mode.  If ORIGINAL is NULL
@@ -178,7 +180,7 @@  lra_create_new_reg_with_unique_value (en
 		 title, REGNO (new_reg));
       fprintf (lra_dump_file, "\n");
     }
-  expand_reg_data ();
+  expand_reg_data (max_reg_num ());
   setup_reg_classes (REGNO (new_reg), rclass, NO_REGS, rclass);
   return new_reg;
 }
@@ -417,7 +419,7 @@  lra_emit_add (rtx x, rtx y, rtx z)
   /* Functions emit_... can create pseudos -- so expand the pseudo
      data.  */
   if (old != max_reg_num ())
-    expand_reg_data ();
+    expand_reg_data (old);
 }
 
 /* The number of emitted reload insns so far.  */
@@ -443,7 +445,7 @@  lra_emit_move (rtx x, rtx y)
       /* Function emit_move can create pseudos -- so expand the pseudo
 	 data.	*/
       if (old != max_reg_num ())
-	expand_reg_data ();
+	expand_reg_data (old);
       return;
     }
   lra_emit_add (x, XEXP (y, 0), XEXP (y, 1));
Index: testsuite/gcc.target/i386/pr59133.c
===================================================================
--- testsuite/gcc.target/i386/pr59133.c	(revision 0)
+++ testsuite/gcc.target/i386/pr59133.c	(working copy)
@@ -0,0 +1,42 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O3 -ffast-math -march=core-avx2" } */
+
+#define XX 0
+#define YY 1
+#define ZZ 2
+#define DIM 3
+typedef float matrix[DIM][DIM];
+typedef float rvec[DIM];
+extern int det (matrix);
+extern void foo(matrix);
+
+void bar1 (int n,int *index,rvec x[],matrix trans)
+{
+  float   xt,yt,zt;
+  int    i,ii;
+  
+  for(i=0; (i<n); i++) {
+    ii=index ? index[i] : i;
+    xt=x[ii][XX];
+    yt=x[ii][YY];
+    zt=x[ii][ZZ];
+    x[ii][XX]=trans[XX][XX]*xt+trans[XX][YY]*yt+trans[XX][ZZ]*zt;
+    x[ii][YY]=trans[YY][XX]*xt+trans[YY][YY]*yt+trans[YY][ZZ]*zt;
+    x[ii][ZZ]=trans[ZZ][XX]*xt+trans[ZZ][YY]*yt+trans[ZZ][ZZ]*zt;
+  }
+}
+
+
+void bar2 (int n, rvec x[]) 
+{
+  int     m;
+  matrix  trans;
+  
+  foo (trans);
+  
+  if (det (trans) < 0) {
+    for(m=0; (m<DIM); m++)
+      trans[ZZ][m] = -trans[ZZ][m];
+  }  
+  bar1 (n,(int*) 0,x,trans);
+}