The following patch fixes

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66424

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

  Committed as rev. 226053.

2015-07-21  Vladimir Makarov  <vmaka...@redhat.com>

        PR ipa/66424.
        * lra-remat.c (operand_to_remat): Prevent using insns with input
        subregs processed separately by IRA.

2015-07-21  Vladimir Makarov  <vmaka...@redhat.com>

        PR ipa/66424.
        * gcc.target/i386/pr66424.c: New.


Index: lra-remat.c
===================================================================
--- lra-remat.c	(revision 225979)
+++ lra-remat.c	(working copy)
@@ -417,6 +417,16 @@ operand_to_remat (rtx_insn *insn)
 	  return -1;
 	found_reg = reg;
       }
+    /* IRA calculates conflicts separately for subregs of two words
+       pseudo.  Even if the pseudo lives, e.g. one its subreg can be
+       used lately, another subreg hard register can be already used
+       for something else.  In such case, it is not safe to
+       rematerialize the insn.  */
+    else if (reg->type == OP_IN && reg->subreg_p
+	     && reg->regno >= FIRST_PSEUDO_REGISTER
+	     && (GET_MODE_SIZE (PSEUDO_REGNO_MODE (reg->regno))
+		 == 2 * UNITS_PER_WORD))
+      return -1;
   if (found_reg == NULL)
     return -1;
   if (found_reg->regno < FIRST_PSEUDO_REGISTER)
Index: testsuite/gcc.target/i386/pr66424.c
===================================================================
--- testsuite/gcc.target/i386/pr66424.c	(revision 0)
+++ testsuite/gcc.target/i386/pr66424.c	(working copy)
@@ -0,0 +1,51 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+/* { dg-require-effective-target ia32 } */
+int a, b, c, d, e[2], f, l, m, n, o;
+long long g = 1, j;
+static unsigned int h;
+static int i, k;
+
+void
+fn1 (long long p)
+{
+  int q = p;
+  f = 1 ^ e[f ^ (q & 1)];
+}
+
+static void
+fn2 (long long p)
+{
+  f = 1 ^ e[(f ^ 1) & 1];
+  fn1 (p >> 1 & 1);
+  fn1 (p >> 32 & 1);
+}
+
+void
+fn3 (int p)
+{
+  g |= j = p;
+}
+
+int
+main ()
+{
+  e[0] = 1;
+  char p = l;
+  h = --g;
+  i = o = c;
+  m = d ? 1 / d : 0;
+  fn3 (l || 0);
+  b = a;
+  n = j++;
+  k--;
+  fn2 (g);
+  fn2 (h);
+  fn2 (i);
+
+  if (k + f)
+    __builtin_abort ();
+
+  return 0;
+}
+

Reply via email to