1 /* { dg-do run } */
2 /* { dg-options "-O2 -fipa-ra" } */
3 
4 extern void abort (void);
5 
6 #if (__SIZEOF_LONG_LONG__ == __SIZEOF_POINTER__)
7 #define ADD_SUFFIX(a) a ## ULL
8 #elif (__SIZEOF_LONG__ == __SIZEOF_POINTER__)
9 #define ADD_SUFFIX(a) a ## UL
10 #elif (__SIZEOF_INT__ == __SIZEOF_POINTER__)
11 #define ADD_SUFFIX(a) a ## U
12 #else
13 #error Add target support here
14 #endif
15 
16 #if __SIZEOF_POINTER__ <= 4
17 /* Use a 16 bit pointer to have a valid pointer for 16-bit to 31-bit pointer
18    architectures.  Using sizeof, we cannot distinguish between 31-bit and 32-bit
19    pointer types, so we also handle the 32-bit pointer type case here.  */
20 #define CONST_PTR ADD_SUFFIX (0x800)
21 #else
22 /* For x86_64 -m64, the problem reproduces with this 32-bit CONST_PTR, but not
23    with a 2-power below it.  */
24 #define CONST_PTR ADD_SUFFIX (0x80000000)
25 #endif
26 
27 int __attribute__((noinline, noclone))
bar(void)28 bar (void)
29 {
30   return 1;
31 }
32 
33 struct S
34 {
35   unsigned long p, q, r;
36   void *v;
37 };
38 
39 struct S *s1;
40 struct S *s2;
41 
42 void __attribute__((noinline, noclone))
fn2(struct S * x)43 fn2 (struct S *x)
44 {
45   s2 = x;
46 }
47 
48 __attribute__((noinline, noclone)) void *
fn1(struct S * x)49 fn1 (struct S *x)
50 {
51   /* Just a statement to make it a non-const function.  */
52   s1 = x;
53 
54   return (void *)0;
55 }
56 
57 int __attribute__((noinline, noclone))
baz(void)58 baz (void)
59 {
60   struct S *x = (struct S *) CONST_PTR;
61 
62   x += bar ();
63 
64   fn1 (x);
65   fn2 (x);
66 
67   return 0;
68 }
69 
70 int
main(void)71 main (void)
72 {
73   baz ();
74 
75   if (s2 != (((struct S *) CONST_PTR) + 1))
76     abort ();
77 
78   return 0;
79 }
80