1 /* { dg-do run } */
2 /* { dg-options "-std=gnu99 -Os" } */
3 
4 /* This is a massively distilled test case based upon
5    mm/memory.c:unmap_vmas() in the Linux kernel when compiled
6    on sparc64 for SMP which uses a global register as the
7    base of the per-cpu variable area.
8 
9    Because of a bug in global register handling in the dataflow
10    code, the loop-invariant pass would move 'expression(regval)'
11    outside of the loop.  */
12 
13 extern void exit(int);
14 extern void abort(void);
15 
16 register unsigned long regval __asm__("g6");
17 
18 extern void cond_resched(void);
19 
20 unsigned int var;
21 
expression(unsigned long v)22 static unsigned long expression(unsigned long v)
23 {
24   unsigned long ret;
25 
26   __asm__("" : "=r" (ret) : "0" (0));
27   return ret + v;
28 }
29 
func(unsigned long * pp)30 void func(unsigned long *pp)
31 {
32   int i;
33 
34   for (i = 0; i < 56; i++) {
35     cond_resched();
36     *pp = expression(regval);
37   }
38 }
39 
cond_resched(void)40 void __attribute__((noinline)) cond_resched(void)
41 {
42 	regval++;
43 }
44 
main(void)45 int main(void)
46 {
47   unsigned long val;
48 
49   regval = 100;
50   func(&val);
51   if (val != 156)
52     abort();
53   exit(0);
54 }
55