1/* PR target/36533 */
2/* { dg-do run { target { { i?86-*-linux* x86_64-*-linux* } && ilp32 } } } */
3/* { dg-options "-Os" } */
4#include <string.h>
5#include <sys/mman.h>
6#ifndef MAP_ANONYMOUS
7#define MAP_ANONYMOUS MAP_ANON
8#endif
9
10typedef struct S1
11{
12  unsigned long s1;
13  struct S1 *s2;
14  char *s3;
15} S1;
16
17typedef struct
18{
19  unsigned int s4;
20  unsigned int s5;
21  int s6;
22  unsigned int *s7;
23} S2;
24
25typedef struct
26{
27  unsigned int s8;
28  unsigned short s9;
29  unsigned char s10;
30  unsigned char s11;
31  char s12[255];
32} S3;
33
34typedef struct
35{
36  unsigned int s4;
37  unsigned short s13;
38  unsigned short s14;
39} S4;
40
41typedef struct
42{
43  char s15[16];
44  unsigned long s16;
45} S5;
46
47typedef struct
48{
49  char s15[48];
50  S5 *s17;
51} S6;
52
53typedef struct
54{
55  S1 *s18;
56} S7;
57
58__attribute__((regparm (3), noinline)) int
59fn1 (const char *x, void *y, S1 *z)
60{
61  asm volatile ("" : : : "memory");
62  return *x + (y != 0);
63}
64
65__attribute__((regparm (3), noinline)) int
66fn2 (const char *x, int y, S2 *z)
67{
68  asm volatile ("" : : : "memory");
69  return 0;
70}
71
72static inline __attribute__ ((always_inline)) unsigned int
73fn4 (unsigned short x)
74{
75  unsigned len = x;
76  if (len == ((1 << 16) - 1))
77    return 1 << 16;
78  return len;
79}
80
81static inline __attribute__ ((always_inline)) S3 *
82fn3 (S3 *p)
83{
84  return (S3 *) ((char *) p + fn4 (p->s9));
85}
86
87__attribute__((regparm (3), noinline)) int
88fn5 (void)
89{
90  asm volatile ("" : : : "memory");
91  return 0;
92}
93
94static inline __attribute__ ((always_inline)) int
95fn6 (S3 *w, int x, S2 *y, S4 *z)
96{
97  int a = 2;
98  char *b = (char *) w;
99  S2 c = *y;
100
101  while ((char *) w < b + x - 2 * sizeof (S4))
102    {
103      if (w->s10 && w->s8)
104	{
105	  fn2 (w->s12, w->s10, &c);
106	  z--;
107	  z->s4 = c.s4;
108	  z->s13 = (unsigned short) ((char *) w - b);
109	  z->s14 = w->s9;
110	  a++;
111	  fn5 ();
112	}
113
114      w = fn3 (w);
115    }
116  return a;
117}
118
119__attribute__((regparm (3), noinline)) unsigned int
120test (void *u, S6 *v, S1 **w, S7 *x, S2 *y, S1 *z)
121{
122  unsigned b = v->s17->s16;
123  unsigned a;
124  S4 *c;
125  unsigned d, e, f, i;
126
127  fn1 (__func__, u, x->s18);
128  c = (S4 *) (z->s3 + b);
129  a = fn6 ((S3 *) (*w)->s3, b, y, c);
130  c -= a;
131  f = 0;
132  e = 2;
133  for (i = a - 1; ; i--)
134    {
135      if (f + (unsigned short) (c[i].s14 / 2) > b / 2)
136	break;
137      f += c[i].s14;
138      e++;
139    }
140  d = a - e;
141  return c[d].s4;
142}
143
144int main (void)
145{
146  char *p = mmap (NULL, 131072, PROT_READ | PROT_WRITE,
147		  MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
148  S1 wb, z, *w;
149  S6 v;
150  S7 x;
151  S2 y;
152  S5 vb;
153  S4 s4;
154  if (p == MAP_FAILED)
155    return 0;
156  if (munmap (p + 65536, 65536) < 0)
157    return 0;
158  memset (&wb, 0, sizeof (wb));
159  memset (&z, 0, sizeof (z));
160  memset (&v, 0, sizeof (v));
161  memset (&x, 0, sizeof (x));
162  memset (&y, 0, sizeof (y));
163  memset (&vb, 0, sizeof (vb));
164  memset (&s4, 0, sizeof (s4));
165  s4.s14 = 254;
166  z.s3 = p + 65536 - 2 * sizeof (S4);
167  w = &wb;
168  v.s17 = &vb;
169  vb.s16 = 2 * sizeof (S4);
170  memcpy (z.s3, &s4, sizeof (s4));
171  memcpy (z.s3 + sizeof (s4), &s4, sizeof (s4));
172  test ((void *) 0, &v, &w, &x, &y, &z);
173  return 0;
174}
175