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