df-scan.c (df_get_call_refs): Mark global registers as both a DF_REF_REG_USE and...
authorDavid S. Miller <davem@gcc.gnu.org>
Tue, 23 Oct 2007 04:33:26 +0000 (21:33 -0700)
committerDavid S. Miller <davem@gcc.gnu.org>
Tue, 23 Oct 2007 04:33:26 +0000 (21:33 -0700)
gcc/:

2007-10-22  Seongbae Park <seongbae.park@gmail.com>
David S. Miller  <davem@davemloft.net>

* df-scan.c (df_get_call_refs): Mark global registers as both a
DF_REF_REG_USE and a non-clobber DF_REF_REG_DEF.

gcc/testsuite/:

2007-10-22  David S. Miller  <davem@davemloft.net>

* gcc.dg/globalreg-1.c: New test.

From-SVN: r129572

gcc/ChangeLog
gcc/df-scan.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/globalreg-1.c [new file with mode: 0644]

index 390ed0db2e643b57f6e2ecc6834766c718fa8ff7..f6f8a862a6fd6c55ba8a5e69e57b1d3144565618 100644 (file)
@@ -1,3 +1,9 @@
+2007-10-22  Seongbae Park <seongbae.park@gmail.com>
+       David S. Miller  <davem@davemloft.net>
+
+       * df-scan.c (df_get_call_refs): Mark global registers as both a
+       DF_REF_REG_USE and a non-clobber DF_REF_REG_DEF.
+
 2007-10-22  Dorit Nuzman  <dorit@il.ibm.com>
 
        PR tree-optimization/33834
index f4ced0d34c94ae04c77caacd01b7b29d425b8e48..cc6866b6b789cdd3e71783bbcfb1f401c5455d56 100644 (file)
@@ -3109,18 +3109,22 @@ df_get_call_refs (struct df_collection_rec * collection_rec,
      so they are recorded as used.  */
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
     if (global_regs[i])
-      df_ref_record (collection_rec, regno_reg_rtx[i],
-                    NULL, bb, insn, DF_REF_REG_USE, flags);
+      {
+       df_ref_record (collection_rec, regno_reg_rtx[i],
+                      NULL, bb, insn, DF_REF_REG_USE, flags);
+       df_ref_record (collection_rec, regno_reg_rtx[i],
+                      NULL, bb, insn, DF_REF_REG_DEF, flags);
+      }
 
   is_sibling_call = SIBLING_CALL_P (insn);
   EXECUTE_IF_SET_IN_BITMAP (df_invalidated_by_call, 0, ui, bi)
     {
-      if ((!bitmap_bit_p (defs_generated, ui))
+      if (!global_regs[ui]
+         && (!bitmap_bit_p (defs_generated, ui))
          && (!is_sibling_call
              || !bitmap_bit_p (df->exit_block_uses, ui)
              || refers_to_regno_p (ui, ui+1, 
                                    current_function_return_rtx, NULL)))
-
         df_ref_record (collection_rec, regno_reg_rtx[ui], 
                       NULL, bb, insn, DF_REF_REG_DEF, DF_REF_MAY_CLOBBER | flags);
     }
index ecc4e8010a00101ccbe51047a508d72e62a3d1cd..39758307a1be49e15da2149eae12e1046a3bc352 100644 (file)
@@ -1,3 +1,7 @@
+2007-10-22  David S. Miller  <davem@davemloft.net>
+
+       * gcc.dg/globalreg-1.c: New test.
+
 2007-10-22  Martin Michlmayr <tbm@cyrius.com>  
            Dorit Nuzman  <dorit@il.ibm.com>
 
diff --git a/gcc/testsuite/gcc.dg/globalreg-1.c b/gcc/testsuite/gcc.dg/globalreg-1.c
new file mode 100644 (file)
index 0000000..f54976d
--- /dev/null
@@ -0,0 +1,54 @@
+/* { dg-do run { target sparc*-*-* } } */
+/* { dg-options "-std=gnu99 -Os" } */
+
+/* This is a massively distilled test case based upon
+   mm/memory.c:unmap_vmas() in the Linux kernel when compiled
+   on sparc64 for SMP which uses a global register as the
+   base of the per-cpu variable area.
+
+   Because of a bug in global register handling in the dataflow
+   code, the loop-invariant pass would move 'expression(regval)'
+   outside of the loop.  */
+
+extern void exit(int);
+extern void abort(void);
+
+register unsigned long regval __asm__("g6");
+
+extern void cond_resched(void);
+
+unsigned int var;
+
+static unsigned long expression(unsigned long v)
+{
+  unsigned long ret;
+
+  __asm__("" : "=r" (ret) : "0" (0));
+  return ret + v;
+}
+
+void func(unsigned long *pp)
+{
+  int i;
+
+  for (i = 0; i < 56; i++) {
+    cond_resched();
+    *pp = expression(regval);
+  }
+}
+
+void __attribute__((noinline)) cond_resched(void)
+{
+       regval++;
+}
+
+int main(void)
+{
+  unsigned long val;
+
+  regval = 100;
+  func(&val);
+  if (val != 156)
+    abort();
+  exit(0);
+}