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