]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
i386: Guard noreturn no-callee-saved-registers optimization with -mnoreturn-no-callee...
authorJakub Jelinek <jakub@redhat.com>
Fri, 8 Mar 2024 08:18:19 +0000 (09:18 +0100)
committerJakub Jelinek <jakub@redhat.com>
Fri, 8 Mar 2024 08:29:30 +0000 (09:29 +0100)
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.

gcc/config/i386/i386-options.cc
gcc/config/i386/i386.opt
gcc/doc/invoke.texi
gcc/testsuite/gcc.target/i386/pr114097-1.c
gcc/testsuite/gcc.target/i386/pr38534-1.c
gcc/testsuite/gcc.target/i386/pr38534-2.c
gcc/testsuite/gcc.target/i386/pr38534-3.c
gcc/testsuite/gcc.target/i386/pr38534-4.c
gcc/testsuite/gcc.target/i386/pr38534-5.c
gcc/testsuite/gcc.target/i386/pr38534-6.c
gcc/testsuite/gcc.target/i386/stack-check-17.c

index 2f8c85f66d4362887eaaf82a6ba4a213251af46c..3cc147fa70c3365eec71d712c3249c3e564f15b7 100644 (file)
@@ -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)
index 5b4f1bff25f47973ce44ce35e255a9653b95bdca..d5f793a9e8b080b77bcb310a3ea7bc804be980ca 100644 (file)
@@ -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
index 2390d478121cc85e001a635fa13804c36b8b3258..c0d604a2c5cb5df221218c19b6f73ba113a53857 100644 (file)
@@ -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
index feeb916557048b38323d9c7c7771ca5796ed79db..b8edfaaf25b80360d0abfa81e9e7e0c9608b4285 100644 (file)
@@ -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
 
index c73c8d23288e21daafe8da483ecee0e6be94b836..795174f4eb3639e030eefa3c1871252cd7427f6b 100644 (file)
@@ -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
 
index 0dc8720dc894e26bd029edc23c231fff7b86db32..2d8a4b6a724091456885d207c191e89d0c07e4b3 100644 (file)
@@ -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));
index 554c594feb7dd2f46fd7ae6e14b3024b0a0bfc41..9ab2f5dca395710cb8da699b44463434f2703a34 100644 (file)
@@ -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;
index 8073aac01fcaa4c36bbe81d10fa3c03d15d0b78f..d4726c3613779da921f3efaf080d8434f682cea5 100644 (file)
@@ -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));
index 91c0c0f8c593bf7e2ee3939712a0c5d52dda61bc..443864598954aad6b35333b4f99561d6a3a58576 100644 (file)
@@ -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
 
index cf1463a9c6666502d47f2ae626fd998da9815c83..266c8e7f1de750c79c89ed4522d63890830ac478 100644 (file)
@@ -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
 
index 648572e5ebd24751f952c705add2f5484e7ee3c1..924a459c4e28f6df7fc41c0de154a88d8acd109f 100644 (file)
@@ -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*" } { "" } } */