Hi,
I found below regression tests are failed on trunk for cortex-m0/Os:
FAIL: gcc.c-torture/execute/pr45070.c execution, -Os
FAIL: gcc.dg/compat/struct-layout-1 c_compat_x_tst.o-c_compat_y_tst.o
execute
FAIL: gcc.dg/compat/struct-return-2 c_compat_x_tst.o-c_compat_y_tst.o
execute
FAIL: tmpdir-gcc.dg-struct-layout-1/t001 c_compat_x_tst.o-c_compat_y_tst.o
execute
WARNING: program timed out.
FAIL: tmpdir-gcc.dg-struct-layout-1/t002 c_compat_x_tst.o-c_compat_y_tst.o
execute
FAIL: tmpdir-gcc.dg-struct-layout-1/t024 c_compat_x_tst.o-c_compat_y_tst.o
execute
FAIL: tmpdir-gcc.dg-struct-layout-1/t025 c_compat_x_tst.o-c_compat_y_tst.o
execute
FAIL: tmpdir-gcc.dg-struct-layout-1/t027 c_compat_x_tst.o-c_compat_y_tst.o
execute
FAIL: tmpdir-gcc.dg-struct-layout-1/t028 c_compat_x_tst.o-c_compat_y_tst.o
execute
Seems the patch for pr45070 does not cover Thumb1 instruction set, here
comes this patch fixing the issue.
It is caused by wrong epilogue generated for cortex-m0/Os. In function
thumb1_extra_regs_pushed, gcc calculates reg_base as following, which does
not honor return value of size less than 4 bytes, resulting in wrong pop
sequences.
reg_base = arm_size_return_regs () / UNITS_PER_WORD;
I ran regression test with/without Os for cortex-m0 and everything is ok.
Ok for trunk and 4.7/4.6 release branches?
Thanks.
2012-09-04 Bin Cheng <bin.ch...@arm.com>
PR target/45070
* config/arm/arm.c (thumb1_extra_regs_pushed): Handle return value
of size
less than 4 bytes by using macro ARM_NUM_INTS.
(thumb1_unexpanded_epilogue): Use macro ARM_NUM_INTS.
Index: gcc/config/arm/arm.c
===================================================================
--- gcc/config/arm/arm.c (revision 190830)
+++ gcc/config/arm/arm.c (working copy)
@@ -21862,7 +21862,7 @@ thumb1_extra_regs_pushed (arm_stack_offsets *offse
unsigned long l_mask = live_regs_mask & (for_prologue ? 0x40ff : 0xff);
/* Then count how many other high registers will need to be pushed. */
unsigned long high_regs_pushed = bit_count (live_regs_mask & 0x0f00);
- int n_free, reg_base;
+ int n_free, reg_base, size;
if (!for_prologue && frame_pointer_needed)
amount = offsets->locals_base - offsets->saved_regs;
@@ -21901,7 +21901,8 @@ thumb1_extra_regs_pushed (arm_stack_offsets *offse
n_free = 0;
if (!for_prologue)
{
- reg_base = arm_size_return_regs () / UNITS_PER_WORD;
+ size = arm_size_return_regs ();
+ reg_base = ARM_NUM_INTS (size);
live_regs_mask >>= reg_base;
}
@@ -21955,8 +21956,7 @@ thumb1_unexpanded_epilogue (void)
if (extra_pop > 0)
{
unsigned long extra_mask = (1 << extra_pop) - 1;
- live_regs_mask |= extra_mask << ((size + UNITS_PER_WORD - 1)
- / UNITS_PER_WORD);
+ live_regs_mask |= extra_mask << ARM_NUM_INTS (size);
}
/* The prolog may have pushed some high registers to use as