| /* { dg-do run } */ |
| /* { dg-options "-O" } */ |
| |
| extern void abort (void); |
| |
| typedef struct { |
| int b, c; |
| } |
| __attribute__((aligned(32))) inner_t; // data type is 32 byte aligned |
| |
| typedef struct { |
| inner_t *inner; |
| int a; |
| } outer_t; |
| |
| void __attribute__ ((noinline,weak)) |
| somefunc (int a, int b, int c) |
| { |
| if (!a || !b || c) |
| abort (); |
| }; |
| |
| __attribute__ ((noinline,weak)) |
| outer_t * |
| some_alloc_1 () |
| { |
| static outer_t x; |
| return &x; |
| } |
| |
| __attribute__ ((noinline,weak)) |
| inner_t * |
| some_alloc_2 () |
| { |
| static inner_t x; |
| return &x; |
| } |
| |
| int main (void) |
| { |
| int y, y2, y3; |
| // @p_out is pointing to instance of outer_t, naturally aligned to 4+4 = 8 |
| // and not gauranteed be 32 byte aligned. |
| outer_t *p_out = some_alloc_1( ); // returns 8 byte aligned ptr |
| |
| // @ptr is pointing to instance of inner_t which is naturally aligned to 32. |
| // It is assigned to p_out->inner which is of type inner_t thus 32 byte |
| // aligned as well |
| // Note that gcc can deduce p_out->inner is 32b aligned, not at runtime, |
| // because it was assigned @ptr, but even at compile time, because it's data |
| // type is naturally 32 byte aligned. |
| inner_t *ptr = some_alloc_2(); // returns 32 byte aligned ptr |
| p_out->inner = ptr; // this ptr will also be 32 byte aligned |
| |
| y = __builtin_arc_aligned(ptr, 32); // this shd return 1 |
| y2 = __builtin_arc_aligned(p_out->inner, 32); // this also shd return 1 |
| // Although p_out->inner ptr is 32 byte aligned, |
| // it's container &(p_out->inner) need not be. |
| // That is because the hoister has no relation to contents. |
| // p_out is not gauranteed to be 32 byte |
| // aligned, so it's member @inner in p_out need not be. |
| y3 = __builtin_arc_aligned(&(p_out->inner), 32); |
| // compiler not sure, so must return 0 |
| |
| somefunc(y, y2, y3); |
| return 0; |
| } |