Bug 107248 - wrong scheduling of stack adjustment in leaf function at -O2
Summary: wrong scheduling of stack adjustment in leaf function at -O2
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: target (show other bugs)
Version: 7.1.0
: P3 normal
Target Milestone: 10.5
Assignee: Eric Botcazou
URL:
Keywords: wrong-code
Depends on:
Blocks:
 
Reported: 2022-10-13 13:21 UTC by Dennis Borde
Modified: 2023-01-03 08:58 UTC (History)
2 users (show)

See Also:
Host:
Target: sparc-*-*
Build:
Known to work:
Known to fail:
Last reconfirmed: 2022-10-13 00:00:00


Attachments
source code to trigger the bug (144 bytes, text/plain)
2022-10-13 13:21 UTC, Dennis Borde
Details
gcc -v output (946 bytes, text/plain)
2022-10-13 13:25 UTC, Dennis Borde
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Dennis Borde 2022-10-13 13:21:16 UTC
Created attachment 53700 [details]
source code to trigger the bug

Environment: GCC V7.1.0, Sparc V8, RTEMS V4.8.0

When compiling with optimization level -O2 (including -fschedule-insns2) the compiler generates code like this:

(1) add %sp, 0x50, %g1
(2) add %sp, 0x50, %sp
(3) add %g1, %o0, %o0
(4) ld [ %o0 + -8 ], %o0

In line (2) the stack pointer is moved by 80 bytes forward, which means memory is "freed".
In line (4) it accesses the "freed" stack memory.

When an interrupt occurs in between line (2) and (4) it will overwrite the stack data and "corrupt" it for the reading in line (4).

E.g.: As part of the RTEMS _ISR_Handler() the interrupt stack frame is stored (see label symbol save_isf). For more information see RTEMS source code. However, this is just one example to show the order of instructions above is not safe. It is not important for the bug itself.

Work-around: Compile with -fno-schedule-insns2

With the work-around the generated code looks like this:
(1) add %sp, 0x50, %g1
(2) add %g1, %o0, %o0
(3) ld [ %o0 + -8 ], %o0
(4) add %sp, 0x50, %sp 

Here the stack memory is "freed" (4) after the access (3).

It seems to be related to
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=38644
Comment 1 Dennis Borde 2022-10-13 13:25:58 UTC
Created attachment 53701 [details]
gcc -v output
Comment 2 Andrew Pinski 2022-10-13 20:28:43 UTC
Looks like for sparc_leaf_function_p, there is a missing a emit_insn (gen_frame_blockage ()) .

Which was added in the non leaf case with r0-114040-ge98b1defdd2c6b .
Comment 3 Eric Botcazou 2022-10-13 22:09:42 UTC
Yes, it's the same bug as on ARM and MIPS, but one decade later...
Comment 4 Eric Botcazou 2022-10-13 22:10:04 UTC
Fixing.
Comment 5 GCC Commits 2022-10-14 09:56:48 UTC
The master branch has been updated by Eric Botcazou <ebotcazou@gcc.gnu.org>:

https://gcc.gnu.org/g:e39b170695a161feba7401b7d21d824db9ee1f8f

commit r13-3296-ge39b170695a161feba7401b7d21d824db9ee1f8f
Author: Eric Botcazou <ebotcazou@adacore.com>
Date:   Fri Oct 14 11:52:04 2022 +0200

    Fix PR target/107248
    
    This is the infamous PR rtl-optimization/38644 rearing its ugly head for
    leaf functions on SPARC more than a decade later...  Richard E.'s generic
    solution has never been implemented so let's do as other RISC back-ends did.
    
    gcc/
            PR target/107248
            * config/sparc/sparc.cc (sparc_expand_prologue): Emit a frame
            blockage for leaf functions.
            (sparc_flat_expand_prologue): Emit frame instead of full blockage.
            (sparc_expand_epilogue): Emit a frame blockage for leaf functions.
            (sparc_flat_expand_epilogue): Emit frame instead of full blockage.
Comment 6 GCC Commits 2022-10-14 09:57:45 UTC
The releases/gcc-12 branch has been updated by Eric Botcazou <ebotcazou@gcc.gnu.org>:

https://gcc.gnu.org/g:a5a6598d5b1d29741993371310c0bb8ca57e190c

