@@ -1685,7 +1685,9 @@ extern rtx simplify_subtraction (rtx);
/* In function.c */
extern rtx assign_stack_local (enum machine_mode, HOST_WIDE_INT, int);
-extern rtx assign_stack_local_1 (enum machine_mode, HOST_WIDE_INT, int, bool);
+#define ASLK_REDUCE_ALIGN 1
+#define ASLK_RECORD_PAD 2
+extern rtx assign_stack_local_1 (enum machine_mode, HOST_WIDE_INT, int, int);
extern rtx assign_stack_temp (enum machine_mode, HOST_WIDE_INT, int);
extern rtx assign_stack_temp_for_type (enum machine_mode,
HOST_WIDE_INT, int, tree);
@@ -355,14 +355,17 @@ add_frame_space (HOST_WIDE_INT start, HO
-2 means use BITS_PER_UNIT,
positive specifies alignment boundary in bits.
- If REDUCE_ALIGNMENT_OK is true, it is OK to reduce alignment.
+ KIND has ASLK_REDUCE_ALIGN bit set if it is OK to reduce
+ alignment and ASLK_RECORD_PAD bit set if we should remember
+ extra space we allocated for alignment purposes. When we are
+ called from assign_stack_temp_for_type, it is not set so we don't
+ track the same stack slot in two independent lists.
We do not round to stack_boundary here. */
rtx
assign_stack_local_1 (enum machine_mode mode, HOST_WIDE_INT size,
- int align,
- bool reduce_alignment_ok ATTRIBUTE_UNUSED)
+ int align, int kind)
{
rtx x, addr;
int bigend_correction = 0;
@@ -412,7 +415,7 @@ assign_stack_local_1 (enum machine_mode
/* It is OK to reduce the alignment as long as the
requested size is 0 or the estimated stack
alignment >= mode alignment. */
- gcc_assert (reduce_alignment_ok
+ gcc_assert ((kind & ASLK_REDUCE_ALIGN)
|| size == 0
|| (crtl->stack_alignment_estimated
>= GET_MODE_ALIGNMENT (mode)));
@@ -430,21 +433,24 @@ assign_stack_local_1 (enum machine_mode
if (mode != BLKmode || size != 0)
{
- struct frame_space **psp;
-
- for (psp = &crtl->frame_space_list; *psp; psp = &(*psp)->next)
+ if (kind & ASLK_RECORD_PAD)
{
- struct frame_space *space = *psp;
- if (!try_fit_stack_local (space->start, space->length, size,
- alignment, &slot_offset))
- continue;
- *psp = space->next;
- if (slot_offset > space->start)
- add_frame_space (space->start, slot_offset);
- if (slot_offset + size < space->start + space->length)
- add_frame_space (slot_offset + size,
- space->start + space->length);
- goto found_space;
+ struct frame_space **psp;
+
+ for (psp = &crtl->frame_space_list; *psp; psp = &(*psp)->next)
+ {
+ struct frame_space *space = *psp;
+ if (!try_fit_stack_local (space->start, space->length, size,
+ alignment, &slot_offset))
+ continue;
+ *psp = space->next;
+ if (slot_offset > space->start)
+ add_frame_space (space->start, slot_offset);
+ if (slot_offset + size < space->start + space->length)
+ add_frame_space (slot_offset + size,
+ space->start + space->length);
+ goto found_space;
+ }
}
}
else if (!STACK_ALIGNMENT_NEEDED)
@@ -460,20 +466,26 @@ assign_stack_local_1 (enum machine_mode
frame_offset -= size;
try_fit_stack_local (frame_offset, size, size, alignment, &slot_offset);
- if (slot_offset > frame_offset)
- add_frame_space (frame_offset, slot_offset);
- if (slot_offset + size < old_frame_offset)
- add_frame_space (slot_offset + size, old_frame_offset);
+ if (kind & ASLK_RECORD_PAD)
+ {
+ if (slot_offset > frame_offset)
+ add_frame_space (frame_offset, slot_offset);
+ if (slot_offset + size < old_frame_offset)
+ add_frame_space (slot_offset + size, old_frame_offset);
+ }
}
else
{
frame_offset += size;
try_fit_stack_local (old_frame_offset, size, size, alignment, &slot_offset);
- if (slot_offset > old_frame_offset)
- add_frame_space (old_frame_offset, slot_offset);
- if (slot_offset + size < frame_offset)
- add_frame_space (slot_offset + size, frame_offset);
+ if (kind & ASLK_RECORD_PAD)
+ {
+ if (slot_offset > old_frame_offset)
+ add_frame_space (old_frame_offset, slot_offset);
+ if (slot_offset + size < frame_offset)
+ add_frame_space (slot_offset + size, frame_offset);
+ }
}
found_space:
@@ -513,7 +525,7 @@ assign_stack_local_1 (enum machine_mode
rtx
assign_stack_local (enum machine_mode mode, HOST_WIDE_INT size, int align)
{
- return assign_stack_local_1 (mode, size, align, false);
+ return assign_stack_local_1 (mode, size, align, ASLK_RECORD_PAD);
}
@@ -868,11 +880,13 @@ assign_stack_temp_for_type (enum machine
and round it now. We also make sure ALIGNMENT is at least
BIGGEST_ALIGNMENT. */
gcc_assert (mode != BLKmode || align == BIGGEST_ALIGNMENT);
- p->slot = assign_stack_local (mode,
- (mode == BLKmode
- ? CEIL_ROUND (size, (int) align / BITS_PER_UNIT)
- : size),
- align);
+ p->slot = assign_stack_local_1 (mode,
+ (mode == BLKmode
+ ? CEIL_ROUND (size,
+ (int) align
+ / BITS_PER_UNIT)
+ : size),
+ align, 0);
p->align = align;
@@ -647,7 +647,8 @@ setup_save_areas (void)
saved_reg->slot
= assign_stack_local_1
(regno_save_mode[regno][1],
- GET_MODE_SIZE (regno_save_mode[regno][1]), 0, true);
+ GET_MODE_SIZE (regno_save_mode[regno][1]), 0,
+ ASLK_REDUCE_ALIGN);
if (dump_file != NULL)
fprintf (dump_file, "%d uses a new slot\n", regno);
}
@@ -705,7 +706,7 @@ setup_save_areas (void)
regno_save_mem[i][j]
= assign_stack_local_1 (regno_save_mode[i][j],
GET_MODE_SIZE (regno_save_mode[i][j]),
- 0, true);
+ 0, ASLK_REDUCE_ALIGN);
/* Setup single word save area just in case... */
for (k = 0; k < j; k++)
@@ -0,0 +1,187 @@
+/* PR middle-end/47893 */
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+/* { dg-options "-O2 -mtune=atom -fno-omit-frame-pointer -fno-strict-aliasing" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } */
+
+extern void abort (void);
+
+struct S
+{
+ unsigned s1:4, s2:2, s3:2, s4:2, s5:2, s6:1, s7:1, s8:1, s9:1, s10:1;
+ int s11:16; unsigned s12:4; int s13:16; unsigned s14:2;
+ int s15:16; unsigned s16:4; int s17:16; unsigned s18:2;
+};
+
+struct T
+{
+ unsigned t[3];
+};
+
+struct U
+{
+ unsigned u1, u2;
+};
+
+struct V;
+
+struct W
+{
+ char w1[24]; struct V *w2; unsigned w3; char w4[28912];
+ unsigned int w5; char w6[60];
+};
+
+struct X
+{
+ unsigned int x[2];
+};
+
+struct V
+{
+ int v1;
+ struct X v2[3];
+ char v3[28];
+};
+
+struct Y
+{
+ void *y1;
+ char y2[3076];
+ struct T y3[32];
+ char y4[1052];
+};
+
+volatile struct S v1 = { .s15 = -1, .s16 = 15, .s17 = -1, .s18 = 3 };
+
+__attribute__ ((noinline, noclone))
+int
+fn1 (int x)
+{
+ int r;
+ __asm__ volatile ("" : "=r" (r) : "0" (1), "r" (x) : "memory");
+ return r;
+}
+
+volatile int cnt;
+
+__attribute__ ((noinline, noclone))
+#ifdef __i386__
+__attribute__ ((regparm (2)))
+#endif
+struct S
+fn2 (struct Y *x, const struct X *y)
+{
+ if (++cnt > 1)
+ abort ();
+ __asm__ volatile ("" : : "r" (x), "r" (y) : "memory");
+ return v1;
+}
+
+__attribute__ ((noinline, noclone))
+void fn3 (void *x, unsigned y, const struct S *z, unsigned w)
+{
+ __asm__ volatile ("" : : "r" (x), "r" (y), "r" (z), "r" (w) : "memory");
+}
+
+volatile struct U v2;
+
+__attribute__ ((noinline, noclone))
+struct U
+fn4 (void *x, unsigned y)
+{
+ __asm__ volatile ("" : : "r" (x), "r" (y) : "memory");
+ return v2;
+}
+
+__attribute__ ((noinline, noclone))
+struct S
+fn5 (void *x)
+{
+ __asm__ volatile ("" : : "r" (x) : "memory");
+ return v1;
+}
+
+volatile struct T v3;
+
+__attribute__ ((noinline, noclone))
+struct T fn6 (void *x)
+{
+ __asm__ volatile ("" : : "r" (x) : "memory");
+ return v3;
+}
+
+__attribute__ ((noinline, noclone))
+struct T fn7 (void *x, unsigned y, unsigned z)
+{
+ __asm__ volatile ("" : : "r" (x), "r" (y), "r" (z) : "memory");
+ return v3;
+}
+
+static void
+fn8 (struct Y *x, const struct V *y)
+{
+ void *a = x->y1;
+ struct S b[4];
+ unsigned i, c;
+ c = fn1 (y->v1);
+ for (i = 0; i < c; i++)
+ b[i] = fn2 (x, &y->v2[i]);
+ fn3 (a, y->v1, b, c);
+}
+
+static inline void
+fn9 (void *x, struct S y __attribute__((unused)))
+{
+ fn4 (x, 8);
+}
+
+static void
+fn10 (struct Y *x)
+{
+ void *a = x->y1;
+ struct T b __attribute__((unused)) = fn6 (a);
+ fn9 (a, fn5 (a));
+}
+
+__attribute__((noinline, noclone))
+int
+fn11 (unsigned int x, void *y, const struct W *z,
+ unsigned int w, const char *v, const char *u)
+{
+ struct Y a, *t;
+ unsigned i;
+ t = &a;
+ __builtin_memset (t, 0, sizeof *t);
+ t->y1 = y;
+ if (x == 0)
+ {
+ if (z->w3 & 1)
+ fn10 (t);
+ for (i = 0; i < w; i++)
+ {
+ if (v[i] == 0)
+ t->y3[i] = fn7 (y, 0, u[i]);
+ else
+ return 0;
+ }
+ }
+ else
+ for (i = 0; i < w; i++)
+ t->y3[i] = fn7 (y, v[i], u[i]);
+ for (i = 0; i < z->w5; i++)
+ fn8 (t, &z->w2[i]);
+ return 0;
+}
+
+volatile int i;
+const char *volatile p = "";
+
+int
+main ()
+{
+ struct V v = { .v1 = 0 };
+ struct W w = { .w5 = 1, .w2 = &v };
+ fn11 (i + 1, (void *) p, &w, i, (const char *) p, (const char *) p);
+ if (cnt != 1)
+ abort ();
+ return 0;
+}