On 12/18/18 3:16 PM, Bernd Edlinger wrote: > Hi, > > while I looked closely at the asm statement in the gdb, > I realized that the SP clobber forces the function to use > the frame pointer, and prevents the red zone. That > makes the push / pop sequence in the asm statement safe > to use, as long as the stack is restored to the original > value. That can be a quite useful feature. And that might > have been the reason why the rsp clobber was chosen in the > first place. > > This seems to work for all targets, but it started to work > this way with gcc-6, all versions before that do ignore > this clobber stmt (as confirmed by godbolt). > > The clobber stmt make the LRA register allocator switch > frame_pointer_needed to 1, and therefore in all likelihood, > all targets should use that consistently. > > On 12/17/18 12:47 PM, Richard Sandiford wrote: >> Dimitar Dimitrov <dimi...@dinux.eu> writes: >>> On Sun, Dec 16 2018 at 14:36:26 EET Bernd Edlinger wrote: >>>> Hi, >>>> >>>> if I understood that right, then clobbering sp is and has always been >>>> ignored. >> >> PR77904 was about the clobber not being ignored, so the behaviour >> hasn't been consistent. >> > > I think 77904 was a fall-out from the change in the LRA register allocator. > The patch referenced in the PR does simply honor frame_pointer_needed, > which changed with gcc-6, and caused a regression on arm. > >> I'm also not sure it was always ignored in recent sources. The clobber >> does get added to the associated rtl insn, and it'd be surprising if >> that never had an effect. >> >>>> If that is right, then I would much prefer a warning, that says exactly >>>> that, because that would also help to understand why removing that clobber >>>> statement is safe even for old gcc versions. >> >> If the asm does leave sp with a different value, then it's never been safe, >> regardless of the gcc version. That's why an error seems more appropriate. >> >>> Thank you. Looks like general consensus is to have a warning. See attached >>> patch that switches the error to a warning. >> >> I don't think there's a good reason to treat this differently from the >> preexisting PIC register error. If the argument for making it a warning >> rather than an error is that the asm might happen to work by accident, >> then the same is true for the PIC register. >> > > In the light of my findings, I believe with a good warning message that > explains that the SP needs to be restored to the previous value, that > is a useful feature, that enables the asm statement to push temporary > values on the stack which would not be safe otherwise. > > Therefore I propose not to rip it out at this time. > See my proposed patch. What do you think? > > Is it OK? > >
Oops, previous version missed the fix of the PR77904 test case, which is currently broken too. Bernd-
2018-12-18 Bernd Edlinger <bernd.edlin...@hotmail.de> * cfgexpand.c (asm_clobber_reg_is_valid): Emit only a warning together with an information message when the stack pointer is clobbered. testsuite: 2018-12-18 Bernd Edlinger <bernd.edlin...@hotmail.de> * gcc.target/arm/pr77904.c: Adjust test. * gcc.target/i386/pr52813.c: Adjust test. Index: gcc/cfgexpand.c =================================================================== --- gcc/cfgexpand.c (revision 267164) +++ gcc/cfgexpand.c (working copy) @@ -2854,6 +2854,7 @@ tree_conflicts_with_clobbers_p (tree t, HARD_REG_S asm clobber operand. Some HW registers cannot be saved/restored, hence they should not be clobbered by asm statements. */ + static bool asm_clobber_reg_is_valid (int regno, int nregs, const char *regname) { @@ -2872,11 +2873,23 @@ asm_clobber_reg_is_valid (int regno, int nregs, co error ("PIC register clobbered by %qs in %<asm%>", regname); is_valid = false; } - /* Clobbering the STACK POINTER register is an error. */ + /* Clobbering the STACK POINTER register is likely an error. + However it is useful to force the use of frame pointer and prevent + the use of red zone. Thus without this clobber, pushing temporary + values onto the stack might clobber the red zone or make stack based + memory references invalid. */ if (overlaps_hard_reg_set_p (regset, Pmode, STACK_POINTER_REGNUM)) { - error ("Stack Pointer register clobbered by %qs in %<asm%>", regname); - is_valid = false; + if (warning (0, "Stack Pointer register clobbered by %qs in %<asm%>", + regname)) + { + inform (input_location, + "This does likely not do what you would expect." + " The Stack Pointer register still needs to be restored to" + " the previous value, however it is safe to push values onto" + " the stack, when they are popped again from the stack" + " before the asm statement terminates"); + } } return is_valid; Index: gcc/testsuite/gcc.target/arm/pr77904.c =================================================================== --- gcc/testsuite/gcc.target/arm/pr77904.c (revision 267164) +++ gcc/testsuite/gcc.target/arm/pr77904.c (working copy) @@ -4,7 +4,7 @@ __attribute__ ((noinline, noclone)) void clobber_sp (void) { - __asm volatile ("" : : : "sp"); + __asm volatile ("" : : : "sp"); /* { dg-warning "Stack Pointer register clobbered" } */ } int Index: gcc/testsuite/gcc.target/i386/pr52813.c =================================================================== --- gcc/testsuite/gcc.target/i386/pr52813.c (revision 267164) +++ gcc/testsuite/gcc.target/i386/pr52813.c (working copy) @@ -1,9 +1,10 @@ /* Ensure that stack pointer cannot be an asm clobber. */ /* { dg-do compile { target { ! ia32 } } } */ -/* { dg-options "-O2" } */ +/* { dg-options "-O3 -fomit-frame-pointer" } */ void test1 (void) { - asm volatile ("" : : : "%esp"); /* { dg-error "Stack Pointer register clobbered" } */ + asm volatile ("" : : : "%rsp"); /* { dg-warning "Stack Pointer register clobbered" } */ } +/* { dg-final { scan-assembler "(?n)pushq.*%rbp" } } */