commit r12-8831-ga5a6598d5b1d29741993371310c0bb8ca57e190c
Author: Eric Botcazou <ebotcazou@adacore.com>
Date:   Fri Oct 14 11:52:04 2022 +0200

    Fix PR target/107248
    
    This is the infamous PR rtl-optimization/38644 rearing its ugly head for
    leaf functions on SPARC more than a decade later...  Richard E.'s generic
    solution has never been implemented so let's do as other RISC back-ends did.
    
    gcc/
            PR target/107248
            * config/sparc/sparc.cc (sparc_expand_prologue): Emit a frame
            blockage for leaf functions.
            (sparc_flat_expand_prologue): Emit frame instead of full blockage.
            (sparc_expand_epilogue): Emit a frame blockage for leaf functions.
            (sparc_flat_expand_epilogue): Emit frame instead of full blockage.
Comment 7 GCC Commits 2022-10-14 09:58:42 UTC
The releases/gcc-11 branch has been updated by Eric Botcazou <ebotcazou@gcc.gnu.org>:

https://gcc.gnu.org/g:3f4b65df625edae3e8829718af721ad2330b3f22

commit r11-10311-g3f4b65df625edae3e8829718af721ad2330b3f22
Author: Eric Botcazou <ebotcazou@adacore.com>
Date:   Fri Oct 14 11:52:04 2022 +0200

    Fix PR target/107248
    
    This is the infamous PR rtl-optimization/38644 rearing its ugly head for
    leaf functions on SPARC more than a decade later...  Richard E.'s generic
    solution has never been implemented so let's do as other RISC back-ends did.
    
    gcc/
            PR target/107248
            * config/sparc/sparc.c (sparc_expand_prologue): Emit a frame
            blockage for leaf functions.
            (sparc_flat_expand_prologue): Emit frame instead of full blockage.
            (sparc_expand_epilogue): Emit a frame blockage for leaf functions.
            (sparc_flat_expand_epilogue): Emit frame instead of full blockage.
Comment 8 GCC Commits 2022-10-14 10:00:03 UTC
The releases/gcc-10 branch has been updated by Eric Botcazou <ebotcazou@gcc.gnu.org>:

https://gcc.gnu.org/g:d0ef37c35b7ff7324b4567652380f32079d46088

commit r10-11034-gd0ef37c35b7ff7324b4567652380f32079d46088
Author: Eric Botcazou <ebotcazou@adacore.com>
Date:   Fri Oct 14 11:52:04 2022 +0200

    Fix PR target/107248
    
    This is the infamous PR rtl-optimization/38644 rearing its ugly head for
    leaf functions on SPARC more than a decade later...  Richard E.'s generic
    solution has never been implemented so let's do as other RISC back-ends did.
    
    gcc/
            PR target/107248
            * config/sparc/sparc.c (sparc_expand_prologue): Emit a frame
            blockage for leaf functions.
            (sparc_flat_expand_prologue): Emit frame instead of full blockage.
            (sparc_expand_epilogue): Emit a frame blockage for leaf functions.
            (sparc_flat_expand_epilogue): Emit frame instead of full blockage.
Comment 9 Eric Botcazou 2022-10-14 10:03:37 UTC
Fixed on all active branches, but the fix should be backportable onto older release branches without any change.  Thanks for reporting the problem.
Comment 10 Dennis Borde 2022-10-17 11:05:43 UTC
Much more important: Thanks for fixing it :-)
Comment 11 Eric Botcazou 2022-10-25 08:00:43 UTC
> Much more important: Thanks for fixing it :-)

You're welcome.  It looks like -mtune=leon or -mtune-leon3 can mitigate it.
Comment 12 Daniel Cederman 2023-01-03 08:30:09 UTC
Just to make it clear, since we have had customers asking about it, it is still possible to trigger this issue with -mtune=leon or -mtune-leon3, though it might make it less likely to happen.
Comment 13 Eric Botcazou 2023-01-03 08:58:24 UTC
> Just to make it clear, since we have had customers asking about it, it is
> still possible to trigger this issue with -mtune=leon or -mtune-leon3,
> though it might make it less likely to happen.

Very likely not, but proving it would be quite hard.