diff options
author | Jakub Jelinek <jakub@redhat.com> | 2024-03-08 09:18:19 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2024-03-08 09:29:30 +0100 |
commit | a307a26e8b392ba65edfdae15489556b7701db81 (patch) | |
tree | e20f2f6fe8a7ffa2cf266fb8209fb5f9cf31c625 /gcc | |
parent | eed4e541711ab4ae7783f75dd132e2acca71fdb9 (diff) | |
download | gcc-a307a26e8b392ba65edfdae15489556b7701db81.zip gcc-a307a26e8b392ba65edfdae15489556b7701db81.tar.gz gcc-a307a26e8b392ba65edfdae15489556b7701db81.tar.bz2 |
i386: Guard noreturn no-callee-saved-registers optimization with -mnoreturn-no-callee-saved-registers [PR38534]
The following patch hides the noreturn no_callee_saved_registers (except bp)
optimization with a not enabled by default option.
The reason is that most noreturn functions should be called just once in a
program (unless they are recursive or invoke longjmp or similar, for exceptions
we already punt), so it isn't that essential to save a few instructions in their
prologue, but more importantly because it interferes with debugging.
And unlike most other optimizations, doesn't actually make it harder to debug
the given function, which can be solved by recompiling the given function if
it is too hard to debug, but makes it harder to debug the callers of that
noreturn function. Those can be from a different translation unit, different
binary or even different package, so if e.g. glibc abort needs to use all
of the callee saved registers (%rbx, %rbp, %r12, %r13, %r14, %r15), debugging
any programs which abort will be harder because any DWARF expressions which
use those registers will be optimized out, not just in the immediate caller,
but in other callers as well until some frame restores a particular register
from some stack slot.
2024-03-08 Jakub Jelinek <jakub@redhat.com>
PR target/38534
* config/i386/i386.opt (mnoreturn-no-callee-saved-registers): New
option.
* config/i386/i386-options.cc (ix86_set_func_type): Don't use
TYPE_NO_CALLEE_SAVED_REGISTERS_EXCEPT_BP unless
ix86_noreturn_no_callee_saved_registers is enabled.
* doc/invoke.texi (-mnoreturn-no-callee-saved-registers): Document.
* gcc.target/i386/pr38534-1.c: Add -mnoreturn-no-callee-saved-registers
to dg-options.
* gcc.target/i386/pr38534-2.c: Likewise.
* gcc.target/i386/pr38534-3.c: Likewise.
* gcc.target/i386/pr38534-4.c: Likewise.
* gcc.target/i386/pr38534-5.c: Likewise.
* gcc.target/i386/pr38534-6.c: Likewise.
* gcc.target/i386/pr114097-1.c: Likewise.
* gcc.target/i386/stack-check-17.c: Likewise.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/config/i386/i386-options.cc | 6 | ||||
-rw-r--r-- | gcc/config/i386/i386.opt | 4 | ||||
-rw-r--r-- | gcc/doc/invoke.texi | 10 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr114097-1.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr38534-1.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr38534-2.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr38534-3.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr38534-4.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr38534-5.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr38534-6.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/stack-check-17.c | 2 |
11 files changed, 26 insertions, 10 deletions
diff --git a/gcc/config/i386/i386-options.cc b/gcc/config/i386/i386-options.cc index 2f8c85f..3cc147f 100644 --- a/gcc/config/i386/i386-options.cc +++ b/gcc/config/i386/i386-options.cc @@ -3384,7 +3384,8 @@ ix86_set_func_type (tree fndecl) { /* No need to save and restore callee-saved registers for a noreturn function with nothrow or compiled with -fno-exceptions unless when - compiling with -O0 or -Og. So that backtrace works for those at least + compiling with -O0 or -Og, except that it interferes with debugging + of callers. So that backtrace works for those at least in most cases, save the bp register if it is used, because it often is used in callers to compute CFA. @@ -3401,7 +3402,8 @@ ix86_set_func_type (tree fndecl) if (lookup_attribute ("no_callee_saved_registers", TYPE_ATTRIBUTES (TREE_TYPE (fndecl)))) no_callee_saved_registers = TYPE_NO_CALLEE_SAVED_REGISTERS; - else if (TREE_THIS_VOLATILE (fndecl) + else if (ix86_noreturn_no_callee_saved_registers + && TREE_THIS_VOLATILE (fndecl) && optimize && !optimize_debug && (TREE_NOTHROW (fndecl) || !flag_exceptions) diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt index 5b4f1bf..d5f793a 100644 --- a/gcc/config/i386/i386.opt +++ b/gcc/config/i386/i386.opt @@ -659,6 +659,10 @@ mstore-max= Target RejectNegative Joined Var(ix86_store_max) Enum(prefer_vector_width) Init(PVW_NONE) Save Maximum number of bits that can be stored to memory efficiently. +mnoreturn-no-callee-saved-registers +Target Var(ix86_noreturn_no_callee_saved_registers) +Optimize noreturn functions by not saving callee-saved registers used in the function. + ;; ISA support m32 diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 2390d47..c0d604a 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -1450,6 +1450,7 @@ See RS/6000 and PowerPC Options. -mvzeroupper -mprefer-avx128 -mprefer-vector-width=@var{opt} -mpartial-vector-fp-math -mmove-max=@var{bits} -mstore-max=@var{bits} +-mnoreturn-no-callee-saved-registers -mmmx -msse -msse2 -msse3 -mssse3 -msse4.1 -msse4.2 -msse4 -mavx -mavx2 -mavx512f -mavx512pf -mavx512er -mavx512cd -mavx512vl -mavx512bw -mavx512dq -mavx512ifma -mavx512vbmi -msha -maes @@ -35397,6 +35398,15 @@ Prefer 256-bit vector width for instructions. Prefer 512-bit vector width for instructions. @end table +@opindex mnoreturn-no-callee-saved-registers +@item -mnoreturn-no-callee-saved-registers +This option optimizes functions with @code{noreturn} attribute or +@code{_Noreturn} specifier by not saving in the function prologue callee-saved +registers which are used in the function (except for the @code{BP} +register). This option can interfere with debugging of the caller of the +@code{noreturn} function or any function further up in the call stack, so it +is not enabled by default. + @opindex mcx16 @item -mcx16 This option enables GCC to generate @code{CMPXCHG16B} instructions in 64-bit diff --git a/gcc/testsuite/gcc.target/i386/pr114097-1.c b/gcc/testsuite/gcc.target/i386/pr114097-1.c index feeb916..b8edfaa 100644 --- a/gcc/testsuite/gcc.target/i386/pr114097-1.c +++ b/gcc/testsuite/gcc.target/i386/pr114097-1.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -mtune-ctrl=^prologue_using_move,^epilogue_using_move -fomit-frame-pointer" } */ +/* { dg-options "-O2 -mtune-ctrl=^prologue_using_move,^epilogue_using_move -fomit-frame-pointer -mnoreturn-no-callee-saved-registers" } */ #define ARRAY_SIZE 256 diff --git a/gcc/testsuite/gcc.target/i386/pr38534-1.c b/gcc/testsuite/gcc.target/i386/pr38534-1.c index c73c8d2..795174f 100644 --- a/gcc/testsuite/gcc.target/i386/pr38534-1.c +++ b/gcc/testsuite/gcc.target/i386/pr38534-1.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -mtune-ctrl=^prologue_using_move,^epilogue_using_move -fomit-frame-pointer" } */ +/* { dg-options "-O2 -mtune-ctrl=^prologue_using_move,^epilogue_using_move -fomit-frame-pointer -mnoreturn-no-callee-saved-registers" } */ #define ARRAY_SIZE 256 diff --git a/gcc/testsuite/gcc.target/i386/pr38534-2.c b/gcc/testsuite/gcc.target/i386/pr38534-2.c index 0dc8720..2d8a4b6 100644 --- a/gcc/testsuite/gcc.target/i386/pr38534-2.c +++ b/gcc/testsuite/gcc.target/i386/pr38534-2.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -mtune-ctrl=^prologue_using_move,^epilogue_using_move -fomit-frame-pointer" } */ +/* { dg-options "-O2 -mtune-ctrl=^prologue_using_move,^epilogue_using_move -fomit-frame-pointer -mnoreturn-no-callee-saved-registers" } */ extern void bar (void) __attribute__ ((no_callee_saved_registers)); extern void fn (void) __attribute__ ((noreturn)); diff --git a/gcc/testsuite/gcc.target/i386/pr38534-3.c b/gcc/testsuite/gcc.target/i386/pr38534-3.c index 554c594..9ab2f5d 100644 --- a/gcc/testsuite/gcc.target/i386/pr38534-3.c +++ b/gcc/testsuite/gcc.target/i386/pr38534-3.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -mtune-ctrl=^prologue_using_move,^epilogue_using_move -fomit-frame-pointer" } */ +/* { dg-options "-O2 -mtune-ctrl=^prologue_using_move,^epilogue_using_move -fomit-frame-pointer -mnoreturn-no-callee-saved-registers" } */ typedef void (*fn_t) (void) __attribute__ ((no_callee_saved_registers)); extern fn_t bar; diff --git a/gcc/testsuite/gcc.target/i386/pr38534-4.c b/gcc/testsuite/gcc.target/i386/pr38534-4.c index 8073aac..d4726c3 100644 --- a/gcc/testsuite/gcc.target/i386/pr38534-4.c +++ b/gcc/testsuite/gcc.target/i386/pr38534-4.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -mtune-ctrl=^prologue_using_move,^epilogue_using_move -fomit-frame-pointer" } */ +/* { dg-options "-O2 -mtune-ctrl=^prologue_using_move,^epilogue_using_move -fomit-frame-pointer -mnoreturn-no-callee-saved-registers" } */ typedef void (*fn_t) (void) __attribute__ ((no_callee_saved_registers)); extern void fn (void) __attribute__ ((noreturn)); diff --git a/gcc/testsuite/gcc.target/i386/pr38534-5.c b/gcc/testsuite/gcc.target/i386/pr38534-5.c index 91c0c0f..4438645 100644 --- a/gcc/testsuite/gcc.target/i386/pr38534-5.c +++ b/gcc/testsuite/gcc.target/i386/pr38534-5.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O0 -mtune-ctrl=^prologue_using_move,^epilogue_using_move" } */ +/* { dg-options "-O0 -mtune-ctrl=^prologue_using_move,^epilogue_using_move -mnoreturn-no-callee-saved-registers" } */ #define ARRAY_SIZE 256 diff --git a/gcc/testsuite/gcc.target/i386/pr38534-6.c b/gcc/testsuite/gcc.target/i386/pr38534-6.c index cf1463a..266c8e7 100644 --- a/gcc/testsuite/gcc.target/i386/pr38534-6.c +++ b/gcc/testsuite/gcc.target/i386/pr38534-6.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -mtune-ctrl=^prologue_using_move,^epilogue_using_move" } */ +/* { dg-options "-O2 -mtune-ctrl=^prologue_using_move,^epilogue_using_move -mnoreturn-no-callee-saved-registers" } */ #define ARRAY_SIZE 256 diff --git a/gcc/testsuite/gcc.target/i386/stack-check-17.c b/gcc/testsuite/gcc.target/i386/stack-check-17.c index 648572e..924a459 100644 --- a/gcc/testsuite/gcc.target/i386/stack-check-17.c +++ b/gcc/testsuite/gcc.target/i386/stack-check-17.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fstack-clash-protection -mtune=generic -fomit-frame-pointer" } */ +/* { dg-options "-O2 -fstack-clash-protection -mtune=generic -fomit-frame-pointer -mnoreturn-no-callee-saved-registers" } */ /* { dg-require-effective-target supports_stack_clash_protection } */ /* { dg-skip-if "" { *-*-* } { "-fstack-protector*" } { "" } } */ |