1 /* PR middle-end/37275 */
2 /* { dg-do compile { target ia32 } } */
3 /* { dg-options "-g -dA -O2 -march=i686 -fstack-protector" } */
4 /* { dg-require-visibility "" } */
5
6 typedef __SIZE_TYPE__ size_t;
7 extern void *memcpy (void *, const void *, size_t);
8 extern void *malloc (size_t);
9
10 typedef int A;
11
12 struct B
13 {
14 int x;
15 };
16
17 struct C
18 {
19 struct F *c1;
20 void *c2;
21 };
22
23 enum D
24 {
25 D0,
26 D1
27 };
28
29 struct E
30 {
31 struct E *e1;
32 struct E *e2;
33 struct B e3;
34 void (*fn) (void *);
35 void *fn_data;
36 enum D e4;
37 _Bool e5;
38 _Bool e6;
39 };
40
41 struct F
42 {
43 unsigned f1;
44 A f2;
45 int f3;
46 };
47
48 struct G
49 {
50 void (*fn) (void *data);
51 void *data;
52 struct C g1;
53 struct E *t;
54 };
55
56 extern void fn1 (A * m);
57 static inline void
fn2(A * x)58 fn2 (A *x)
59 {
60 if (!__sync_bool_compare_and_swap (x, 0, 1))
61 fn1 (x);
62 }
63
64 extern __thread struct G thr __attribute__ ((visibility ("hidden")));
65 static inline struct G *
fn3(void)66 fn3 (void)
67 {
68 return &thr;
69 }
70
71 extern struct B *fn4 (void);
72 extern struct B a;
73
74 static inline struct B *
fn5(_Bool x)75 fn5 (_Bool x)
76 {
77 struct E *t = fn3 ()->t;
78 if (t)
79 return &t->e3;
80 else if (x)
81 return fn4 ();
82 else
83 return &a;
84 }
85
86 void
fn6(struct E * t,struct E * e1_t,struct B * prev_e3)87 fn6 (struct E *t, struct E *e1_t,
88 struct B *prev_e3)
89 {
90 t->e1 = e1_t;
91 t->e3 = *prev_e3;
92 t->e4 = D0;
93 t->e5 = 0;
94 t->e6 = 0;
95 t->e2 = ((void *) 0);
96 }
97
98 void
test(void (* fn)(void *),void * data,void (* cpyfn)(void *,void *),long x,long y,_Bool z)99 test (void (*fn) (void *), void *data, void (*cpyfn) (void *, void *), long x, long y, _Bool z)
100 {
101 struct G *thr = fn3 ();
102 struct F *c1 = thr->g1.c1;
103 if (!z || c1 == 0 || (unsigned) c1->f3 > 64 * c1->f1)
104 {
105 struct E t;
106
107 fn6 (&t, thr->t, fn5 (0));
108 if (thr->t)
109 t.e6 = thr->t->e6;
110 thr->t = &t;
111 if (__builtin_expect (cpyfn != ((void *) 0), 0))
112 {
113 char buf[x + y - 1];
114 char *arg = (char *) (((unsigned long) buf + y - 1)
115 & ~(unsigned long) (y - 1));
116 cpyfn (arg, data);
117 fn (arg);
118 }
119 }
120 else
121 {
122 struct E *t;
123 struct E *e1 = thr->t;
124 char *arg;
125
126 t = malloc (sizeof (*t) + x + y - 1);
127 arg = (char *) (((unsigned long) (t + 1) + y - 1)
128 & ~(unsigned long) (y - 1));
129 fn6 (t, e1, fn5 (0));
130 thr->t = t;
131 if (cpyfn)
132 cpyfn (arg, data);
133 else
134 memcpy (arg, data, x);
135 thr->t = e1;
136 fn2 (&c1->f2);
137 }
138 }
139