1/* PR middle-end/37275 */
2/* { dg-do compile { target ilp32 } } */
3/* { dg-options "-g -dA -O2 -march=i686 -fstack-protector" } */
4/* { dg-require-visibility "" } */
5
6typedef __SIZE_TYPE__ size_t;
7extern void *memcpy (void *, const void *, size_t);
8extern void *malloc (size_t);
9
10typedef int A;
11
12struct B
13{
14  int x;
15};
16
17struct C
18{
19  struct F *c1;
20  void *c2;
21};
22
23enum D
24{
25  D0,
26  D1
27};
28
29struct 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
41struct F
42{
43  unsigned f1;
44  A f2;
45  int f3;
46};
47
48struct G
49{
50  void (*fn) (void *data);
51  void *data;
52  struct C g1;
53  struct E *t;
54};
55
56extern void fn1 (A * m);
57static inline void
58fn2 (A *x)
59{
60  if (!__sync_bool_compare_and_swap (x, 0, 1))
61    fn1 (x);
62}
63
64extern __thread struct G thr __attribute__ ((visibility ("hidden")));
65static inline struct G *
66fn3 (void)
67{
68  return &thr;
69}
70
71extern struct B *fn4 (void);
72extern struct B a;
73
74static inline struct B *
75fn5 (_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
86void
87fn6 (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
98void
99test (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