On Wed, May 13, 2026 at 7:11 PM Richard Sandiford <[email protected]> wrote: > > "H.J. Lu" <[email protected]> writes: > > Implement TARGET_FNTYPE_ABI to avoid spills of callee-saved registers > > when calling functions with no_caller_saved_registers attribute. > > > > 1. For functions with no_callee_saved_registers attribute, frame register > > is preserved to mitigate PR target/114116. MMX and x87 registers aren't > > clobbered if MMX and x87 aren't enabled. > > 2. For functions with no_caller_saved_registers attribute, MMX and x87 > > registers are clobbered since saving and restoring registers doesn't > > include MMX nor x87 registers. > > 3. Don't mark disabled registers as call used to avoid reg_to_stack > > crashes when x87 registers are still accessed even with -mno-mmx > > -mno-80387. > > 4. Add ABI_ORIGINAL which is the function ABI without attributes on > > the current function. > > 5. Add ABI_ALTERNATE which is the alternate function ABI from ABI_DEFAULT. > > If ix86_abi is SYSV_ABI, ABI_ALTERNATE is the function ABI for MS_ABI. > > Otherwise, ABI_ALTERNATE is the function ABI for SYSV_ABI. > > > > Tested on Linux/x86-64 and with CPython 3.14.4. > > Like I mentioned in the PR trail for 125266, I don't think > the ix86_original_abi stuff, and the use of cfun in > ix86_conditional_register_usage, is correct. Maybe the simplest > thing would be for me to come up with a counterproposal, based on > this patch. It might be a few days before I can give it a go though.
Thanks. I appreciate it. > Thanks, > Richard > > > > > gcc/ > > > > PR target/124798 > > * config/i386/i386-expand.cc: Include "function-abi.h". > > (ix86_expand_call): Add call clobbers only when callee is > > no-callee-saved and caller isn't. Use callee abi to get the > > list of call clobbers. > > * config/i386/i386-options.cc (ix86_init_machine_status): Call > > ix86_init_original_abi. > > * config/i386/i386-protos.h > > (ix86_type_no_callee_saved_registers_p): Removed. > > (ix86_init_original_abi): New. > > * config/i386/i386.cc (ix86_conditional_register_usage): Mark > > all, but frame pointer, are caller-saved in no-callee-saved and > > preserve_none functions. Clear disabled registers in > > call_used_regs. > > (ix86_type_no_callee_saved_registers_p): Make it static. > > (ix86_no_callee_saved_abi): New function. > > (ix86_no_caller_saved_abi_void): Likewise. > > (ix86_no_caller_saved_abi_ax): Likewise. > > (ix86_no_caller_saved_abi_ax_dx): Likewise. > > (ix86_no_caller_saved_abi_xmm0): Likewise. > > (ix86_no_caller_saved_abi_xmm0_xmm1): Likewise. > > (ix86_original_abi): Likewise. > > (ix86_alternate_abi): Likewise. > > (ix86_init_original_abi): Likewise. > > (ix86_function_abi_id): Likewise. > > (ix86_fntype_abi): Likewise. > > (ix86_hard_regno_call_part_clobbered): Handle newly added ABIs. > > (TARGET_FNTYPE_ABI): New. > > * config/i386/i386.md: Add ABI_ORIGINAL, ABI_ALTERNATE, > > ABI_NO_CALLEE_SAVED, ABI_NO_CALLER_SAVED_RETURN_VOID, > > ABI_NO_CALLER_SAVED_RETURN_AX, ABI_NO_CALLER_SAVED_RETURN_AX_DX, > > ABI_NO_CALLER_SAVED_RETURN_XMM0 and > > ABI_NO_CALLER_SAVED_RETURN_XMM0_XMM1. > > > > gcc/testsuite/ > > > > PR target/124798 > > * gcc.target/i386/no-callee-saved-18.c: Don't check frame > > register. > > * gcc.target/i386/no-callee-saved-19b.c: Update the expected > > instruction order. > > * gcc.target/i386/no-callee-saved-19d.c: Likewise. > > * gcc.target/i386/no-callee-saved-19e.c: Likewise. > > * gcc.target/i386/no-callee-saved-2.c: Check frame register isn't > > saved nor restored in 64-bit mode. > > * gcc.target/i386/no-callee-saved-8.c: Expect no saving nor > > restoring caller-saved registers. > > * gcc.target/i386/no-callee-saved-9.c: Likewise. > > * gcc.target/i386/preserve-none-14.c: Don't check frame register. > > * gcc.target/i386/preserve-none-23.c: Likewise. > > * gcc.target/i386/preserve-none-7.c: Check frame register isn't > > saved nor restored in 64-bit mode > > * gcc.target/i386/no-caller-saved-1-ms.c: New test. > > * gcc.target/i386/no-caller-saved-1-sysv.c: Likewise. > > * gcc.target/i386/no-caller-saved-1.c: Likewise. > > * gcc.target/i386/no-caller-saved-2.c: Likewise. > > * gcc.target/i386/no-caller-saved-3.c: Likewise. > > * gcc.target/i386/no-caller-saved-4.c: Likewise. > > * gcc.target/i386/no-caller-saved-5.c: Likewise. > > * gcc.target/i386/no-caller-saved-6.c: Likewise. > > * gcc.target/i386/no-caller-saved-7.c: Likewise. > > * gcc.target/i386/stack-check-17.c: Also expect 1 pop in 64-bit > > mode. > > > > > > -- > > H.J. > > > > From 8f6ebc95073e972b75796e9109ca1242f7bee94d Mon Sep 17 00:00:00 2001 > > From: "H.J. Lu" <[email protected]> > > Date: Tue, 14 Apr 2026 18:37:20 +0800 > > Subject: [PATCH v2] x86: Implement TARGET_FNTYPE_ABI > > > > Implement TARGET_FNTYPE_ABI to avoid spills of callee-saved registers > > when calling functions with no_caller_saved_registers attribute. > > > > 1. For functions with no_callee_saved_registers attribute, frame register > > is preserved to mitigate PR target/114116. MMX and x87 registers aren't > > clobbered if MMX and x87 aren't enabled. > > 2. For functions with no_caller_saved_registers attribute, MMX and x87 > > registers are clobbered since saving and restoring registers doesn't > > include MMX nor x87 registers. > > 3. Don't mark disabled registers as call used to avoid reg_to_stack > > crashes when x87 registers are still accessed even with -mno-mmx > > -mno-80387. > > 4. Add ABI_ORIGINAL which is the function ABI without attributes on > > the current function. > > 5. Add ABI_ALTERNATE which is the alternate function ABI from ABI_DEFAULT. > > If ix86_abi is SYSV_ABI, ABI_ALTERNATE is the function ABI for MS_ABI. > > Otherwise, ABI_ALTERNATE is the function ABI for SYSV_ABI. > > > > Tested on Linux/x86-64 and with CPython 3.14.4. > > > > gcc/ > > > > PR target/124798 > > * config/i386/i386-expand.cc: Include "function-abi.h". > > (ix86_expand_call): Add call clobbers only when callee is > > no-callee-saved and caller isn't. Use callee abi to get the > > list of call clobbers. > > * config/i386/i386-options.cc (ix86_init_machine_status): Call > > ix86_init_original_abi. > > * config/i386/i386-protos.h > > (ix86_type_no_callee_saved_registers_p): Removed. > > (ix86_init_original_abi): New. > > * config/i386/i386.cc (ix86_conditional_register_usage): Mark > > all, but frame pointer, are caller-saved in no-callee-saved and > > preserve_none functions. Clear disabled registers in > > call_used_regs. > > (ix86_type_no_callee_saved_registers_p): Make it static. > > (ix86_no_callee_saved_abi): New function. > > (ix86_no_caller_saved_abi_void): Likewise. > > (ix86_no_caller_saved_abi_ax): Likewise. > > (ix86_no_caller_saved_abi_ax_dx): Likewise. > > (ix86_no_caller_saved_abi_xmm0): Likewise. > > (ix86_no_caller_saved_abi_xmm0_xmm1): Likewise. > > (ix86_original_abi): Likewise. > > (ix86_alternate_abi): Likewise. > > (ix86_init_original_abi): Likewise. > > (ix86_function_abi_id): Likewise. > > (ix86_fntype_abi): Likewise. > > (ix86_hard_regno_call_part_clobbered): Handle newly added ABIs. > > (TARGET_FNTYPE_ABI): New. > > * config/i386/i386.md: Add ABI_ORIGINAL, ABI_ALTERNATE, > > ABI_NO_CALLEE_SAVED, ABI_NO_CALLER_SAVED_RETURN_VOID, > > ABI_NO_CALLER_SAVED_RETURN_AX, ABI_NO_CALLER_SAVED_RETURN_AX_DX, > > ABI_NO_CALLER_SAVED_RETURN_XMM0 and > > ABI_NO_CALLER_SAVED_RETURN_XMM0_XMM1. > > > > gcc/testsuite/ > > > > PR target/124798 > > * gcc.target/i386/no-callee-saved-18.c: Don't check frame > > register. > > * gcc.target/i386/no-callee-saved-19b.c: Update the expected > > instruction order. > > * gcc.target/i386/no-callee-saved-19d.c: Likewise. > > * gcc.target/i386/no-callee-saved-19e.c: Likewise. > > * gcc.target/i386/no-callee-saved-2.c: Check frame register isn't > > saved nor restored in 64-bit mode. > > * gcc.target/i386/no-callee-saved-8.c: Expect no saving nor > > restoring caller-saved registers. > > * gcc.target/i386/no-callee-saved-9.c: Likewise. > > * gcc.target/i386/preserve-none-14.c: Don't check frame register. > > * gcc.target/i386/preserve-none-23.c: Likewise. > > * gcc.target/i386/preserve-none-7.c: Check frame register isn't > > saved nor restored in 64-bit mode > > * gcc.target/i386/no-caller-saved-1-ms.c: New test. > > * gcc.target/i386/no-caller-saved-1-sysv.c: Likewise. > > * gcc.target/i386/no-caller-saved-1.c: Likewise. > > * gcc.target/i386/no-caller-saved-2.c: Likewise. > > * gcc.target/i386/no-caller-saved-3.c: Likewise. > > * gcc.target/i386/no-caller-saved-4.c: Likewise. > > * gcc.target/i386/no-caller-saved-5.c: Likewise. > > * gcc.target/i386/no-caller-saved-6.c: Likewise. > > * gcc.target/i386/no-caller-saved-7.c: Likewise. > > * gcc.target/i386/stack-check-17.c: Also expect 1 pop in 64-bit > > mode. > > > > Signed-off-by: H.J. Lu <[email protected]> > > --- > > gcc/config/i386/i386-expand.cc | 31 +- > > gcc/config/i386/i386-options.cc | 4 + > > gcc/config/i386/i386-protos.h | 2 +- > > gcc/config/i386/i386.cc | 393 +++++++++++++++++- > > gcc/config/i386/i386.md | 30 +- > > .../gcc.target/i386/no-callee-saved-18.c | 2 - > > .../gcc.target/i386/no-callee-saved-19b.c | 8 +- > > .../gcc.target/i386/no-callee-saved-19d.c | 6 +- > > .../gcc.target/i386/no-callee-saved-19e.c | 8 +- > > .../gcc.target/i386/no-callee-saved-2.c | 10 +- > > .../gcc.target/i386/no-callee-saved-8.c | 8 +- > > .../gcc.target/i386/no-callee-saved-9.c | 10 +- > > .../gcc.target/i386/no-caller-saved-1-ms.c | 50 +++ > > .../gcc.target/i386/no-caller-saved-1-sysv.c | 46 ++ > > .../gcc.target/i386/no-caller-saved-1.c | 50 +++ > > .../gcc.target/i386/no-caller-saved-2.c | 49 +++ > > .../gcc.target/i386/no-caller-saved-3.c | 49 +++ > > .../gcc.target/i386/no-caller-saved-4.c | 44 ++ > > .../gcc.target/i386/no-caller-saved-5.c | 34 ++ > > .../gcc.target/i386/no-caller-saved-6.c | 34 ++ > > .../gcc.target/i386/no-caller-saved-7.c | 49 +++ > > .../gcc.target/i386/preserve-none-14.c | 2 - > > .../gcc.target/i386/preserve-none-23.c | 2 - > > .../gcc.target/i386/preserve-none-7.c | 10 +- > > .../gcc.target/i386/stack-check-17.c | 3 +- > > 25 files changed, 860 insertions(+), 74 deletions(-) > > create mode 100644 gcc/testsuite/gcc.target/i386/no-caller-saved-1-ms.c > > create mode 100644 gcc/testsuite/gcc.target/i386/no-caller-saved-1-sysv.c > > create mode 100644 gcc/testsuite/gcc.target/i386/no-caller-saved-1.c > > create mode 100644 gcc/testsuite/gcc.target/i386/no-caller-saved-2.c > > create mode 100644 gcc/testsuite/gcc.target/i386/no-caller-saved-3.c > > create mode 100644 gcc/testsuite/gcc.target/i386/no-caller-saved-4.c > > create mode 100644 gcc/testsuite/gcc.target/i386/no-caller-saved-5.c > > create mode 100644 gcc/testsuite/gcc.target/i386/no-caller-saved-6.c > > create mode 100644 gcc/testsuite/gcc.target/i386/no-caller-saved-7.c > > > > diff --git a/gcc/config/i386/i386-expand.cc b/gcc/config/i386/i386-expand.cc > > index df44a4eb99d..443eacbfe62 100644 > > --- a/gcc/config/i386/i386-expand.cc > > +++ b/gcc/config/i386/i386-expand.cc > > @@ -94,6 +94,7 @@ along with GCC; see the file COPYING3. If not see > > #include "i386-builtins.h" > > #include "i386-expand.h" > > #include "asan.h" > > +#include "function-abi.h" > > > > /* Split one or more double-mode RTL references into pairs of half-mode > > references. The RTL can be REG, offsettable MEM, integer constant, or > > @@ -11081,7 +11082,8 @@ ix86_expand_call (rtx retval, rtx fnaddr, rtx > > callarg1, > > rtx use = NULL, call; > > unsigned int vec_len = 0; > > tree fndecl; > > - bool call_no_callee_saved_registers = false; > > + function_abi caller_abi = fndecl_abi (current_function_decl); > > + function_abi callee_abi = caller_abi; > > > > if (SYMBOL_REF_P (XEXP (fnaddr, 0))) > > { > > @@ -11091,8 +11093,8 @@ ix86_expand_call (rtx retval, rtx fnaddr, rtx > > callarg1, > > if (lookup_attribute ("interrupt", > > TYPE_ATTRIBUTES (TREE_TYPE (fndecl)))) > > error ("interrupt service routine cannot be called directly"); > > - else if (ix86_type_no_callee_saved_registers_p (TREE_TYPE (fndecl))) > > - call_no_callee_saved_registers = true; > > + else if (TREE_CODE (fndecl) == FUNCTION_DECL) > > + callee_abi = fndecl_abi (fndecl); > > if (fndecl == current_function_decl > > && decl_binds_to_current_def_p (fndecl)) > > cfun->machine->recursive_function = true; > > @@ -11103,10 +11105,8 @@ ix86_expand_call (rtx retval, rtx fnaddr, rtx > > callarg1, > > if (MEM_P (fnaddr)) > > { > > tree mem_expr = MEM_EXPR (fnaddr); > > - if (mem_expr != nullptr > > - && TREE_CODE (mem_expr) == MEM_REF > > - && ix86_type_no_callee_saved_registers_p (TREE_TYPE (mem_expr))) > > - call_no_callee_saved_registers = true; > > + if (mem_expr != nullptr && TREE_CODE (mem_expr) == MEM_REF) > > + callee_abi = fntype_abi (TREE_TYPE (mem_expr)); > > } > > > > fndecl = NULL_TREE; > > @@ -11320,21 +11320,14 @@ ix86_expand_call (rtx retval, rtx fnaddr, rtx > > callarg1, > > clobber_reg (&use, gen_rtx_REG (DImode, R10_REG)); > > } > > > > - if (call_no_callee_saved_registers) > > + if (callee_abi.id () == ABI_NO_CALLEE_SAVED > > + && caller_abi.id () != ABI_NO_CALLEE_SAVED) > > { > > - /* After calling a no_callee_saved_registers function, all > > - registers may be clobbered. Clobber all registers that are > > - not used by the callee. */ > > - bool is_64bit_ms_abi = (TARGET_64BIT > > - && ix86_function_abi (fndecl) == MS_ABI); > > - char c_mask = CALL_USED_REGISTERS_MASK (is_64bit_ms_abi); > > for (int i = 0; i < FIRST_PSEUDO_REGISTER; i++) > > - if (!fixed_regs[i] > > + if (GENERAL_REGNO_P (i) > > + && TEST_HARD_REG_BIT (accessible_reg_set, i) > > && i != HARD_FRAME_POINTER_REGNUM > > - && !(ix86_call_used_regs[i] == 1 > > - || (ix86_call_used_regs[i] & c_mask)) > > - && !STACK_REGNO_P (i) > > - && !MMX_REGNO_P (i)) > > + && callee_abi.clobbers_at_least_part_of_reg_p (i)) > > clobber_reg (&use, > > gen_rtx_REG (GET_MODE (regno_reg_rtx[i]), i)); > > } > > diff --git a/gcc/config/i386/i386-options.cc > > b/gcc/config/i386/i386-options.cc > > index 7ffe9cd2a38..890b36835dd 100644 > > --- a/gcc/config/i386/i386-options.cc > > +++ b/gcc/config/i386/i386-options.cc > > @@ -2004,6 +2004,10 @@ ix86_init_machine_status (void) > > f->stack_frame_required = true; > > f->silent_p = true; > > > > + /* NB: Call ix86_init_original_abi to make a copy of the function ABI > > + without attributes on the current function. */ > > + ix86_init_original_abi (); > > + > > return f; > > } > > > > diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h > > index 4ba4fb08556..1664a1a06a3 100644 > > --- a/gcc/config/i386/i386-protos.h > > +++ b/gcc/config/i386/i386-protos.h > > @@ -283,10 +283,10 @@ extern tree ix86_valid_target_attribute_tree (tree, > > tree, > > struct gcc_options *, > > struct gcc_options *, bool); > > extern unsigned int ix86_get_callcvt (const_tree); > > -extern bool ix86_type_no_callee_saved_registers_p (const_tree); > > > > #endif > > > > +extern void ix86_init_original_abi (void); > > extern rtx ix86_tls_module_base (void); > > extern bool ix86_gpr_tls_address_pattern_p (rtx); > > extern bool ix86_tls_address_pattern_p (rtx); > > diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc > > index 2744c749578..ab30d03e998 100644 > > --- a/gcc/config/i386/i386.cc > > +++ b/gcc/config/i386/i386.cc > > @@ -503,16 +503,33 @@ ix86_conditional_register_usage (void) > > { > > int i, c_mask; > > > > - /* If there are no caller-saved registers, preserve all registers. > > - except fixed_regs and registers used for function return value > > - since aggregate_value_p checks call_used_regs[regno] on return > > - value. */ > > - if (cfun > > - && (cfun->machine->call_saved_registers > > - == TYPE_NO_CALLER_SAVED_REGISTERS)) > > - for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) > > - if (!fixed_regs[i] && !ix86_function_value_regno_p (i)) > > - call_used_regs[i] = 0; > > + if (cfun) > > + switch (cfun->machine->call_saved_registers) > > + { > > + case TYPE_DEFAULT_CALL_SAVED_REGISTERS: > > + break; > > + > > + case TYPE_NO_CALLER_SAVED_REGISTERS: > > + /* If there are no caller-saved registers, preserve all > > + registers. except fixed_regs and registers used for > > + function return value since aggregate_value_p checks > > + call_used_regs[regno] on return value. */ > > + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) > > + if (!fixed_regs[i] && !ix86_function_value_regno_p (i)) > > + call_used_regs[i] = 0; > > + break; > > + > > + case TYPE_NO_CALLEE_SAVED_REGISTERS: > > + case TYPE_PRESERVE_NONE: > > + /* All, but frame pointer, are caller-saved. */ > > + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) > > + if (GENERAL_REGNO_P (i) > > + || SSE_REGNO_P (i) > > + || MASK_REGNO_P (i)) > > + call_used_regs[i] = 1; > > + call_used_regs[BP_REG] = 0; > > + break; > > + } > > > > /* For 32-bit targets, disable the REX registers. */ > > if (! TARGET_64BIT) > > @@ -571,6 +588,13 @@ ix86_conditional_register_usage (void) > > for (i = FIRST_REX2_INT_REG; i <= LAST_REX2_INT_REG; i++) > > CLEAR_HARD_REG_BIT (accessible_reg_set, i); > > } > > + > > + /* If a register is disabled, it can't be used for call. This avoids > > + reg_to_stack crashes when x87 registers are still accessed even > > + with -mno-mmx -mno-80387. */ > > + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) > > + if (!TEST_HARD_REG_BIT (accessible_reg_set, i)) > > + call_used_regs[i] = 0; > > } > > > > /* Canonicalize a comparison from one we don't have to one we do have. */ > > @@ -932,7 +956,7 @@ x86_64_elf_unique_section (tree decl, int reloc) > > /* Return true if TYPE has no_callee_saved_registers or preserve_none > > attribute. */ > > > > -bool > > +static bool > > ix86_type_no_callee_saved_registers_p (const_tree type) > > { > > return (lookup_attribute ("no_callee_saved_registers", > > @@ -21854,6 +21878,307 @@ ix86_hard_regno_mode_ok (unsigned int regno, > > machine_mode mode) > > return false; > > } > > > > +/* Return the descriptor of no_callee_saved_registers function type. > > + None of registers are preserved, except for frame register to > > + mitigate PR target/114116. MMX and x87 registers are preserved > > + if MMX and x87 aren't enabled. */ > > + > > +static const predefined_function_abi & > > +ix86_no_callee_saved_abi (void) > > +{ > > + auto &no_callee_saved_abi = function_abis[ABI_NO_CALLEE_SAVED]; > > + if (!no_callee_saved_abi.initialized_p ()) > > + { > > + HARD_REG_SET full_reg_clobbers = reg_class_contents[ALL_REGS]; > > + CLEAR_HARD_REG_BIT (full_reg_clobbers, HARD_FRAME_POINTER_REGNUM); > > + for (int i = 0; i < FIRST_PSEUDO_REGISTER; i++) > > + if ((!TARGET_80387 && STACK_REGNO_P (i)) > > + || (!TARGET_MMX && MMX_REGNO_P (i))) > > + CLEAR_HARD_REG_BIT (full_reg_clobbers, i); > > + no_callee_saved_abi.initialize (ABI_NO_CALLEE_SAVED, > > + full_reg_clobbers); > > + } > > + return no_callee_saved_abi; > > +} > > + > > +/* Return the descriptor of no_caller_saved_registers function type. > > + All registers are preserved, except for MMX and x87 registers > > + which aren't supported when saving and restoring registers. */ > > + > > +static const predefined_function_abi & > > +ix86_no_caller_saved_abi_void (void) > > +{ > > + auto &no_caller_saved_abi > > + = function_abis[ABI_NO_CALLER_SAVED_RETURN_VOID]; > > + if (!no_caller_saved_abi.initialized_p ()) > > + { > > + HARD_REG_SET full_reg_clobbers = {}; > > + for (int i = 0; i < FIRST_PSEUDO_REGISTER; i++) > > + if ((TARGET_80387 && STACK_REGNO_P (i)) > > + || (TARGET_MMX && MMX_REGNO_P (i))) > > + SET_HARD_REG_BIT (full_reg_clobbers, i); > > + no_caller_saved_abi.initialize > > + (ABI_NO_CALLER_SAVED_RETURN_VOID, full_reg_clobbers); > > + } > > + return no_caller_saved_abi; > > +} > > + > > +/* Return the descriptor of no_caller_saved_registers function type. > > + All registers are preserved, except for AX used for return value, > > + MMX and x87 registers which aren't supported when saving and > > + restoring registers. */ > > + > > +static const predefined_function_abi & > > +ix86_no_caller_saved_abi_ax (void) > > +{ > > + auto &no_caller_saved_abi > > + = function_abis[ABI_NO_CALLER_SAVED_RETURN_AX]; > > + if (!no_caller_saved_abi.initialized_p ()) > > + { > > + HARD_REG_SET full_reg_clobbers = {}; > > + for (int i = 0; i < FIRST_PSEUDO_REGISTER; i++) > > + if (i == AX_REG > > + || (TARGET_80387 && STACK_REGNO_P (i)) > > + || (TARGET_MMX && MMX_REGNO_P (i))) > > + SET_HARD_REG_BIT (full_reg_clobbers, i); > > + no_caller_saved_abi.initialize > > + (ABI_NO_CALLER_SAVED_RETURN_AX, full_reg_clobbers); > > + } > > + return no_caller_saved_abi; > > +} > > + > > +/* Return the descriptor of no_caller_saved_registers function type. > > + All registers are preserved, except for AX/DX used for return value, > > + MMX and x87 registers which aren't supported when saving and > > + restoring registers. */ > > + > > +static const predefined_function_abi & > > +ix86_no_caller_saved_abi_ax_dx (void) > > +{ > > + auto &no_caller_saved_abi > > + = function_abis[ABI_NO_CALLER_SAVED_RETURN_AX_DX]; > > + if (!no_caller_saved_abi.initialized_p ()) > > + { > > + HARD_REG_SET full_reg_clobbers = {}; > > + for (int i = 0; i < FIRST_PSEUDO_REGISTER; i++) > > + if (i == AX_REG > > + || i == DX_REG > > + || (TARGET_80387 && STACK_REGNO_P (i)) > > + || (TARGET_MMX && MMX_REGNO_P (i))) > > + SET_HARD_REG_BIT (full_reg_clobbers, i); > > + no_caller_saved_abi.initialize > > + (ABI_NO_CALLER_SAVED_RETURN_AX_DX, full_reg_clobbers); > > + } > > + return no_caller_saved_abi; > > +} > > + > > +/* Return the descriptor of no_caller_saved_registers function type. > > + All registers are preserved, except for XMM0 used for return value, > > + MMX and x87 registers which aren't supported when saving and > > + restoring registers. */ > > + > > +static const predefined_function_abi & > > +ix86_no_caller_saved_abi_xmm0 (void) > > +{ > > + auto &no_caller_saved_abi > > + = function_abis[ABI_NO_CALLER_SAVED_RETURN_XMM0]; > > + if (!no_caller_saved_abi.initialized_p ()) > > + { > > + HARD_REG_SET full_reg_clobbers = {}; > > + for (int i = 0; i < FIRST_PSEUDO_REGISTER; i++) > > + if (i == XMM0_REG > > + || (TARGET_80387 && STACK_REGNO_P (i)) > > + || (TARGET_MMX && MMX_REGNO_P (i))) > > + SET_HARD_REG_BIT (full_reg_clobbers, i); > > + no_caller_saved_abi.initialize > > + (ABI_NO_CALLER_SAVED_RETURN_XMM0, full_reg_clobbers); > > + } > > + return no_caller_saved_abi; > > +} > > + > > +/* Return the descriptor of no_caller_saved_registers function type. > > + All registers are preserved, except for XMM0/XMM1 used for return > > + value, MMX and x87 registers which aren't supported when saving and > > + restoring registers. */ > > + > > +static const predefined_function_abi & > > +ix86_no_caller_saved_abi_xmm0_xmm1 (void) > > +{ > > + auto &no_caller_saved_abi > > + = function_abis[ABI_NO_CALLER_SAVED_RETURN_XMM0_XMM1]; > > + if (!no_caller_saved_abi.initialized_p ()) > > + { > > + HARD_REG_SET full_reg_clobbers = {}; > > + for (int i = 0; i < FIRST_PSEUDO_REGISTER; i++) > > + if (i == XMM0_REG > > + || i == XMM1_REG > > + || (TARGET_80387 && STACK_REGNO_P (i)) > > + || (TARGET_MMX && MMX_REGNO_P (i))) > > + SET_HARD_REG_BIT (full_reg_clobbers, i); > > + no_caller_saved_abi.initialize > > + (ABI_NO_CALLER_SAVED_RETURN_XMM0_XMM1, full_reg_clobbers); > > + } > > + return no_caller_saved_abi; > > +} > > + > > +/* Return the descriptor of the function ABI type without attributes > > + on the current function. */ > > + > > +static const predefined_function_abi & > > +ix86_original_abi (void) > > +{ > > + auto &original_abi = function_abis[ABI_ORIGINAL]; > > + if (!original_abi.initialized_p ()) > > + { > > + HARD_REG_SET full_reg_clobbers > > + = default_function_abi.full_reg_clobbers (); > > + original_abi.initialize (ABI_ORIGINAL, full_reg_clobbers); > > + } > > + return original_abi; > > +} > > + > > +/* Return the descriptor of the function alternate ABI type. */ > > + > > +static const predefined_function_abi & > > +ix86_alternate_abi (void) > > +{ > > + static const char ix86_call_used_regs[] = CALL_USED_REGISTERS; > > + auto &alternate_abi = function_abis[ABI_ALTERNATE]; > > + if (!alternate_abi.initialized_p ()) > > + { > > + HARD_REG_SET full_reg_clobbers = {}; > > + > > + /* Add all registers that are clobbered by the call. NB: If the > > + current ABI is SYSV_ABI, the alternate ABI is MS_ABI. */ > > + bool is_64bit_ms_abi = TARGET_64BIT && ix86_abi == SYSV_ABI; > > + char c_mask = CALL_USED_REGISTERS_MASK (is_64bit_ms_abi); > > + for (int i = 0; i < FIRST_PSEUDO_REGISTER; i++) > > + if (!fixed_regs[i] > > + && (ix86_call_used_regs[i] == 1 > > + || (ix86_call_used_regs[i] & c_mask))) > > + SET_HARD_REG_BIT (full_reg_clobbers, i); > > + alternate_abi.initialize (ABI_ORIGINAL, full_reg_clobbers); > > + } > > + return alternate_abi; > > +} > > + > > +/* Make ABI_ORIGINAL a copy of the function ABI without attributes on > > + the current function. */ > > + > > +void > > +ix86_init_original_abi (void) > > +{ > > + gcc_assert (default_function_abi.initialized_p ()); > > + ix86_original_abi (); > > +} > > + > > +/* Return the function ABI ID based on FNTYPE. */ > > + > > +static int > > +ix86_function_abi_id (const_tree fntype) > > +{ > > + if (ix86_type_no_callee_saved_registers_p (fntype)) > > + return ABI_NO_CALLEE_SAVED; > > + > > + if (lookup_attribute ("no_caller_saved_registers", > > + TYPE_ATTRIBUTES (fntype))) > > + { > > + tree type = TREE_TYPE (fntype); > > + if (VOID_TYPE_P (type)) > > + return ABI_NO_CALLER_SAVED_RETURN_VOID; > > + /* AX register contains the address of the return value location > > + passed in by the caller. */ > > + else if (ix86_return_in_memory (type, fntype)) > > + return ABI_NO_CALLER_SAVED_RETURN_AX; > > + rtx ret = ix86_function_value (type, fntype, false); > > + unsigned int nregs; > > + if (REG_P (ret)) > > + { > > + unsigned int regno = REGNO (ret); > > + if (STACK_REGNO_P (regno) || MMX_REGNO_P (regno)) > > + return ABI_NO_CALLER_SAVED_RETURN_VOID; > > + else > > + switch (regno) > > + { > > + case AX_REG: > > + nregs = REG_NREGS (ret); > > + if (nregs == 1) > > + return ABI_NO_CALLER_SAVED_RETURN_AX; > > + else if (nregs == 2) > > + return ABI_NO_CALLER_SAVED_RETURN_AX_DX; > > + break; > > + case XMM0_REG: > > + return ABI_NO_CALLER_SAVED_RETURN_XMM0; > > + default: > > + gcc_unreachable (); > > + } > > + } > > + else if (GET_CODE (ret) == PARALLEL && XVECLEN (ret, 0) == 2) > > + { > > + rtx x0 = XVECEXP (ret, 0, 0); > > + rtx x1 = XVECEXP (ret, 0, 1); > > + if (GET_CODE (x0) == EXPR_LIST > > + && GET_CODE (x1) == EXPR_LIST) > > + { > > + x0 = XEXP (x0, 0); > > + x1 = XEXP (x1, 0); > > + if (REG_P (x0) > > + && REGNO (x0) == XMM0_REG > > + && REG_P (x1) > > + && REGNO (x1) == XMM1_REG) > > + return ABI_NO_CALLER_SAVED_RETURN_XMM0_XMM1; > > + } > > + > > + gcc_unreachable (); > > + } > > + } > > + > > + /* NB: This must be the last since other attributes change the > > + function ABI. */ > > + if (ix86_function_type_abi (fntype) != ix86_abi) > > + return ABI_ALTERNATE; > > + > > + return ABI_ORIGINAL; > > +} > > + > > +/* Implement TARGET_FNTYPE_ABI. */ > > + > > +static const predefined_function_abi & > > +ix86_fntype_abi (const_tree fntype) > > +{ > > + switch (ix86_function_abi_id (fntype)) > > + { > > + case ABI_ORIGINAL: > > + return ix86_original_abi (); > > + > > + case ABI_ALTERNATE: > > + return ix86_alternate_abi (); > > + > > + case ABI_NO_CALLEE_SAVED: > > + return ix86_no_callee_saved_abi (); > > + > > + case ABI_NO_CALLER_SAVED_RETURN_VOID: > > + return ix86_no_caller_saved_abi_void (); > > + > > + case ABI_NO_CALLER_SAVED_RETURN_AX: > > + return ix86_no_caller_saved_abi_ax (); > > + > > + case ABI_NO_CALLER_SAVED_RETURN_AX_DX: > > + return ix86_no_caller_saved_abi_ax_dx (); > > + > > + case ABI_NO_CALLER_SAVED_RETURN_XMM0: > > + return ix86_no_caller_saved_abi_xmm0 (); > > + > > + case ABI_NO_CALLER_SAVED_RETURN_XMM0_XMM1: > > + return ix86_no_caller_saved_abi_xmm0_xmm1 (); > > + > > + default: > > + gcc_unreachable (); > > + } > > + > > + return default_function_abi; > > +} > > + > > /* Implement TARGET_INSN_CALLEE_ABI. */ > > > > const predefined_function_abi & > > @@ -21904,12 +22229,51 @@ static bool > > ix86_hard_regno_call_part_clobbered (unsigned int abi_id, unsigned int > > regno, > > machine_mode mode) > > { > > - /* Special ABI for vzeroupper which only clobber higher part of sse > > regs. */ > > - if (abi_id == ABI_VZEROUPPER) > > + if (abi_id == ABI_DEFAULT) > > + { > > + /* Get the ABI ID from the current function. */ > > + if (cfun) > > + abi_id = ix86_function_abi_id (TREE_TYPE (cfun->decl)); > > + else > > + abi_id = ABI_ORIGINAL; > > + } > > + > > + switch (abi_id) > > + { > > + case ABI_VZEROUPPER: > > + /* Special ABI for vzeroupper which only clobbers higher part of > > + SSE registers. */ > > return (GET_MODE_SIZE (mode) > 16 > > && ((TARGET_64BIT && REX_SSE_REGNO_P (regno)) > > || LEGACY_SSE_REGNO_P (regno))); > > > > + case ABI_ORIGINAL: > > + case ABI_ALTERNATE: > > + case ABI_NO_CALLEE_SAVED: > > + break; > > + > > + case ABI_NO_CALLER_SAVED_RETURN_VOID: > > + case ABI_NO_CALLER_SAVED_RETURN_AX: > > + case ABI_NO_CALLER_SAVED_RETURN_AX_DX: > > + /* These ABIs don't clobber SSE registers. */ > > + return false; > > + > > + case ABI_NO_CALLER_SAVED_RETURN_XMM0: > > + /* This ABI only clobbers XMM0. */ > > + if (regno != XMM0_REG) > > + return false; > > + break; > > + > > + case ABI_NO_CALLER_SAVED_RETURN_XMM0_XMM1: > > + /* This ABI only clobbers XMM0 and XMM1. */ > > + if (regno != XMM0_REG && regno != XMM1_REG) > > + return false; > > + break; > > + > > + default: > > + gcc_unreachable (); > > + } > > + > > return SSE_REGNO_P (regno) && GET_MODE_SIZE (mode) > 16; > > } > > > > @@ -28786,6 +29150,9 @@ ix86_libgcc_floating_mode_supported_p > > #define TARGET_HARD_REGNO_CALL_PART_CLOBBERED \ > > ix86_hard_regno_call_part_clobbered > > > > +#undef TARGET_FNTYPE_ABI > > +#define TARGET_FNTYPE_ABI ix86_fntype_abi > > + > > #undef TARGET_INSN_CALLEE_ABI > > #define TARGET_INSN_CALLEE_ABI ix86_insn_callee_abi > > > > diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md > > index b4e397bc925..3ac7aca9461 100644 > > --- a/gcc/config/i386/i386.md > > +++ b/gcc/config/i386/i386.md > > @@ -511,11 +511,33 @@ (define_constants > > (FIRST_PSEUDO_REG 92) > > ]) > > > > -;; Insn callee abi index. > > +;; Insn callee abi index. ABI_DEFAULT is the funtion ABI for the > > +;; current function. ABI_ORIGINAL is the function ABI without > > +;; attributes on the current function. ABI_ALTERNATE is the Windows > > +;; function ABI if ix86_abi == SYSV_ABI and is the SYSV function ABI > > +;; if ix86_abi == MS_ABI. > > (define_constants > > - [(ABI_DEFAULT 0) > > - (ABI_VZEROUPPER 1) > > - (ABI_UNKNOWN 2)]) > > + [(ABI_DEFAULT 0) > > + (ABI_VZEROUPPER 1) > > + (ABI_ORIGINAL 2) > > + (ABI_ALTERNATE 3) > > + (ABI_NO_CALLEE_SAVED 4) > > + ;; Return void. > > + (ABI_NO_CALLER_SAVED_RETURN_VOID 5) > > + ;; Return char, short, int in 32-bit/64-bit. > > + ;; Return int64 and _Complex int in 64-bit. > > + ;; Return _Complex float in MS 32-bit/64-bit. > > + (ABI_NO_CALLER_SAVED_RETURN_AX 6) > > + ;; Return int64 and _Complex int in 32-bit. > > + ;; Return _Complex int64 in 64-bit. > > + (ABI_NO_CALLER_SAVED_RETURN_AX_DX 7) > > + ;; Return float and double in 64-bit. > > + ;; Return _Complex float in SYSV 64-bit. > > + ;; Return int28, _Complex double in MS 64-bit. > > + (ABI_NO_CALLER_SAVED_RETURN_XMM0 8) > > + ;; Return _Complex double in SYSV 64-bit. > > + (ABI_NO_CALLER_SAVED_RETURN_XMM0_XMM1 9) > > + (ABI_UNKNOWN 10)]) > > > > ;; Insns whose names begin with "x86_" are emitted by gen_FOO calls > > ;; from i386.cc. > > diff --git a/gcc/testsuite/gcc.target/i386/no-callee-saved-18.c > > b/gcc/testsuite/gcc.target/i386/no-callee-saved-18.c > > index 128b9c46e8e..5e228753d8a 100644 > > --- a/gcc/testsuite/gcc.target/i386/no-callee-saved-18.c > > +++ b/gcc/testsuite/gcc.target/i386/no-callee-saved-18.c > > @@ -19,7 +19,6 @@ foo (uintptr_t p) > > /* { dg-final { scan-assembler-times "push(?:l|q)\[\\t \]*%(?:e|r)bx" 1 } > > } */ > > /* { dg-final { scan-assembler-not "push(?:l|q)\[\\t \]*%(?:e|r)cx" } } */ > > /* { dg-final { scan-assembler-not "push(?:l|q)\[\\t \]*%(?:e|r)dx" } } */ > > -/* { dg-final { scan-assembler-not "push(?:l|q)\[\\t \]*%(?:e|r)bp" } } */ > > /* { dg-final { scan-assembler-times "pushl\[\\t \]*%esi" 1 { target ia32 > > } } } */ > > /* { dg-final { scan-assembler-not "pushq\[\\t \]*%rsi" { target { ! ia32 > > } } } } */ > > /* { dg-final { scan-assembler-times "pushl\[\\t \]*%edi" 1 { target ia32 > > } } } */ > > @@ -36,7 +35,6 @@ foo (uintptr_t p) > > /* { dg-final { scan-assembler-times "pop(?:l|q)\[\\t \]*%(?:e|r)bx" 1 } } > > */ > > /* { dg-final { scan-assembler-not "pop(?:l|q)\[\\t \]*%(?:e|r)cx" } } */ > > /* { dg-final { scan-assembler-not "pop(?:l|q)\[\\t \]*%(?:e|r)dx" } } */ > > -/* { dg-final { scan-assembler-not "pop(?:l|q)\[\\t \]*%(?:e|r)bp" } } */ > > /* { dg-final { scan-assembler-times "popl\[\\t \]*%esi" 1 { target ia32 } > > } } */ > > /* { dg-final { scan-assembler-not "popq\[\\t \]*%rsi" { target { ! ia32 } > > } } } */ > > /* { dg-final { scan-assembler-times "popl\[\\t \]*%edi" 1 { target ia32 } > > } } */ > > diff --git a/gcc/testsuite/gcc.target/i386/no-callee-saved-19b.c > > b/gcc/testsuite/gcc.target/i386/no-callee-saved-19b.c > > index dc38936a61a..d784065b456 100644 > > --- a/gcc/testsuite/gcc.target/i386/no-callee-saved-19b.c > > +++ b/gcc/testsuite/gcc.target/i386/no-callee-saved-19b.c > > @@ -52,15 +52,15 @@ > > ** .cfi_startproc > > ** subl \$376, %esp > > **... > > +** movq %rdi, 296\(%rsp\) > > +**... > > +** movl \$code\+4, %edi > > +** movq %rbp, 304\(%rsp\) > > ** movq %rax, 256\(%rsp\) > > ** movq %rdx, 264\(%rsp\) > > ** movq %rcx, 272\(%rsp\) > > ** movq %rbx, 280\(%rsp\) > > ** movq %rsi, 288\(%rsp\) > > -** movq %rdi, 296\(%rsp\) > > -**... > > -** movl \$code\+4, %edi > > -** movq %rbp, 304\(%rsp\) > > ** movq %r8, 312\(%rsp\) > > ** movq %r9, 320\(%rsp\) > > ** movq %r10, 328\(%rsp\) > > diff --git a/gcc/testsuite/gcc.target/i386/no-callee-saved-19d.c > > b/gcc/testsuite/gcc.target/i386/no-callee-saved-19d.c > > index 4657e170350..bb9dce13350 100644 > > --- a/gcc/testsuite/gcc.target/i386/no-callee-saved-19d.c > > +++ b/gcc/testsuite/gcc.target/i386/no-callee-saved-19d.c > > @@ -50,14 +50,14 @@ > > ** .cfi_startproc > > ** subq \$504, %rsp > > **... > > +** movq %rdi, 304\(%rsp\) > > +**... > > +** movl \$code\+8, %edi > > ** movq %rax, 264\(%rsp\) > > ** movq %rdx, 272\(%rsp\) > > ** movq %rcx, 280\(%rsp\) > > ** movq %rbx, 288\(%rsp\) > > ** movq %rsi, 296\(%rsp\) > > -** movq %rdi, 304\(%rsp\) > > -**... > > -** movl \$code\+8, %edi > > ** movq %r8, 312\(%rsp\) > > ** movq %r9, 320\(%rsp\) > > ** movq %r10, 328\(%rsp\) > > diff --git a/gcc/testsuite/gcc.target/i386/no-callee-saved-19e.c > > b/gcc/testsuite/gcc.target/i386/no-callee-saved-19e.c > > index 8e0bbe82eae..617bb755f85 100644 > > --- a/gcc/testsuite/gcc.target/i386/no-callee-saved-19e.c > > +++ b/gcc/testsuite/gcc.target/i386/no-callee-saved-19e.c > > @@ -52,15 +52,15 @@ > > ** .cfi_startproc > > ** subl \$504, %esp > > **... > > +** movq %rdi, 296\(%rsp\) > > +**... > > +** movl \$code\+4, %edi > > +** movq %rbp, 304\(%rsp\) > > ** movq %rax, 256\(%rsp\) > > ** movq %rdx, 264\(%rsp\) > > ** movq %rcx, 272\(%rsp\) > > ** movq %rbx, 280\(%rsp\) > > ** movq %rsi, 288\(%rsp\) > > -** movq %rdi, 296\(%rsp\) > > -**... > > -** movl \$code\+4, %edi > > -** movq %rbp, 304\(%rsp\) > > ** movq %r8, 312\(%rsp\) > > ** movq %r9, 320\(%rsp\) > > ** movq %r10, 328\(%rsp\) > > diff --git a/gcc/testsuite/gcc.target/i386/no-callee-saved-2.c > > b/gcc/testsuite/gcc.target/i386/no-callee-saved-2.c > > index e074ca51df4..86864ea9bff 100644 > > --- a/gcc/testsuite/gcc.target/i386/no-callee-saved-2.c > > +++ b/gcc/testsuite/gcc.target/i386/no-callee-saved-2.c > > @@ -26,7 +26,9 @@ foo (void *frame) > > } > > } > > > > -/* { dg-final { scan-assembler-times "push(?:l|q)\[\\t \]*%(?:e|r)bp" 1 } > > } */ > > -/* { dg-final { scan-assembler-times "pop(?:l|q)\[\\t \]*%(?:e|r)bp" 1 } } > > */ > > -/* { dg-final { scan-assembler-times "push(?:l|q)\[\\t \]*" 1 } } */ > > -/* { dg-final { scan-assembler-times "pop(?:l|q)\[\\t \]*" 1 } } */ > > +/* { dg-final { scan-assembler-times "push(?:l|q)\[\\t \]*%(?:e|r)bp" 1 { > > target ia32 } } } */ > > +/* { dg-final { scan-assembler-times "pop(?:l|q)\[\\t \]*%(?:e|r)bp" 1 { > > target ia32 } } } */ > > +/* { dg-final { scan-assembler-times "push(?:l|q)\[\\t \]*" 1 { target > > ia32 } } } */ > > +/* { dg-final { scan-assembler-times "pop(?:l|q)\[\\t \]*" 1 { target ia32 > > } } } */ > > +/* { dg-final { scan-assembler-not "push(?:l|q)\[\\t \]*" { target { ! > > ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "pop(?:l|q)\[\\t \]*" { target { ! ia32 > > } } } } */ > > diff --git a/gcc/testsuite/gcc.target/i386/no-callee-saved-8.c > > b/gcc/testsuite/gcc.target/i386/no-callee-saved-8.c > > index ed3d96bdca0..692166c98e9 100644 > > --- a/gcc/testsuite/gcc.target/i386/no-callee-saved-8.c > > +++ b/gcc/testsuite/gcc.target/i386/no-callee-saved-8.c > > @@ -44,7 +44,7 @@ foo (void) > > /* { dg-final { scan-assembler-not "popq\[\\t \]*%r9" { target { ! ia32 } > > } } } */ > > /* { dg-final { scan-assembler-not "popq\[\\t \]*%r10" { target { ! ia32 } > > } } } */ > > /* { dg-final { scan-assembler-not "popq\[\\t \]*%r11" { target { ! ia32 } > > } } } */ > > -/* { dg-final { scan-assembler-times "popq\[\\t \]*%r12" 1 { target { ! > > ia32 } } } } */ > > -/* { dg-final { scan-assembler-times "popq\[\\t \]*%r13" 1 { target { ! > > ia32 } } } } */ > > -/* { dg-final { scan-assembler-times "popq\[\\t \]*%r14" 1 { target { ! > > ia32 } } } } */ > > -/* { dg-final { scan-assembler-times "popq\[\\t \]*%r15" 1 { target { ! > > ia32 } } } } */ > > +/* { dg-final { scan-assembler-times "pushq\[\\t \]*%r12" 1 { target { ! > > ia32 } } } } */ > > +/* { dg-final { scan-assembler-times "pushq\[\\t \]*%r13" 1 { target { ! > > ia32 } } } } */ > > +/* { dg-final { scan-assembler-times "pushq\[\\t \]*%r14" 1 { target { ! > > ia32 } } } } */ > > +/* { dg-final { scan-assembler-times "pushq\[\\t \]*%r15" 1 { target { ! > > ia32 } } } } */ > > diff --git a/gcc/testsuite/gcc.target/i386/no-callee-saved-9.c > > b/gcc/testsuite/gcc.target/i386/no-callee-saved-9.c > > index 7730c5903d4..7acaff2ad35 100644 > > --- a/gcc/testsuite/gcc.target/i386/no-callee-saved-9.c > > +++ b/gcc/testsuite/gcc.target/i386/no-callee-saved-9.c > > @@ -17,7 +17,6 @@ foo (fn_t bar) > > /* { dg-final { scan-assembler-times "push(?:l|q)\[\\t \]*%(?:e|r)bx" 1 } > > } */ > > /* { dg-final { scan-assembler-not "push(?:l|q)\[\\t \]*%(?:e|r)cx" } } */ > > /* { dg-final { scan-assembler-not "push(?:l|q)\[\\t \]*%(?:e|r)dx" } } */ > > -/* { dg-final { scan-assembler-not "push(?:l|q)\[\\t \]*%(?:e|r)bp" } } */ > > /* { dg-final { scan-assembler-times "pushl\[\\t \]*%esi" 1 { target ia32 > > } } } */ > > /* { dg-final { scan-assembler-not "pushq\[\\t \]*%rsi" { target { ! ia32 > > } } } } */ > > /* { dg-final { scan-assembler-times "pushl\[\\t \]*%edi" 1 { target ia32 > > } } } */ > > @@ -34,7 +33,6 @@ foo (fn_t bar) > > /* { dg-final { scan-assembler-times "pop(?:l|q)\[\\t \]*%(?:e|r)bx" 1 } } > > */ > > /* { dg-final { scan-assembler-not "pop(?:l|q)\[\\t \]*%(?:e|r)cx" } } */ > > /* { dg-final { scan-assembler-not "pop(?:l|q)\[\\t \]*%(?:e|r)dx" } } */ > > -/* { dg-final { scan-assembler-not "pop(?:l|q)\[\\t \]*%(?:e|r)bp" } } */ > > /* { dg-final { scan-assembler-times "popl\[\\t \]*%esi" 1 { target ia32 } > > } } */ > > /* { dg-final { scan-assembler-not "popq\[\\t \]*%rsi" { target { ! ia32 } > > } } } */ > > /* { dg-final { scan-assembler-times "popl\[\\t \]*%edi" 1 { target ia32 } > > } } */ > > @@ -43,7 +41,7 @@ foo (fn_t bar) > > /* { dg-final { scan-assembler-not "popq\[\\t \]*%r9" { target { ! ia32 } > > } } } */ > > /* { dg-final { scan-assembler-not "popq\[\\t \]*%r10" { target { ! ia32 } > > } } } */ > > /* { dg-final { scan-assembler-not "popq\[\\t \]*%r11" { target { ! ia32 } > > } } } */ > > -/* { dg-final { scan-assembler-times "popq\[\\t \]*%r12" 1 { target { ! > > ia32 } } } } */ > > -/* { dg-final { scan-assembler-times "popq\[\\t \]*%r13" 1 { target { ! > > ia32 } } } } */ > > -/* { dg-final { scan-assembler-times "popq\[\\t \]*%r14" 1 { target { ! > > ia32 } } } } */ > > -/* { dg-final { scan-assembler-times "popq\[\\t \]*%r15" 1 { target { ! > > ia32 } } } } */ > > +/* { dg-final { scan-assembler-times "pushq\[\\t \]*%r12" 1 { target { ! > > ia32 } } } } */ > > +/* { dg-final { scan-assembler-times "pushq\[\\t \]*%r13" 1 { target { ! > > ia32 } } } } */ > > +/* { dg-final { scan-assembler-times "pushq\[\\t \]*%r14" 1 { target { ! > > ia32 } } } } */ > > +/* { dg-final { scan-assembler-times "pushq\[\\t \]*%r15" 1 { target { ! > > ia32 } } } } */ > > diff --git a/gcc/testsuite/gcc.target/i386/no-caller-saved-1-ms.c > > b/gcc/testsuite/gcc.target/i386/no-caller-saved-1-ms.c > > new file mode 100644 > > index 00000000000..9a834d49870 > > --- /dev/null > > +++ b/gcc/testsuite/gcc.target/i386/no-caller-saved-1-ms.c > > @@ -0,0 +1,50 @@ > > +/* PR target/124798 */ > > +/* { dg-do compile } */ > > +/* { dg-options "-mabi=sysv -O2 -mtune=corei7 > > -mtune-ctrl=^prologue_using_move,^epilogue_using_move -fomit-frame-pointer" > > } */ > > + > > +extern void foo (void) __attribute__ ((no_caller_saved_registers, ms_abi)); > > + > > +void > > +qux (void) > > +{ > > + int a, b, c, d, e, f; > > + asm volatile ("# %0 %1 %2 %3 %4 %5" > > + : "=r" (a), "=r" (b), "=r" (c), "=r" (d), "=r" (e), "=r" (f)); > > +#ifdef __x86_64__ > > + int g, h, i, j, k, l, m, n, o, p; > > + asm volatile ("# %0 %1 %2 %3 %4 %5 %6 %7 %8 %9" > > + : "=r" (g), "=r" (h), "=r" (i), "=r" (j), "=r" (k), "=r" (l), > > "=r" (m), "=r" (n), "=r" (o), "=r" (p)); > > +#endif > > + foo (); > > + asm volatile ("# %0 %1 %2 %3 %4 %5" > > + :: "r" (a), "r" (b), "r" (c), "r" (d), "r" (e), "r" (f)); > > +#ifdef __x86_64__ > > + asm volatile ("# %0 %1 %2 %3 %4 %5 %6 %7 %8 %9" > > + : : "r" (g), "r" (h), "r" (i), "r" (j), "r" (k), "r" (l), "r" > > (m), "r" (n), "r" (o), "r" (p)); > > +#endif > > +} > > + > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%edx, > > \[0-9\]*\\(%\[re\]?sp\\)" } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%ecx, > > \[0-9\]*\\(%\[re\]?sp\\)" } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%esi, > > \[0-9\]*\\(%\[re\]?sp\\)" } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%edi, > > \[0-9\]*\\(%\[re\]?sp\\)" } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %edx" } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %ecx" } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %esi" } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %edi" } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%r8d, > > \[0-9\]*\\(%\[re\]?sp\\)" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%r9d, > > \[0-9\]*\\(%\[re\]?sp\\)" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%r10d, > > \[0-9\]*\\(%\[re\]?sp\\)" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%r11d, > > \[0-9\]*\\(%\[re\]?sp\\)" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%r12d, > > \[0-9\]*\\(%\[re\]?sp\\)" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%r13d, > > \[0-9\]*\\(%\[re\]?sp\\)" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%r14d, > > \[0-9\]*\\(%\[re\]?sp\\)" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%r15d, > > \[0-9\]*\\(%\[re\]?sp\\)" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %r8d" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %r9d" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %r10d" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %r11d" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %r12d" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %r13d" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %r14d" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %r15d" { target { ! ia32 } } } } */ > > diff --git a/gcc/testsuite/gcc.target/i386/no-caller-saved-1-sysv.c > > b/gcc/testsuite/gcc.target/i386/no-caller-saved-1-sysv.c > > new file mode 100644 > > index 00000000000..4bd3eecfcc6 > > --- /dev/null > > +++ b/gcc/testsuite/gcc.target/i386/no-caller-saved-1-sysv.c > > @@ -0,0 +1,46 @@ > > +/* PR target/124798 */ > > +/* { dg-do compile } */ > > +/* { dg-options "-mabi=ms -O2 -mtune=corei7 > > -mtune-ctrl=^prologue_using_move,^epilogue_using_move -fomit-frame-pointer" > > } */ > > + > > +extern void foo (void) __attribute__ ((no_caller_saved_registers, > > sysv_abi)); > > + > > +void > > +qux (void) > > +{ > > + int a, b, c, d, e, f; > > + asm volatile ("# %0 %1 %2 %3 %4 %5" > > + : "=r" (a), "=r" (b), "=r" (c), "=r" (d), "=r" (e), "=r" (f)); > > +#ifdef __x86_64__ > > + int g, h, i, j, k, l, m, n, o, p; > > + asm volatile ("# %0 %1 %2 %3 %4 %5 %6 %7 %8 %9" > > + : "=r" (g), "=r" (h), "=r" (i), "=r" (j), "=r" (k), "=r" (l), > > "=r" (m), "=r" (n), "=r" (o), "=r" (p)); > > +#endif > > + foo (); > > + asm volatile ("# %0 %1 %2 %3 %4 %5" > > + :: "r" (a), "r" (b), "r" (c), "r" (d), "r" (e), "r" (f)); > > +#ifdef __x86_64__ > > + asm volatile ("# %0 %1 %2 %3 %4 %5 %6 %7 %8 %9" > > + : : "r" (g), "r" (h), "r" (i), "r" (j), "r" (k), "r" (l), "r" > > (m), "r" (n), "r" (o), "r" (p)); > > +#endif > > +} > > + > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%edx, > > \[0-9\]*\\(%\[re\]?sp\\)" } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%ecx, > > \[0-9\]*\\(%\[re\]?sp\\)" } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %edx" } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %ecx" } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%r8d, > > \[0-9\]*\\(%\[re\]?sp\\)" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%r9d, > > \[0-9\]*\\(%\[re\]?sp\\)" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%r10d, > > \[0-9\]*\\(%\[re\]?sp\\)" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%r11d, > > \[0-9\]*\\(%\[re\]?sp\\)" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%r12d, > > \[0-9\]*\\(%\[re\]?sp\\)" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%r13d, > > \[0-9\]*\\(%\[re\]?sp\\)" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%r14d, > > \[0-9\]*\\(%\[re\]?sp\\)" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%r15d, > > \[0-9\]*\\(%\[re\]?sp\\)" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %r8d" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %r9d" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %r10d" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %r11d" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %r12d" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %r13d" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %r14d" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %r15d" { target { ! ia32 } } } } */ > > diff --git a/gcc/testsuite/gcc.target/i386/no-caller-saved-1.c > > b/gcc/testsuite/gcc.target/i386/no-caller-saved-1.c > > new file mode 100644 > > index 00000000000..fc8ab95c7e8 > > --- /dev/null > > +++ b/gcc/testsuite/gcc.target/i386/no-caller-saved-1.c > > @@ -0,0 +1,50 @@ > > +/* PR target/124798 */ > > +/* { dg-do compile } */ > > +/* { dg-options "-O2 -mtune=corei7 > > -mtune-ctrl=^prologue_using_move,^epilogue_using_move -fomit-frame-pointer" > > } */ > > + > > +[[gnu::no_caller_saved_registers]] extern void foo (void); > > + > > +void > > +qux (void) > > +{ > > + int a, b, c, d, e, f; > > + asm volatile ("# %0 %1 %2 %3 %4 %5" > > + : "=r" (a), "=r" (b), "=r" (c), "=r" (d), "=r" (e), "=r" (f)); > > +#ifdef __x86_64__ > > + int g, h, i, j, k, l, m, n, o, p; > > + asm volatile ("# %0 %1 %2 %3 %4 %5 %6 %7 %8 %9" > > + : "=r" (g), "=r" (h), "=r" (i), "=r" (j), "=r" (k), "=r" (l), > > "=r" (m), "=r" (n), "=r" (o), "=r" (p)); > > +#endif > > + foo (); > > + asm volatile ("# %0 %1 %2 %3 %4 %5" > > + :: "r" (a), "r" (b), "r" (c), "r" (d), "r" (e), "r" (f)); > > +#ifdef __x86_64__ > > + asm volatile ("# %0 %1 %2 %3 %4 %5 %6 %7 %8 %9" > > + : : "r" (g), "r" (h), "r" (i), "r" (j), "r" (k), "r" (l), "r" > > (m), "r" (n), "r" (o), "r" (p)); > > +#endif > > +} > > + > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%edx, > > \[0-9\]*\\(%\[re\]?sp\\)" } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%ecx, > > \[0-9\]*\\(%\[re\]?sp\\)" } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%esi, > > \[0-9\]*\\(%\[re\]?sp\\)" } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%edi, > > \[0-9\]*\\(%\[re\]?sp\\)" } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %edx" } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %ecx" } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %esi" } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %edi" } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%r8d, > > \[0-9\]*\\(%\[re\]?sp\\)" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%r9d, > > \[0-9\]*\\(%\[re\]?sp\\)" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%r10d, > > \[0-9\]*\\(%\[re\]?sp\\)" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%r11d, > > \[0-9\]*\\(%\[re\]?sp\\)" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%r12d, > > \[0-9\]*\\(%\[re\]?sp\\)" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%r13d, > > \[0-9\]*\\(%\[re\]?sp\\)" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%r14d, > > \[0-9\]*\\(%\[re\]?sp\\)" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%r15d, > > \[0-9\]*\\(%\[re\]?sp\\)" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %r8d" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %r9d" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %r10d" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %r11d" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %r12d" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %r13d" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %r14d" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %r15d" { target { ! ia32 } } } } */ > > diff --git a/gcc/testsuite/gcc.target/i386/no-caller-saved-2.c > > b/gcc/testsuite/gcc.target/i386/no-caller-saved-2.c > > new file mode 100644 > > index 00000000000..47b671dfa40 > > --- /dev/null > > +++ b/gcc/testsuite/gcc.target/i386/no-caller-saved-2.c > > @@ -0,0 +1,49 @@ > > +/* PR target/124798 */ > > +/* { dg-do compile } */ > > +/* { dg-options "-O2 -mtune=corei7 > > -mtune-ctrl=^prologue_using_move,^epilogue_using_move -fomit-frame-pointer" > > } */ > > + > > +[[gnu::no_caller_saved_registers]] extern int foo (void); > > + > > +int > > +qux (void) > > +{ > > + int a, b, c, d, e, f; > > + asm volatile ("# %0 %1 %2 %3 %4 %5" > > + : "=r" (a), "=r" (b), "=r" (c), "=r" (d), "=r" (e), "=r" (f)); > > +#ifdef __x86_64__ > > + int g, h, i, j, k, l, m, n, o, p; > > + asm volatile ("# %0 %1 %2 %3 %4 %5 %6 %7 %8 %9" > > + : "=r" (g), "=r" (h), "=r" (i), "=r" (j), "=r" (k), "=r" (l), > > "=r" (m), "=r" (n), "=r" (o), "=r" (p)); > > +#endif > > + int ret = foo (); > > + asm volatile ("# %0 %1 %2 %3 %4 %5" > > + :: "r" (a), "r" (b), "r" (c), "r" (d), "r" (e), "r" (f)); > > +#ifdef __x86_64__ > > + asm volatile ("# %0 %1 %2 %3 %4 %5 %6 %7 %8 %9" > > + : : "r" (g), "r" (h), "r" (i), "r" (j), "r" (k), "r" (l), "r" > > (m), "r" (n), "r" (o), "r" (p)); > > +#endif > > + > > + return ret; > > +} > > + > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%ecx, > > \[0-9\]*\\(%\[re\]?sp\\)" } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%esi, > > \[0-9\]*\\(%\[re\]?sp\\)" } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%edi, > > \[0-9\]*\\(%\[re\]?sp\\)" } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %ecx" } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %esi" } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %edi" } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%r8d, > > \[0-9\]*\\(%\[re\]?sp\\)" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%r9d, > > \[0-9\]*\\(%\[re\]?sp\\)" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%r10d, > > \[0-9\]*\\(%\[re\]?sp\\)" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%r11d, > > \[0-9\]*\\(%\[re\]?sp\\)" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%r12d, > > \[0-9\]*\\(%\[re\]?sp\\)" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%r13d, > > \[0-9\]*\\(%\[re\]?sp\\)" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%r14d, > > \[0-9\]*\\(%\[re\]?sp\\)" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%r15d, > > \[0-9\]*\\(%\[re\]?sp\\)" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %r8d" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %r9d" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %r10d" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %r11d" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %r12d" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %r13d" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %r15d" { target { ! ia32 } } } } */ > > diff --git a/gcc/testsuite/gcc.target/i386/no-caller-saved-3.c > > b/gcc/testsuite/gcc.target/i386/no-caller-saved-3.c > > new file mode 100644 > > index 00000000000..990b870c323 > > --- /dev/null > > +++ b/gcc/testsuite/gcc.target/i386/no-caller-saved-3.c > > @@ -0,0 +1,49 @@ > > +/* PR target/124798 */ > > +/* { dg-do compile } */ > > +/* { dg-options "-O2 -mtune=corei7 > > -mtune-ctrl=^prologue_using_move,^epilogue_using_move -fomit-frame-pointer" > > } */ > > + > > +[[gnu::no_caller_saved_registers]] extern long long foo (void); > > + > > +long long > > +qux (void) > > +{ > > + int a, b, c, d, e, f; > > + asm volatile ("# %0 %1 %2 %3 %4 %5" > > + : "=r" (a), "=r" (b), "=r" (c), "=r" (d), "=r" (e), "=r" (f)); > > +#ifdef __x86_64__ > > + int g, h, i, j, k, l, m, n, o, p; > > + asm volatile ("# %0 %1 %2 %3 %4 %5 %6 %7 %8 %9" > > + : "=r" (g), "=r" (h), "=r" (i), "=r" (j), "=r" (k), "=r" (l), > > "=r" (m), "=r" (n), "=r" (o), "=r" (p)); > > +#endif > > + long long ret = foo (); > > + asm volatile ("# %0 %1 %2 %3 %4 %5" > > + :: "r" (a), "r" (b), "r" (c), "r" (d), "r" (e), "r" (f)); > > +#ifdef __x86_64__ > > + asm volatile ("# %0 %1 %2 %3 %4 %5 %6 %7 %8 %9" > > + : : "r" (g), "r" (h), "r" (i), "r" (j), "r" (k), "r" (l), "r" > > (m), "r" (n), "r" (o), "r" (p)); > > +#endif > > + > > + return ret; > > +} > > + > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%ecx, > > \[0-9\]*\\(%\[re\]?sp\\)" } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%esi, > > \[0-9\]*\\(%\[re\]?sp\\)" } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%edi, > > \[0-9\]*\\(%\[re\]?sp\\)" } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %ecx" } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %esi" } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %edi" } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%r8d, > > \[0-9\]*\\(%\[re\]?sp\\)" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%r9d, > > \[0-9\]*\\(%\[re\]?sp\\)" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%r10d, > > \[0-9\]*\\(%\[re\]?sp\\)" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%r11d, > > \[0-9\]*\\(%\[re\]?sp\\)" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%r12d, > > \[0-9\]*\\(%\[re\]?sp\\)" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%r13d, > > \[0-9\]*\\(%\[re\]?sp\\)" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%r14d, > > \[0-9\]*\\(%\[re\]?sp\\)" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%r15d, > > \[0-9\]*\\(%\[re\]?sp\\)" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %r8d" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %r9d" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %r10d" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %r11d" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %r12d" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %r13d" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %r15d" { target { ! ia32 } } } } */ > > diff --git a/gcc/testsuite/gcc.target/i386/no-caller-saved-4.c > > b/gcc/testsuite/gcc.target/i386/no-caller-saved-4.c > > new file mode 100644 > > index 00000000000..9f6b494bdb7 > > --- /dev/null > > +++ b/gcc/testsuite/gcc.target/i386/no-caller-saved-4.c > > @@ -0,0 +1,44 @@ > > +/* PR target/124798 */ > > +/* { dg-do compile { target int128 } } */ > > +/* { dg-options "-O2 -mtune=corei7 > > -mtune-ctrl=^prologue_using_move,^epilogue_using_move -fomit-frame-pointer" > > } */ > > + > > +[[gnu::no_caller_saved_registers]] extern __int128 foo (void); > > + > > +__int128 > > +qux (void) > > +{ > > + int a, b, c, d, e, f; > > + asm volatile ("# %0 %1 %2 %3 %4 %5" > > + : "=r" (a), "=r" (b), "=r" (c), "=r" (d), "=r" (e), "=r" (f)); > > +#ifdef __x86_64__ > > + int g, h, i, j, k, l, m, n; > > + asm volatile ("# %0 %1 %2 %3 %4 %5 %6 %7" > > + : "=r" (g), "=r" (h), "=r" (i), "=r" (j), "=r" (k), "=r" (l), > > "=r" (m), "=r" (n)); > > +#endif > > + __int128 ret = foo (); > > + asm volatile ("# %0 %1 %2 %3 %4 %5" > > + :: "r" (a), "r" (b), "r" (c), "r" (d), "r" (e), "r" (f)); > > +#ifdef __x86_64__ > > + asm volatile ("# %0 %1 %2 %3 %4 %5 %6 %7" > > + : : "r" (g), "r" (h), "r" (i), "r" (j), "r" (k), "r" (l), "r" > > (m), "r" (n)); > > +#endif > > + > > + return ret; > > +} > > + > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%edx, > > \[0-9\]*\\(%\[re\]?sp\\)" } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%ecx, > > \[0-9\]*\\(%\[re\]?sp\\)" } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%esi, > > \[0-9\]*\\(%\[re\]?sp\\)" } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%edi, > > \[0-9\]*\\(%\[re\]?sp\\)" } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %edx" } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %ecx" } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %esi" } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %edi" } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%r8d, > > \[0-9\]*\\(%\[re\]?sp\\)" } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%r9d, > > \[0-9\]*\\(%\[re\]?sp\\)" } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%r10d, > > \[0-9\]*\\(%\[re\]?sp\\)" } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%r11d, > > \[0-9\]*\\(%\[re\]?sp\\)" } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %r8d" } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %r9d" } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %r10d" } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %r11d" } } */ > > diff --git a/gcc/testsuite/gcc.target/i386/no-caller-saved-5.c > > b/gcc/testsuite/gcc.target/i386/no-caller-saved-5.c > > new file mode 100644 > > index 00000000000..98f58fe92f5 > > --- /dev/null > > +++ b/gcc/testsuite/gcc.target/i386/no-caller-saved-5.c > > @@ -0,0 +1,34 @@ > > +/* PR target/124798 */ > > +/* { dg-do compile } */ > > +/* { dg-options "-O2 -mtune=corei7 -msse2 > > -mtune-ctrl=^prologue_using_move,^epilogue_using_move -fomit-frame-pointer" > > } */ > > + > > +[[gnu::no_caller_saved_registers]] extern float foo (void); > > + > > +float > > +qux (void) > > +{ > > + float a, b, c, d, e, f; > > + asm volatile ("# %0 %1 %2 %3 %4 %5" > > + : "=v" (a), "=v" (b), "=v" (c), "=v" (d), "=v" (e), "=v" (f)); > > +#ifdef __x86_64__ > > + float g, h, i, j, k, l, m, n, o, p; > > + asm volatile ("# %0 %1" > > + : "=v" (g), "=v" (h)); > > + asm volatile ("# %0 %1 %2 %3 %4 %5 %6 %7" > > + : "=v" (i), "=v" (j), "=v" (k), "=v" (l), "=v" (m), "=v" (n), > > "=v" (o), "=v" (p)); > > +#endif > > + float ret = foo (); > > + asm volatile ("# %0 %1 %2 %3 %4 %5" > > + :: "v" (a), "v" (b), "v" (c), "v" (d), "v" (e), "v" (f)); > > +#ifdef __x86_64__ > > + asm volatile ("# %0 %1" > > + :: "v" (g), "v" (h)); > > + asm volatile ("# %0 %1 %2 %3 %4 %5 %6 %7" > > + : : "v" (i), "v" (j), "v" (k), "v" (l), "v" (m), "v" (n), "v" > > (o), "v" (p)); > > +#endif > > + > > + return ret; > > +} > > + > > +/* { dg-final { scan-assembler-not "movss\[ \\t\]+%xmm\[0-9\]+, > > \[0-9\]*\\(%\[re\]?sp\\)" } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %xmm\[0-9\]+" } } */ > > diff --git a/gcc/testsuite/gcc.target/i386/no-caller-saved-6.c > > b/gcc/testsuite/gcc.target/i386/no-caller-saved-6.c > > new file mode 100644 > > index 00000000000..5eb5b102843 > > --- /dev/null > > +++ b/gcc/testsuite/gcc.target/i386/no-caller-saved-6.c > > @@ -0,0 +1,34 @@ > > +/* PR target/124798 */ > > +/* { dg-do compile } */ > > +/* { dg-options "-O2 -mtune=corei7 -msse2 > > -mtune-ctrl=^prologue_using_move,^epilogue_using_move -fomit-frame-pointer" > > } */ > > + > > +[[gnu::no_caller_saved_registers]] extern _Complex double foo (void); > > + > > +_Complex double > > +qux (void) > > +{ > > + double a, b, c, d, e, f; > > + asm volatile ("# %0 %1 %2 %3 %4 %5" > > + : "=v" (a), "=v" (b), "=v" (c), "=v" (d), "=v" (e), "=v" (f)); > > +#ifdef __x86_64__ > > + double g, h, i, j, k, l, m, n, o, p; > > + asm volatile ("# %0 %1" > > + : "=v" (g), "=v" (h)); > > + asm volatile ("# %0 %1 %2 %3 %4 %5 %6 %7" > > + : "=v" (i), "=v" (j), "=v" (k), "=v" (l), "=v" (m), "=v" (n), > > "=v" (o), "=v" (p)); > > +#endif > > + _Complex double ret = foo (); > > + asm volatile ("# %0 %1 %2 %3 %4 %5" > > + :: "v" (a), "v" (b), "v" (c), "v" (d), "v" (e), "v" (f)); > > +#ifdef __x86_64__ > > + asm volatile ("# %0 %1" > > + :: "v" (g), "v" (h)); > > + asm volatile ("# %0 %1 %2 %3 %4 %5 %6 %7" > > + : : "v" (i), "v" (j), "v" (k), "v" (l), "v" (m), "v" (n), "v" > > (o), "v" (p)); > > +#endif > > + > > + return ret; > > +} > > + > > +/* { dg-final { scan-assembler-not "movss\[ \\t\]+%xmm\[0-9\]+, > > \[0-9\]*\\(%\[re\]?sp\\)" } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %xmm\[0-9\]+" } } */ > > diff --git a/gcc/testsuite/gcc.target/i386/no-caller-saved-7.c > > b/gcc/testsuite/gcc.target/i386/no-caller-saved-7.c > > new file mode 100644 > > index 00000000000..c8a99e950da > > --- /dev/null > > +++ b/gcc/testsuite/gcc.target/i386/no-caller-saved-7.c > > @@ -0,0 +1,49 @@ > > +/* PR target/124798 */ > > +/* { dg-do compile } */ > > +/* { dg-options "-O2 -mtune=corei7 > > -mtune-ctrl=^prologue_using_move,^epilogue_using_move -fomit-frame-pointer" > > } */ > > + > > +typedef struct > > +{ > > + double d[16]; > > +} record; > > + > > +[[gnu::no_caller_saved_registers]] extern record foo (void); > > + > > +record > > +qux (void) > > +{ > > + int a, b, c, d, e, f; > > + asm volatile ("# %0 %1 %2 %3 %4 %5" > > + : "=r" (a), "=r" (b), "=r" (c), "=r" (d), "=r" (e), "=r" (f)); > > +#ifdef __x86_64__ > > + int g, h, i, j; > > + asm volatile ("# %0 %1 %2 %3" > > + : "=r" (g), "=r" (h), "=r" (i), "=r" (j)); > > +#endif > > + record ret = foo (); > > + asm volatile ("# %0 %1 %2 %3 %4 %5" > > + :: "r" (a), "r" (b), "r" (c), "r" (d), "r" (e), "r" (f)); > > +#ifdef __x86_64__ > > + asm volatile ("# %0 %1 %2 %3" > > + :: "r" (g), "r" (h), "r" (i), "r" (j)); > > +#endif > > + > > + return ret; > > +} > > + > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%edx, > > \[0-9\]*\\(%\[re\]?sp\\)" } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%ecx, > > \[0-9\]*\\(%\[re\]?sp\\)" } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%esi, > > \[0-9\]*\\(%\[re\]?sp\\)" } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%edi, > > \[0-9\]*\\(%\[re\]?sp\\)" } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %edx" } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %ecx" } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %esi" } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %edi" } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%r8d, > > \[0-9\]*\\(%\[re\]?sp\\)" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%r9d, > > \[0-9\]*\\(%\[re\]?sp\\)" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%r10d, > > \[0-9\]*\\(%\[re\]?sp\\)" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ \\t\]+%r11d, > > \[0-9\]*\\(%\[re\]?sp\\)" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %r8d" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %r9d" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %r10d" { target { ! ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "mov(l|q)\[ > > \\t\]+\[0-9\]*\\(%\[re\]?sp\\), %r11d" { target { ! ia32 } } } } */ > > diff --git a/gcc/testsuite/gcc.target/i386/preserve-none-14.c > > b/gcc/testsuite/gcc.target/i386/preserve-none-14.c > > index ca23b586fa1..175eb25acd6 100644 > > --- a/gcc/testsuite/gcc.target/i386/preserve-none-14.c > > +++ b/gcc/testsuite/gcc.target/i386/preserve-none-14.c > > @@ -17,7 +17,6 @@ foo (fn_t bar) > > /* { dg-final { scan-assembler-times "push(?:l|q)\[\\t \]*%(?:e|r)bx" 1 } > > } */ > > /* { dg-final { scan-assembler-not "push(?:l|q)\[\\t \]*%(?:e|r)cx" } } */ > > /* { dg-final { scan-assembler-not "push(?:l|q)\[\\t \]*%(?:e|r)dx" } } */ > > -/* { dg-final { scan-assembler-not "push(?:l|q)\[\\t \]*%(?:e|r)bp" } } */ > > /* { dg-final { scan-assembler-times "pushl\[\\t \]*%esi" 1 { target ia32 > > } } } */ > > /* { dg-final { scan-assembler-not "pushq\[\\t \]*%rsi" { target { ! ia32 > > } } } } */ > > /* { dg-final { scan-assembler-times "pushl\[\\t \]*%edi" 1 { target ia32 > > } } } */ > > @@ -34,7 +33,6 @@ foo (fn_t bar) > > /* { dg-final { scan-assembler-times "pop(?:l|q)\[\\t \]*%(?:e|r)bx" 1 } } > > */ > > /* { dg-final { scan-assembler-not "pop(?:l|q)\[\\t \]*%(?:e|r)cx" } } */ > > /* { dg-final { scan-assembler-not "pop(?:l|q)\[\\t \]*%(?:e|r)dx" } } */ > > -/* { dg-final { scan-assembler-not "pop(?:l|q)\[\\t \]*%(?:e|r)bp" } } */ > > /* { dg-final { scan-assembler-times "popl\[\\t \]*%esi" 1 { target ia32 } > > } } */ > > /* { dg-final { scan-assembler-not "popq\[\\t \]*%rsi" { target { ! ia32 } > > } } } */ > > /* { dg-final { scan-assembler-times "popl\[\\t \]*%edi" 1 { target ia32 } > > } } */ > > diff --git a/gcc/testsuite/gcc.target/i386/preserve-none-23.c > > b/gcc/testsuite/gcc.target/i386/preserve-none-23.c > > index 8e83879443f..629bd695374 100644 > > --- a/gcc/testsuite/gcc.target/i386/preserve-none-23.c > > +++ b/gcc/testsuite/gcc.target/i386/preserve-none-23.c > > @@ -19,7 +19,6 @@ foo (uintptr_t p) > > /* { dg-final { scan-assembler-times "push(?:l|q)\[\\t \]*%(?:e|r)bx" 1 } > > } */ > > /* { dg-final { scan-assembler-not "push(?:l|q)\[\\t \]*%(?:e|r)cx" } } */ > > /* { dg-final { scan-assembler-not "push(?:l|q)\[\\t \]*%(?:e|r)dx" } } */ > > -/* { dg-final { scan-assembler-not "push(?:l|q)\[\\t \]*%(?:e|r)bp" } } */ > > /* { dg-final { scan-assembler-times "pushl\[\\t \]*%esi" 1 { target ia32 > > } } } */ > > /* { dg-final { scan-assembler-not "pushq\[\\t \]*%rsi" { target { ! ia32 > > } } } } */ > > /* { dg-final { scan-assembler-times "pushl\[\\t \]*%edi" 1 { target ia32 > > } } } */ > > @@ -36,7 +35,6 @@ foo (uintptr_t p) > > /* { dg-final { scan-assembler-times "pop(?:l|q)\[\\t \]*%(?:e|r)bx" 1 } } > > */ > > /* { dg-final { scan-assembler-not "pop(?:l|q)\[\\t \]*%(?:e|r)cx" } } */ > > /* { dg-final { scan-assembler-not "pop(?:l|q)\[\\t \]*%(?:e|r)dx" } } */ > > -/* { dg-final { scan-assembler-not "pop(?:l|q)\[\\t \]*%(?:e|r)bp" } } */ > > /* { dg-final { scan-assembler-times "popl\[\\t \]*%esi" 1 { target ia32 } > > } } */ > > /* { dg-final { scan-assembler-not "popq\[\\t \]*%rsi" { target { ! ia32 } > > } } } */ > > /* { dg-final { scan-assembler-times "popl\[\\t \]*%edi" 1 { target ia32 } > > } } */ > > diff --git a/gcc/testsuite/gcc.target/i386/preserve-none-7.c > > b/gcc/testsuite/gcc.target/i386/preserve-none-7.c > > index 2c80560887c..6f252ee50a4 100644 > > --- a/gcc/testsuite/gcc.target/i386/preserve-none-7.c > > +++ b/gcc/testsuite/gcc.target/i386/preserve-none-7.c > > @@ -26,7 +26,9 @@ foo (void *frame) > > } > > } > > > > -/* { dg-final { scan-assembler-times "push(?:l|q)\[\\t \]*%(?:e|r)bp" 1 } > > } */ > > -/* { dg-final { scan-assembler-times "pop(?:l|q)\[\\t \]*%(?:e|r)bp" 1 } } > > */ > > -/* { dg-final { scan-assembler-times "push(?:l|q)\[\\t \]*" 1 } } */ > > -/* { dg-final { scan-assembler-times "pop(?:l|q)\[\\t \]*" 1 } } */ > > +/* { dg-final { scan-assembler-times "push(?:l|q)\[\\t \]*%(?:e|r)bp" 1 { > > target ia32 } } } */ > > +/* { dg-final { scan-assembler-times "pop(?:l|q)\[\\t \]*%(?:e|r)bp" 1 { > > target ia32 } } } */ > > +/* { dg-final { scan-assembler-times "push(?:l|q)\[\\t \]*" 1 { target > > ia32 } } } */ > > +/* { dg-final { scan-assembler-times "pop(?:l|q)\[\\t \]*" 1 { target ia32 > > } } } */ > > +/* { dg-final { scan-assembler-not "push(?:l|q)\[\\t \]*" { target { ! > > ia32 } } } } */ > > +/* { dg-final { scan-assembler-not "pop(?:l|q)\[\\t \]*" { target { ! ia32 > > } } } } */ > > diff --git a/gcc/testsuite/gcc.target/i386/stack-check-17.c > > b/gcc/testsuite/gcc.target/i386/stack-check-17.c > > index 924a459c4e2..ed2f341b106 100644 > > --- a/gcc/testsuite/gcc.target/i386/stack-check-17.c > > +++ b/gcc/testsuite/gcc.target/i386/stack-check-17.c > > @@ -32,5 +32,4 @@ f3 (void) > > register on ia32 for a noreturn function. */ > > /* { dg-final { scan-assembler-times "push\[ql\]" 1 { target { ! ia32 } } > > } } */ > > /* { dg-final { scan-assembler-times "push\[ql\]" 3 { target ia32 } } } */ > > -/* { dg-final { scan-assembler-not "pop" { target { ! ia32 } } } } */ > > -/* { dg-final { scan-assembler-times "pop" 1 { target ia32 } } } */ > > +/* { dg-final { scan-assembler-times "pop\[ql\]" 1 } } */ -- H.J.
