On Fri, Aug 17, 2012 at 6:36 PM, Uros Bizjak <ubiz...@gmail.com> wrote:

> 2012-08-17  Uros Bizjak  <ubiz...@gmail.com>
>
>         PR rtl-optimization/46829
>         * combine.c (recog_for_combine): Check operand constraints
>         in case hard registers were propagater into insn pattern.
>
> testsuite/ChangeLog:
>
> 2012-08-17  Uros Bizjak  <ubiz...@gmail.com>
>
>         PR rtl-optimization/46829
>         * gcc.target/i386/pr46829.c: New test.
>
> Patch was bootstrapped and regression tested on x86_64-pc-linux-gnu {,-m32}.

Oh ...

This part:

+                     && rtx_equal_p (recog_data.operand[j],
+                                     recog_data.operand[op_alt[j].matches]))

should read:

+                     && rtx_equal_p (recog_data.operand[i],
+                                     recog_data.operand[op_alt[j].matches]))

Note the "j" vs "i" array index difference in the first line.

Correct patch attached, bootstrapped and re-tested on
x86_64-pc-linux-gnu {,-m32}.

Uros.
Index: combine.c
===================================================================
--- combine.c   (revision 190480)
+++ combine.c   (working copy)
@@ -10507,6 +10507,7 @@ recog_for_combine (rtx *pnewpat, rtx insn, rtx *pn
   int i;
   rtx notes = 0;
   rtx old_notes, old_pat;
+  int old_icode;
 
   /* If PAT is a PARALLEL, check to see if it contains the CLOBBER
      we use to indicate that something didn't match.  If we find such a
@@ -10566,6 +10567,7 @@ recog_for_combine (rtx *pnewpat, rtx insn, rtx *pn
          print_rtl_single (dump_file, pat);
        }
     }
+
   PATTERN (insn) = old_pat;
   REG_NOTES (insn) = old_notes;
 
@@ -10607,6 +10609,86 @@ recog_for_combine (rtx *pnewpat, rtx insn, rtx *pn
       pat = newpat;
     }
 
+  old_pat = PATTERN (insn);
+  old_notes = REG_NOTES (insn);
+  old_icode = INSN_CODE (insn);
+  PATTERN (insn) = pat;
+  REG_NOTES (insn) = notes;
+
+  /* Check operand constraints in case hard registers were propagated
+     into insn pattern.  This check prevents combine pass from
+     generating insn patterns with invalid hard register operands.
+     These invalid insns can eventually confuse reload to error out
+     with a spill failure.  See also PR 46829.  */
+  if (insn_code_number >= 0
+      && insn_code_number != NOOP_MOVE_INSN_CODE
+      && (INSN_CODE (insn) = recog (PATTERN (insn), insn, 0)) >= 0)
+    {
+      extract_insn (insn);
+      preprocess_constraints ();
+
+      for (i = 0; i < recog_data.n_operands; i++)
+       {
+         rtx op = recog_data.operand[i];
+         enum machine_mode mode = GET_MODE (op);
+         struct operand_alternative *op_alt;
+         int offset = 0;
+         bool win;
+         int j;
+
+         /* A unary operator may be accepted by the predicate, but it
+            is irrelevant for matching constraints.  */
+         if (UNARY_P (op))
+           op = XEXP (op, 0);
+
+         if (GET_CODE (op) == SUBREG)
+           {
+             if (REG_P (SUBREG_REG (op))
+                 && REGNO (SUBREG_REG (op)) < FIRST_PSEUDO_REGISTER)
+               offset = subreg_regno_offset (REGNO (SUBREG_REG (op)),
+                                             GET_MODE (SUBREG_REG (op)),
+                                             SUBREG_BYTE (op),
+                                             GET_MODE (op));
+             op = SUBREG_REG (op);
+           }
+
+         if (!(REG_P (op) && HARD_REGISTER_P (op)))
+           continue;
+
+         op_alt = recog_op_alt[i];
+
+         win = false;
+         for (j = 0; j < recog_data.n_alternatives; j++)
+           {
+             if (op_alt[j].anything_ok
+                 || (op_alt[j].matches != -1
+                     && rtx_equal_p (recog_data.operand[i],
+                                     recog_data.operand[op_alt[j].matches]))
+                 || (reg_fits_class_p (op, op_alt[j].cl, offset, mode)))
+               {
+                 win = true;
+                 break;
+               }
+           }
+
+         if (!win)
+           {
+             if (dump_file && (dump_flags & TDF_DETAILS))
+               {
+                 fputs ("Operand failed to match constraints:\n",
+                        dump_file);
+                 print_rtl_single (dump_file, op);
+               }
+             insn_code_number = -1;
+             break;
+           }
+       }
+    }
+
+  PATTERN (insn) = old_pat;
+  REG_NOTES (insn) = old_notes;
+  INSN_CODE (insn) = old_icode;
+
   *pnewpat = pat;
   *pnotes = notes;
 
Index: testsuite/gcc.target/i386/pr46829.c
===================================================================
--- testsuite/gcc.target/i386/pr46829.c (revision 0)
+++ testsuite/gcc.target/i386/pr46829.c (working copy)
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fschedule-insns" } */
+
+struct S
+{
+  int i, j;
+};
+
+extern struct S s[];
+
+extern void bar (int, ...);
+
+void
+foo (int n)
+{
+  while (s[n].i)
+    bar (0, n, s[n].j, s, s[n].i / s[n].j);
+}

Reply via email to