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
This commit is contained in:
parent
d154f92719
commit
80a832cd25
6 changed files with 262 additions and 37 deletions
|
@ -1,3 +1,19 @@
|
|||
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>
|
||||
|
||||
PR debug/47283
|
||||
|
|
|
@ -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++)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* Expands front end tree to back end RTL for GCC.
|
||||
Copyright (C) 1987, 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
|
||||
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.
|
||||
|
||||
|
@ -355,14 +355,17 @@ add_frame_space (HOST_WIDE_INT start, HOST_WIDE_INT end)
|
|||
-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 mode, HOST_WIDE_INT size,
|
|||
/* 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 mode, HOST_WIDE_INT size,
|
|||
|
||||
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 mode, HOST_WIDE_INT size,
|
|||
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 mode, HOST_WIDE_INT size,
|
|||
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_mode mode, HOST_WIDE_INT size,
|
|||
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;
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* Register Transfer Language (RTL) definitions for GCC
|
||||
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.
|
||||
|
||||
This file is part of GCC.
|
||||
|
@ -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);
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
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>
|
||||
|
||||
* objc.dg/gnu-api-2-sel.m: Test that sel_getTypedSelector return
|
||||
|
|
187
gcc/testsuite/gcc.dg/pr47893.c
Normal file
187
gcc/testsuite/gcc.dg/pr47893.c
Normal file
|
@ -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;
|
||||
}
|
Loading…
Add table
Reference in a new issue