https://gcc.gnu.org/g:9d5efd46b3329f6b7b0eb2983f317687899caba6

commit r17-487-g9d5efd46b3329f6b7b0eb2983f317687899caba6
Author: H.J. Lu <[email protected]>
Date:   Sun May 10 18:36:26 2026 +0800

    x86-64: Use R11 for DRAP register in preserve_none functions
    
    In 64-bit mode, for preserve_none functions, DRAP may use any register
    except AX, R12–R15, DI, SI (argument registers), SP, and BP. Use R11.
    In non-callee-saved functions, R10 and R13 are also available since they
    are not used for parameter passing.  In 32-bit mode, preserve_none does
    not affect parameter passing, so the current approach remains valid.
    
    DRAP register is used to restore stack pointer in epilogue for stack
    realignment.  Always save and restore DRAP register between prologue
    and epilogue so that stack pointer can be restored.
    
    Tested with CPython 3.14.4 on Linux/x86-64.
    
    gcc/
    
            PR target/120870
            * config/i386/i386.cc (ix86_save_reg): Return true for DRAP
            register early at entry.
            (find_drap_reg): Use R11_REG in preserve_none functions in
            64-bit mode.
    
    gcc/testsuite/
    
            PR target/120870
            * gcc.target/i386/pr120870-1.c: New test.
            * gcc.target/i386/pr120870-2.c: Likewise.
    
    Signed-off-by: H.J. Lu <[email protected]>
    Co-Authored-By: Uros Bizjak <[email protected]>

Diff:
---
 gcc/config/i386/i386.cc                    | 17 ++++++++++-----
 gcc/testsuite/gcc.target/i386/pr120870-1.c | 35 ++++++++++++++++++++++++++++++
 gcc/testsuite/gcc.target/i386/pr120870-2.c |  6 +++++
 3 files changed, 53 insertions(+), 5 deletions(-)

diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
index 9aecd51119f3..2744c7495780 100644
--- a/gcc/config/i386/i386.cc
+++ b/gcc/config/i386/i386.cc
@@ -6776,6 +6776,13 @@ ix86_save_reg (unsigned int regno, bool maybe_eh_return, 
bool ignore_outlined)
 {
   rtx reg;
 
+  /* Save and restore DRAP register between prologue and epilogue so
+     that stack pointer can be restored.  */
+  if (crtl->drap_reg
+      && regno == REGNO (crtl->drap_reg)
+      && !cfun->machine->no_drap_save_restore)
+    return true;
+
   switch (cfun->machine->call_saved_registers)
     {
     case TYPE_DEFAULT_CALL_SAVED_REGISTERS:
@@ -6851,11 +6858,6 @@ ix86_save_reg (unsigned int regno, bool maybe_eh_return, 
bool ignore_outlined)
        return false;
     }
 
-  if (crtl->drap_reg
-      && regno == REGNO (crtl->drap_reg)
-      && !cfun->machine->no_drap_save_restore)
-    return true;
-
   return (df_regs_ever_live_p (regno)
          && !call_used_or_fixed_reg_p (regno)
          && (regno != HARD_FRAME_POINTER_REGNUM || !frame_pointer_needed));
@@ -7946,6 +7948,11 @@ find_drap_reg (void)
      registers.  */
   if (TARGET_64BIT)
     {
+      /* In preserve_none functions, any register can be used for DRAP,
+        except AX, R12–R15, DI, SI (argument registers), SP, and BP.  */
+      if (cfun->machine->call_saved_registers == TYPE_PRESERVE_NONE)
+       return R11_REG;
+
       /* Use R13 for nested function or function need static chain.
         Since function with tail call may use any caller-saved
         registers in epilogue, DRAP must not use caller-saved
diff --git a/gcc/testsuite/gcc.target/i386/pr120870-1.c 
b/gcc/testsuite/gcc.target/i386/pr120870-1.c
new file mode 100644
index 000000000000..21e38d2b8877
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr120870-1.c
@@ -0,0 +1,35 @@
+/* { dg-do run } */
+/* { dg-options "-O0 -march=x86-64-v3" } */
+
+void
+ext (long a, long b, long c, long d, long e, long f, long g)
+{
+}
+
+void
+tail (long a, long b)
+{
+}
+
+__attribute__ ((preserve_none)) void
+caller (long a, long b, long c, long d, long e, long f, long g)
+{
+  __attribute__ ((aligned (32))) long x[4]; // for stack alignment
+  ext (a, b, c, d, e, f, g);
+  __attribute__ ((musttail)) return tail (a + b, b + c);
+}
+
+__attribute__ ((noipa))
+static void
+do_test ()
+{
+  caller (1, 2, 3, 4, 5, 6, 7);
+}
+
+int
+main (void)
+{
+  if (__builtin_cpu_supports ("x86-64-v3"))
+    do_test ();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr120870-2.c 
b/gcc/testsuite/gcc.target/i386/pr120870-2.c
new file mode 100644
index 000000000000..7e68718d81a3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr120870-2.c
@@ -0,0 +1,6 @@
+/* { dg-do run } */
+/* { dg-options "-O0 -march=x86-64-v3" } */
+
+#define preserve_none no_callee_saved_registers
+
+#include "pr120870-1.c"

Reply via email to