[backport proposed 4.8 patch to ARM stack alignment code ] Date: Thu, 14 Jun 2012 10:16:42 -0700 From: Roland McGrath Subject: [PATCH] ARM: exclude fixed_regs for stack-alignment save/restore List-Archive: When the ARM compiler needs to ensure the stack pointer stays aligned and it's already doing a multi-register push/pop in the prologue and epilogue, it chooses some arbitrary register to add to the register set in that push and pop just to increase the size of the stack used by 4 bytes. This is presumed to be harmless, since some register that is either call-clobbered or not touched by the function at all is just getting pushed and then the same value popped into it. But if e.g. I use -ffixed-r9 then I think it's a reasonable expectation that no code is generated that touches r9 in any way, shape, or form. (My actual concern is a variant target port still in progress, where the ABI specifies that r9 is reserved, and the system enforces that no instruction may modify r9.) I haven't managed to come up with an isolated test case to demonstrate the bug. Apparently I just don't understand the stack and register pressure requirements that make the compiler get into the situation where it wants to add a random register for alignment padding purposes. I don't have a setup where I can do a proper regression test for ARM. (My system has a /usr/arm-linux-gnueabi/include/ but configuring with --target=arm-linux-gnueabi --with-headers=/usr/arm-linux-gnueabi/include did not succeed in building libgcc.) But the change seems pretty obviously correct IMHO. Thanks, Roland From: Roland McGrath Date: Thu, 14 Jun 2012 16:21:29 -0700 Subject: Re: [PATCH] ARM: exclude fixed_regs for stack-alignment save/restore List-Archive: Here's the version of the change that incorporates Mike's suggestion. Thanks, Roland gcc/ 2012-06-14 Roland McGrath * config/arm/arm.c (arm_get_frame_offsets): Never use a fixed register as the extra register to save/restore for stack-alignment padding. --- gcc-4.7.1/gcc/config/arm/arm.c.~1~ 2012-05-25 11:57:57.000000000 +0200 +++ gcc-4.7.1/gcc/config/arm/arm.c 2012-06-16 14:23:30.000000000 +0200 @@ -16541,7 +16541,12 @@ arm_get_frame_offsets (void) else for (i = 4; i <= (TARGET_THUMB1 ? LAST_LO_REGNUM : 11); i++) { - if ((offsets->saved_regs_mask & (1 << i)) == 0) + /* While the gratuitous register save/restore is ordinarily + harmless, if a register is marked as fixed or global it + may be entirely forbidden by the system ABI to touch it, + so we should avoid those registers. */ + if (!fixed_regs[i] && !global_regs[i] + && (offsets->saved_regs_mask & (1 << i)) == 0) { reg = i; break;