From e237b8ddccbebf8abc31cf7f481e34828bff9658 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 22 Oct 2007 21:37:02 -0700 Subject: [PATCH] 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/: 2007-10-22 Seongbae Park David S. Miller * 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 * gcc.dg/globalreg-1.c: New test. From-SVN: r129573 --- gcc/ChangeLog | 6 ++++ gcc/df-scan.c | 17 +++++++--- gcc/testsuite/ChangeLog | 4 +++ gcc/testsuite/gcc.dg/globalreg-1.c | 54 ++++++++++++++++++++++++++++++ 4 files changed, 76 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/globalreg-1.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6bc59f0fa60e..49925677f53a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2007-10-22 Seongbae Park + David S. Miller + + * 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 PR target/33169 diff --git a/gcc/df-scan.c b/gcc/df-scan.c index 7a7bd70db83b..216a4e6d211b 100644 --- a/gcc/df-scan.c +++ b/gcc/df-scan.c @@ -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, ®no_reg_rtx[i], - DF_REF_REG_USE, bb, insn, - 0); + { + df_uses_record (dflow, ®no_reg_rtx[i], + DF_REF_REG_USE, bb, insn, 0); + df_ref_record (dflow, regno_reg_rtx[i], ®no_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], ®no_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], ®no_reg_rtx[ui], bb, + insn, DF_REF_REG_DEF, DF_REF_MAY_CLOBBER, false); + } } } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 5665b19a3867..45f21cacf0ab 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2007-10-22 David S. Miller + + * gcc.dg/globalreg-1.c: New test. + 2007-10-18 Uros Bizjak 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 index 000000000000..f54976dce1de --- /dev/null +++ b/gcc/testsuite/gcc.dg/globalreg-1.c @@ -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); +} -- 2.47.2