{
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:
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));
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
--- /dev/null
+/* { 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;
+}