The following patch solves

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

  It is a bug in a new rematerialization subpass of LRA.

The patch was bootstrapped on x86/x86-64.

Committed as rev. 218874.

2014-12-18  Vladimir Makarov  <vmaka...@redhat.com>

        PR rtl-optimization/64291
        * lra-remat.c (bad_for_rematerialization_p): Add UNPSEC_VLOATILE.
        (create_cands): Process only output reload insn with potential
        cands.

2014-12-18  Vladimir Makarov  <vmaka...@redhat.com>

        PR rtl-optimization/64291
        * testsuite/gcc.target/i386/pr64291-[12].c: New tests.

Index: lra-remat.c
===================================================================
--- lra-remat.c (revision 218685)
+++ lra-remat.c (working copy)
@@ -350,12 +350,12 @@ finish_cand_table (void)
 
 
 
-/* Return true if X contains memory or UNSPEC.  We can not just check
-   insn operands as memory or unspec might be not an operand itself
-   but contain an operand.  Insn with memory access is not profitable
-   for rematerialization.  Rematerialization of UNSPEC might result in
-   wrong code generation as the UNPEC effect is unknown
-   (e.g. generating a label).  */
+/* Return true if X contains memory or some UNSPEC.  We can not just
+   check insn operands as memory or unspec might be not an operand
+   itself but contain an operand.  Insn with memory access is not
+   profitable for rematerialization.  Rematerialization of UNSPEC
+   might result in wrong code generation as the UNPEC effect is
+   unknown (e.g. generating a label).  */
 static bool
 bad_for_rematerialization_p (rtx x)
 {
@@ -363,7 +363,7 @@ bad_for_rematerialization_p (rtx x)
   const char *fmt;
   enum rtx_code code;
 
-  if (MEM_P (x) || GET_CODE (x) == UNSPEC)
+  if (MEM_P (x) || GET_CODE (x) == UNSPEC || GET_CODE (x) == UNSPEC_VOLATILE)
     return true;
   code = GET_CODE (x);
   fmt = GET_RTX_FORMAT (code);
@@ -406,7 +406,7 @@ operand_to_remat (rtx_insn *insn)
     if (reg->regno == STACK_POINTER_REGNUM && frame_pointer_needed)
       return -1;
     else if (reg->type == OP_OUT && ! reg->subreg_p
-       && find_regno_note (insn, REG_UNUSED, reg->regno) == NULL)
+            && find_regno_note (insn, REG_UNUSED, reg->regno) == NULL)
       {
        /* We permits only one spilled reg.  */
        if (found_reg != NULL)
@@ -508,11 +508,14 @@ create_cands (void)
 
        if ((set = single_set (insn)) != NULL
            && REG_P (SET_SRC (set)) && REG_P (SET_DEST (set))
-           && (src_regno = REGNO (SET_SRC (set))) >= FIRST_PSEUDO_REGISTER
+           && ((src_regno = REGNO (SET_SRC (set)))
+               >= lra_constraint_new_regno_start)
            && (dst_regno = REGNO (SET_DEST (set))) >= FIRST_PSEUDO_REGISTER
            && reg_renumber[dst_regno] < 0
            && (insn2 = regno_potential_cand[src_regno].insn) != NULL
            && BLOCK_FOR_INSN (insn2) == BLOCK_FOR_INSN (insn))
+         /* It is an output reload insn after insn can be
+            rematerialized (potential candidate).  */
          create_cand (insn2, regno_potential_cand[src_regno].nop, dst_regno);
        if (nop < 0)
          goto fail;
Index: testsuite/gcc.target/i386/pr64291-1.c
===================================================================
--- testsuite/gcc.target/i386/pr64291-1.c       (revision 0)
+++ testsuite/gcc.target/i386/pr64291-1.c       (working copy)
@@ -0,0 +1,51 @@
+/* { dg-options "-O2" } */
+/* { dg-additional-sources pr64291-2.c } */
+/* { dg-do run } */
+void f(void*,...);
+void g(void*,long,long);
+int nnn=0;
+long test=0;
+
+typedef struct
+{
+  int _mp_size;
+  unsigned long *_mp_d;
+} __mpz_struct;
+typedef __mpz_struct mpz_t[1];
+
+int main ()
+{
+  mpz_t n, d;
+  long nn, dn;
+  unsigned long *np, *dup, *dnp, *qp;
+  long alloc, itch;
+
+  f (n);
+  f (d);
+  qp = (unsigned long*)__builtin_alloca(4099*8) + 1;
+  dnp = (unsigned long*)__builtin_alloca (2049*8);
+  alloc = 1;
+  for (test = 0; test < 1; test++)
+    {
+      dn = d->_mp_size;
+      dup = d->_mp_d;
+      f (dnp, dup, dn);
+      dnp[dn - 1] |= 1UL<<63;
+      f (0);
+      nn = nnn;
+      np = n->_mp_d;
+      qp[-1] = -757136820;
+      qp[nn - dn + 1] = 14883681;
+      f (0);
+      if (dn >= 6)
+       f (0);
+      itch = nn + 1;
+      if (itch + 1> alloc)
+       {
+         g(0,alloc*8,(itch+1)*8);
+         alloc = itch + 1;
+       }
+      f (np, nn);
+    }
+  return 0;
+}
Index: testsuite/gcc.target/i386/pr64291-2.c
===================================================================
--- testsuite/gcc.target/i386/pr64291-2.c       (revision 0)
+++ testsuite/gcc.target/i386/pr64291-2.c       (working copy)
@@ -0,0 +1,4 @@
+/* { dg-do compile } */
+extern void abort (void);
+void f(void*p,...){}
+void g(void*p,long a,long b){if (a!=8) abort();}

Reply via email to