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
      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 *
      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 *
      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
      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
      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  }