/* PR middle-end/37275 */
|
/* PR middle-end/37275 */
|
/* { dg-do compile { target ilp32 } } */
|
/* { dg-do compile { target ilp32 } } */
|
/* { dg-options "-g -dA -O2 -march=i686 -fstack-protector" } */
|
/* { dg-options "-g -dA -O2 -march=i686 -fstack-protector" } */
|
/* { dg-require-visibility "" } */
|
/* { dg-require-visibility "" } */
|
|
|
typedef __SIZE_TYPE__ size_t;
|
typedef __SIZE_TYPE__ size_t;
|
extern void *memcpy (void *, const void *, size_t);
|
extern void *memcpy (void *, const void *, size_t);
|
extern void *malloc (size_t);
|
extern void *malloc (size_t);
|
|
|
typedef int A;
|
typedef int A;
|
|
|
struct B
|
struct B
|
{
|
{
|
int x;
|
int x;
|
};
|
};
|
|
|
struct C
|
struct C
|
{
|
{
|
struct F *c1;
|
struct F *c1;
|
void *c2;
|
void *c2;
|
};
|
};
|
|
|
enum D
|
enum D
|
{
|
{
|
D0,
|
D0,
|
D1
|
D1
|
};
|
};
|
|
|
struct E
|
struct E
|
{
|
{
|
struct E *e1;
|
struct E *e1;
|
struct E *e2;
|
struct E *e2;
|
struct B e3;
|
struct B e3;
|
void (*fn) (void *);
|
void (*fn) (void *);
|
void *fn_data;
|
void *fn_data;
|
enum D e4;
|
enum D e4;
|
_Bool e5;
|
_Bool e5;
|
_Bool e6;
|
_Bool e6;
|
};
|
};
|
|
|
struct F
|
struct F
|
{
|
{
|
unsigned f1;
|
unsigned f1;
|
A f2;
|
A f2;
|
int f3;
|
int f3;
|
};
|
};
|
|
|
struct G
|
struct G
|
{
|
{
|
void (*fn) (void *data);
|
void (*fn) (void *data);
|
void *data;
|
void *data;
|
struct C g1;
|
struct C g1;
|
struct E *t;
|
struct E *t;
|
};
|
};
|
|
|
extern void fn1 (A * m);
|
extern void fn1 (A * m);
|
static inline void
|
static inline void
|
fn2 (A *x)
|
fn2 (A *x)
|
{
|
{
|
if (!__sync_bool_compare_and_swap (x, 0, 1))
|
if (!__sync_bool_compare_and_swap (x, 0, 1))
|
fn1 (x);
|
fn1 (x);
|
}
|
}
|
|
|
extern __thread struct G thr __attribute__ ((visibility ("hidden")));
|
extern __thread struct G thr __attribute__ ((visibility ("hidden")));
|
static inline struct G *
|
static inline struct G *
|
fn3 (void)
|
fn3 (void)
|
{
|
{
|
return &thr;
|
return &thr;
|
}
|
}
|
|
|
extern struct B *fn4 (void);
|
extern struct B *fn4 (void);
|
extern struct B a;
|
extern struct B a;
|
|
|
static inline struct B *
|
static inline struct B *
|
fn5 (_Bool x)
|
fn5 (_Bool x)
|
{
|
{
|
struct E *t = fn3 ()->t;
|
struct E *t = fn3 ()->t;
|
if (t)
|
if (t)
|
return &t->e3;
|
return &t->e3;
|
else if (x)
|
else if (x)
|
return fn4 ();
|
return fn4 ();
|
else
|
else
|
return &a;
|
return &a;
|
}
|
}
|
|
|
void
|
void
|
fn6 (struct E *t, struct E *e1_t,
|
fn6 (struct E *t, struct E *e1_t,
|
struct B *prev_e3)
|
struct B *prev_e3)
|
{
|
{
|
t->e1 = e1_t;
|
t->e1 = e1_t;
|
t->e3 = *prev_e3;
|
t->e3 = *prev_e3;
|
t->e4 = D0;
|
t->e4 = D0;
|
t->e5 = 0;
|
t->e5 = 0;
|
t->e6 = 0;
|
t->e6 = 0;
|
t->e2 = ((void *) 0);
|
t->e2 = ((void *) 0);
|
}
|
}
|
|
|
void
|
void
|
test (void (*fn) (void *), void *data, void (*cpyfn) (void *, void *), long x, long y, _Bool z)
|
test (void (*fn) (void *), void *data, void (*cpyfn) (void *, void *), long x, long y, _Bool z)
|
{
|
{
|
struct G *thr = fn3 ();
|
struct G *thr = fn3 ();
|
struct F *c1 = thr->g1.c1;
|
struct F *c1 = thr->g1.c1;
|
if (!z || c1 == 0 || (unsigned) c1->f3 > 64 * c1->f1)
|
if (!z || c1 == 0 || (unsigned) c1->f3 > 64 * c1->f1)
|
{
|
{
|
struct E t;
|
struct E t;
|
|
|
fn6 (&t, thr->t, fn5 (0));
|
fn6 (&t, thr->t, fn5 (0));
|
if (thr->t)
|
if (thr->t)
|
t.e6 = thr->t->e6;
|
t.e6 = thr->t->e6;
|
thr->t = &t;
|
thr->t = &t;
|
if (__builtin_expect (cpyfn != ((void *) 0), 0))
|
if (__builtin_expect (cpyfn != ((void *) 0), 0))
|
{
|
{
|
char buf[x + y - 1];
|
char buf[x + y - 1];
|
char *arg = (char *) (((unsigned long) buf + y - 1)
|
char *arg = (char *) (((unsigned long) buf + y - 1)
|
& ~(unsigned long) (y - 1));
|
& ~(unsigned long) (y - 1));
|
cpyfn (arg, data);
|
cpyfn (arg, data);
|
fn (arg);
|
fn (arg);
|
}
|
}
|
}
|
}
|
else
|
else
|
{
|
{
|
struct E *t;
|
struct E *t;
|
struct E *e1 = thr->t;
|
struct E *e1 = thr->t;
|
char *arg;
|
char *arg;
|
|
|
t = malloc (sizeof (*t) + x + y - 1);
|
t = malloc (sizeof (*t) + x + y - 1);
|
arg = (char *) (((unsigned long) (t + 1) + y - 1)
|
arg = (char *) (((unsigned long) (t + 1) + y - 1)
|
& ~(unsigned long) (y - 1));
|
& ~(unsigned long) (y - 1));
|
fn6 (t, e1, fn5 (0));
|
fn6 (t, e1, fn5 (0));
|
thr->t = t;
|
thr->t = t;
|
if (cpyfn)
|
if (cpyfn)
|
cpyfn (arg, data);
|
cpyfn (arg, data);
|
else
|
else
|
memcpy (arg, data, x);
|
memcpy (arg, data, x);
|
thr->t = e1;
|
thr->t = e1;
|
fn2 (&c1->f2);
|
fn2 (&c1->f2);
|
}
|
}
|
}
|
}
|
|
|