]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
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:37:02 +0000 (21:37 -0700)
committerDavid S. Miller <davem@gcc.gnu.org>
Tue, 23 Oct 2007 04:37:02 +0000 (21:37 -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: r129573

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

index 6bc59f0fa60e58acff1539d51f036cc7f931b7dc..49925677f53a0fe1f06300ae8e673d550b4d4791 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  Richard Sandiford  <rsandifo@nildram.co.uk>
 
        PR target/33169
index 7a7bd70db83b131d2a566a21be30224c63a6b2bb..216a4e6d211ba8866d88135fce8c7ae0f203189d 100644 (file)
@@ -1584,12 +1584,19 @@ df_insn_refs_record (struct dataflow *dflow, basic_block bb, rtx insn)
                 so they are recorded as used.  */
              for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
                if (global_regs[i])
-                 df_uses_record (dflow, &regno_reg_rtx[i],
-                                 DF_REF_REG_USE, bb, insn, 
-                                 0);
+                 {
+                   df_uses_record (dflow, &regno_reg_rtx[i],
+                                   DF_REF_REG_USE, bb, insn, 0);
+                   df_ref_record (dflow, regno_reg_rtx[i], &regno_reg_rtx[i],
+                                  bb, insn, DF_REF_REG_DEF, 0, true);
+                 }
+
              EXECUTE_IF_SET_IN_BITMAP (df_invalidated_by_call, 0, ui, bi)
-               df_ref_record (dflow, regno_reg_rtx[ui], &regno_reg_rtx[ui], bb, 
-                              insn, DF_REF_REG_DEF, DF_REF_MAY_CLOBBER, false);
+               {
+                 if (!global_regs[ui])
+                   df_ref_record (dflow, regno_reg_rtx[ui], &regno_reg_rtx[ui], bb, 
+                                  insn, DF_REF_REG_DEF, DF_REF_MAY_CLOBBER, false);
+               }
            }
        }
 
index 5665b19a38676f87fd703bec2df78a4c098116eb..45f21cacf0ab4f0dcf3ad647772be11b458ea952 100644 (file)
@@ -1,3 +1,7 @@
+2007-10-22  David S. Miller  <davem@davemloft.net>
+
+       * gcc.dg/globalreg-1.c: New test.
+
 2007-10-18  Uros Bizjak  <ubizjak@gmail.com>
 
        PR target/32961
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);
+}