Commit 80a832cd by Jakub Jelinek

re PR middle-end/47893 (4.6 miscompiles mesa on i686)

	PR middle-end/47893
	* rtl.h (ASLK_REDUCE_ALIGN, ASLK_RECORD_PAD): Define.
	(assign_stack_local_1): Change last argument type to int.
	* function.c (assign_stack_local_1): Replace reduce_alignment_ok
	argument with kind.  If bit ASLK_RECORD_PAD is not set in it,
	don't record padding space into frame_space_list nor
	use those areas.
	(assign_stack_local): Adjust caller.
	(assign_stack_temp_for_type): Call assign_stack_local_1 instead
	of assign_stack_local, pass 0 as last argument.
	* caller-save.c (setup_save_areas): Adjust assign_stack_local_1
	callers.

	* gcc.dg/pr47893.c: New test.

From-SVN: r170568
parent d154f927
2011-02-28 Bernd Schmidt <bernds@codesourcery.com>
Jakub Jelinek <jakub@redhat.com>
PR middle-end/47893
* rtl.h (ASLK_REDUCE_ALIGN, ASLK_RECORD_PAD): Define.
(assign_stack_local_1): Change last argument type to int.
* function.c (assign_stack_local_1): Replace reduce_alignment_ok
argument with kind. If bit ASLK_RECORD_PAD is not set in it,
don't record padding space into frame_space_list nor
use those areas.
(assign_stack_local): Adjust caller.
(assign_stack_temp_for_type): Call assign_stack_local_1 instead
of assign_stack_local, pass 0 as last argument.
* caller-save.c (setup_save_areas): Adjust assign_stack_local_1
callers.
2011-02-28 Jakub Jelinek <jakub@redhat.com> 2011-02-28 Jakub Jelinek <jakub@redhat.com>
PR debug/47283 PR debug/47283
......
...@@ -647,7 +647,8 @@ setup_save_areas (void) ...@@ -647,7 +647,8 @@ setup_save_areas (void)
saved_reg->slot saved_reg->slot
= assign_stack_local_1 = assign_stack_local_1
(regno_save_mode[regno][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) if (dump_file != NULL)
fprintf (dump_file, "%d uses a new slot\n", regno); fprintf (dump_file, "%d uses a new slot\n", regno);
} }
...@@ -705,7 +706,7 @@ setup_save_areas (void) ...@@ -705,7 +706,7 @@ setup_save_areas (void)
regno_save_mem[i][j] regno_save_mem[i][j]
= assign_stack_local_1 (regno_save_mode[i][j], = assign_stack_local_1 (regno_save_mode[i][j],
GET_MODE_SIZE (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... */ /* Setup single word save area just in case... */
for (k = 0; k < j; k++) for (k = 0; k < j; k++)
......
/* Expands front end tree to back end RTL for GCC. /* Expands front end tree to back end RTL for GCC.
Copyright (C) 1987, 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997, Copyright (C) 1987, 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
2010 Free Software Foundation, Inc. 2010, 2011 Free Software Foundation, Inc.
This file is part of GCC. This file is part of GCC.
...@@ -355,14 +355,17 @@ add_frame_space (HOST_WIDE_INT start, HOST_WIDE_INT end) ...@@ -355,14 +355,17 @@ add_frame_space (HOST_WIDE_INT start, HOST_WIDE_INT end)
-2 means use BITS_PER_UNIT, -2 means use BITS_PER_UNIT,
positive specifies alignment boundary in bits. 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. */ We do not round to stack_boundary here. */
rtx rtx
assign_stack_local_1 (enum machine_mode mode, HOST_WIDE_INT size, assign_stack_local_1 (enum machine_mode mode, HOST_WIDE_INT size,
int align, int align, int kind)
bool reduce_alignment_ok ATTRIBUTE_UNUSED)
{ {
rtx x, addr; rtx x, addr;
int bigend_correction = 0; int bigend_correction = 0;
...@@ -412,7 +415,7 @@ assign_stack_local_1 (enum machine_mode mode, HOST_WIDE_INT size, ...@@ -412,7 +415,7 @@ assign_stack_local_1 (enum machine_mode mode, HOST_WIDE_INT size,
/* It is OK to reduce the alignment as long as the /* It is OK to reduce the alignment as long as the
requested size is 0 or the estimated stack requested size is 0 or the estimated stack
alignment >= mode alignment. */ alignment >= mode alignment. */
gcc_assert (reduce_alignment_ok gcc_assert ((kind & ASLK_REDUCE_ALIGN)
|| size == 0 || size == 0
|| (crtl->stack_alignment_estimated || (crtl->stack_alignment_estimated
>= GET_MODE_ALIGNMENT (mode))); >= GET_MODE_ALIGNMENT (mode)));
...@@ -430,21 +433,24 @@ assign_stack_local_1 (enum machine_mode mode, HOST_WIDE_INT size, ...@@ -430,21 +433,24 @@ assign_stack_local_1 (enum machine_mode mode, HOST_WIDE_INT size,
if (mode != BLKmode || size != 0) if (mode != BLKmode || size != 0)
{ {
struct frame_space **psp; if (kind & ASLK_RECORD_PAD)
for (psp = &crtl->frame_space_list; *psp; psp = &(*psp)->next)
{ {
struct frame_space *space = *psp; struct frame_space **psp;
if (!try_fit_stack_local (space->start, space->length, size,
alignment, &slot_offset)) for (psp = &crtl->frame_space_list; *psp; psp = &(*psp)->next)
continue; {
*psp = space->next; struct frame_space *space = *psp;
if (slot_offset > space->start) if (!try_fit_stack_local (space->start, space->length, size,
add_frame_space (space->start, slot_offset); alignment, &slot_offset))
if (slot_offset + size < space->start + space->length) continue;
add_frame_space (slot_offset + size, *psp = space->next;
space->start + space->length); if (slot_offset > space->start)
goto found_space; 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) else if (!STACK_ALIGNMENT_NEEDED)
...@@ -460,20 +466,26 @@ assign_stack_local_1 (enum machine_mode mode, HOST_WIDE_INT size, ...@@ -460,20 +466,26 @@ assign_stack_local_1 (enum machine_mode mode, HOST_WIDE_INT size,
frame_offset -= size; frame_offset -= size;
try_fit_stack_local (frame_offset, size, size, alignment, &slot_offset); try_fit_stack_local (frame_offset, size, size, alignment, &slot_offset);
if (slot_offset > frame_offset) if (kind & ASLK_RECORD_PAD)
add_frame_space (frame_offset, slot_offset); {
if (slot_offset + size < old_frame_offset) if (slot_offset > frame_offset)
add_frame_space (slot_offset + size, old_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 else
{ {
frame_offset += size; frame_offset += size;
try_fit_stack_local (old_frame_offset, size, size, alignment, &slot_offset); try_fit_stack_local (old_frame_offset, size, size, alignment, &slot_offset);
if (slot_offset > old_frame_offset) if (kind & ASLK_RECORD_PAD)
add_frame_space (old_frame_offset, slot_offset); {
if (slot_offset + size < frame_offset) if (slot_offset > old_frame_offset)
add_frame_space (slot_offset + size, 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: found_space:
...@@ -513,7 +525,7 @@ assign_stack_local_1 (enum machine_mode mode, HOST_WIDE_INT size, ...@@ -513,7 +525,7 @@ assign_stack_local_1 (enum machine_mode mode, HOST_WIDE_INT size,
rtx rtx
assign_stack_local (enum machine_mode mode, HOST_WIDE_INT size, int align) 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_mode mode, HOST_WIDE_INT size, ...@@ -868,11 +880,13 @@ assign_stack_temp_for_type (enum machine_mode mode, HOST_WIDE_INT size,
and round it now. We also make sure ALIGNMENT is at least and round it now. We also make sure ALIGNMENT is at least
BIGGEST_ALIGNMENT. */ BIGGEST_ALIGNMENT. */
gcc_assert (mode != BLKmode || align == BIGGEST_ALIGNMENT); gcc_assert (mode != BLKmode || align == BIGGEST_ALIGNMENT);
p->slot = assign_stack_local (mode, p->slot = assign_stack_local_1 (mode,
(mode == BLKmode (mode == BLKmode
? CEIL_ROUND (size, (int) align / BITS_PER_UNIT) ? CEIL_ROUND (size,
: size), (int) align
align); / BITS_PER_UNIT)
: size),
align, 0);
p->align = align; p->align = align;
......
/* Register Transfer Language (RTL) definitions for GCC /* Register Transfer Language (RTL) definitions for GCC
Copyright (C) 1987, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, Copyright (C) 1987, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
Free Software Foundation, Inc. Free Software Foundation, Inc.
This file is part of GCC. This file is part of GCC.
...@@ -1685,7 +1685,9 @@ extern rtx simplify_subtraction (rtx); ...@@ -1685,7 +1685,9 @@ extern rtx simplify_subtraction (rtx);
/* In function.c */ /* In function.c */
extern rtx assign_stack_local (enum machine_mode, HOST_WIDE_INT, int); 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 (enum machine_mode, HOST_WIDE_INT, int);
extern rtx assign_stack_temp_for_type (enum machine_mode, extern rtx assign_stack_temp_for_type (enum machine_mode,
HOST_WIDE_INT, int, tree); HOST_WIDE_INT, int, tree);
......
2011-02-28 Jakub Jelinek <jakub@redhat.com>
PR middle-end/47893
* gcc.dg/pr47893.c: New test.
2011-02-28 Nicola Pero <nicola.pero@meta-innovation.com> 2011-02-28 Nicola Pero <nicola.pero@meta-innovation.com>
* objc.dg/gnu-api-2-sel.m: Test that sel_getTypedSelector return * objc.dg/gnu-api-2-sel.m: Test that sel_getTypedSelector return
......
/* 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;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment