I am testing this patch.  OK for master if there are no regressions?

-- 
H.J.
In 64-bit mode, in preserve_none functions, we can use any register for
DRAP, except for R12, R13, R14, R15, DI, SI (which are used for parameter
passing), SP and BP.  Use R11 instead.  Since no-callee-saved functions
don't use R10 nor R13 for parameter passing, they are OK for DRAP.  In
32-bit mode, since preserve_none functions don't change parameter passing,
the existing choice is OK.

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.
(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]>
From 192b51b6654f81da6fbaaa69924d30f46d06bbfd Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <[email protected]>
Date: Sun, 10 May 2026 18:36:26 +0800
Subject: [PATCH v3] x86-64: Use R11 for DRAP register in preserve_none
 functions

In 64-bit mode, in preserve_none functions, we can use any register for
DRAP, except for R12, R13, R14, R15, DI, SI (which are used for parameter
passing), SP and BP.  Use R11 instead.  Since no-callee-saved functions
don't use R10 nor R13 for parameter passing, they are OK for DRAP.  In
32-bit mode, since preserve_none functions don't change parameter passing,
the existing choice is OK.

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.
	(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]>
---
 gcc/config/i386/i386.cc                    | 16 ++++++++++
 gcc/testsuite/gcc.target/i386/pr120870-1.c | 35 ++++++++++++++++++++++
 gcc/testsuite/gcc.target/i386/pr120870-2.c |  6 ++++
 3 files changed, 57 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/i386/pr120870-1.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr120870-2.c

diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
index 9aecd51119f..46bef11d3f8 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:
@@ -7946,6 +7953,15 @@ find_drap_reg (void)
      registers.  */
   if (TARGET_64BIT)
     {
+      /* In preserve_none functions, we can use any register for DRAP,
+	 except for R12_REG, R13_REG, R14_REG, R15_REG, DI_REG, SI_REG
+	 (which are used for parameter passing), SP_REG and BP_REG.
+	 Pick R11_REG instead.  Since no-callee-saved functions don't
+	 use R10_REG nor R13_REG for parameter passing, they are OK
+	 for DRAP.  */
+      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 00000000000..31d38391133
--- /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)
+{
+}
+
+__attribute__ ((preserve_none)) 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 00000000000..7e68718d81a
--- /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"
-- 
2.54.0

Reply via email to