Implement TARGET_FNTYPE_ABI to avoid spills of callee-saved registers when calling functions with no_caller_saved_registers attribute.
After commit 754c6600fe058f1026098fde57860bbc38cc28fe Author: Richard Sandiford <[email protected]> Date: Wed Jun 3 13:11:17 2026 +0100 Add CALL_INSN_ABI_ID there is no need for ix86_expand_call to add clobbers for when one ABI calls another ABI. ABI_ALTERNATE is the alternate function ABI from the system ABI. 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. This target hook also properly marks the implicit __tls_get_addr call: (call_insn/u 9 8 10 (parallel [ (set (reg:DI 0 ax) (call:DI (mem:QI (symbol_ref:DI ("__tls_get_addr")) [0 S1 A8]) (const_int 0 [0]))) (unspec:DI [ (reg/f:DI 7 sp) ] UNSPEC_TLS_LD_BASE) (clobber (reg:DI 5 di)) ]) "x.c":7:16 -1 (expr_list:REG_EH_REGION (const_int -2147483648 [0xffffffff80000000]) (nil)) (nil) 0) with ABI_DEFAULT function ABI. Tested on Linux/x86-64 and with CPython 3.14.4. gcc/ PR target/124798 PR target/125436 * config/i386/i386-expand.cc: Include "function-abi.h". (x86_64_ms_sysv_extra_clobbered_registers): Removed. (ix86_expand_call): Don't add explicit call and ABI-switch clobbers. * config/i386/i386-features.cc (ix86_place_single_tls_call): Set CALL_INSN_ABI_ID on TLS calls. * config/i386/i386-options.cc (ix86_set_current_function): Don't call reinit_regs. * config/i386/i386-protos.h (ix86_type_no_callee_saved_registers_p): Removed. (ix86_tls_get_addr_abi): New. * config/i386/i386.cc (ix86_alternate_abi): New prototype. (ix86_conditional_register_usage): Changed to describe the system ABI. (ix86_type_no_callee_saved_registers_p): Make it static. (ix86_function_value_regno_p): Replace ix86_cfun_abi () with ix86_abi. (ix86_save_reg): Only check TYPE_NO_CALLEE_SAVED_REGISTERS as a special case. (ix86_tls_get_addr_abi): New. (legitimize_tls_address): Set CALL_INSN_ABI_ID on TLS calls. Call ix86_alternate_abi to initialize the alternate function ABI. (ix86_initialize_abi): New function. (ix86_no_callee_saved_abi): Likewise. (ix86_no_caller_saved_abi): Likewise. (ix86_standard_abi): Likewise. (ix86_alternate_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_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 PR target/125436 * gcc.target/i386/abi-mix-1.c: New test. * gcc.target/i386/abi-mix-2.c: Likewise. * gcc.target/i386/no-callee-saved-20.c: Likewise. * gcc.target/i386/no-caller-saved-1-ms.c: Likewise. * 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/pr125436-1a.c: Likewise. * gcc.target/i386/pr125436-1b.c: Likewise. * gcc.target/i386/pr125436-2a.c: Likewise. * gcc.target/i386/pr125436-2b.c: Likewise. * gcc.target/i386/pr125436-3.c: Likewise. * gcc.target/i386/pr125436-4.c: Likewise. * 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. Signed-off-by: H.J. Lu <[email protected]> Co-Authored by: Richard Sandiford <[email protected]> --- gcc/config/i386/i386-expand.cc | 113 +----- gcc/config/i386/i386-features.cc | 2 + gcc/config/i386/i386-options.cc | 17 - gcc/config/i386/i386-protos.h | 3 +- gcc/config/i386/i386.cc | 336 +++++++++++++++--- gcc/config/i386/i386.md | 30 +- gcc/testsuite/gcc.target/i386/abi-mix-1.c | 20 ++ gcc/testsuite/gcc.target/i386/abi-mix-2.c | 6 + .../gcc.target/i386/no-callee-saved-18.c | 2 - .../gcc.target/i386/no-callee-saved-19b.c | 32 +- .../gcc.target/i386/no-callee-saved-19d.c | 6 +- .../gcc.target/i386/no-callee-saved-19e.c | 33 +- .../gcc.target/i386/no-callee-saved-2.c | 10 +- .../gcc.target/i386/no-callee-saved-20.c | 92 +++++ .../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/testsuite/gcc.target/i386/pr125436-1a.c | 130 +++++++ gcc/testsuite/gcc.target/i386/pr125436-1b.c | 81 +++++ gcc/testsuite/gcc.target/i386/pr125436-2a.c | 132 +++++++ gcc/testsuite/gcc.target/i386/pr125436-2b.c | 83 +++++ gcc/testsuite/gcc.target/i386/pr125436-3.c | 88 +++++ gcc/testsuite/gcc.target/i386/pr125436-4.c | 88 +++++ .../gcc.target/i386/preserve-none-14.c | 2 - .../gcc.target/i386/preserve-none-23.c | 2 - .../gcc.target/i386/preserve-none-7.c | 10 +- 34 files changed, 1503 insertions(+), 238 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/abi-mix-1.c create mode 100644 gcc/testsuite/gcc.target/i386/abi-mix-2.c create mode 100644 gcc/testsuite/gcc.target/i386/no-callee-saved-20.c 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 create mode 100644 gcc/testsuite/gcc.target/i386/pr125436-1a.c create mode 100644 gcc/testsuite/gcc.target/i386/pr125436-1b.c create mode 100644 gcc/testsuite/gcc.target/i386/pr125436-2a.c create mode 100644 gcc/testsuite/gcc.target/i386/pr125436-2b.c create mode 100644 gcc/testsuite/gcc.target/i386/pr125436-3.c create mode 100644 gcc/testsuite/gcc.target/i386/pr125436-4.c diff --git a/gcc/config/i386/i386-expand.cc b/gcc/config/i386/i386-expand.cc index 07756897fad..18b259a660d 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 @@ -11094,17 +11095,6 @@ construct_plt_address (rtx symbol) return tmp; } -/* Additional registers that are clobbered by SYSV calls. */ - -static int const x86_64_ms_sysv_extra_clobbered_registers - [NUM_X86_64_MS_CLOBBERED_REGS] = -{ - SI_REG, DI_REG, - XMM6_REG, XMM7_REG, - XMM8_REG, XMM9_REG, XMM10_REG, XMM11_REG, - XMM12_REG, XMM13_REG, XMM14_REG, XMM15_REG -}; - rtx_insn * ix86_expand_call (rtx retval, rtx fnaddr, rtx callarg1, rtx callarg2, @@ -11114,7 +11104,6 @@ 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; if (SYMBOL_REF_P (XEXP (fnaddr, 0))) { @@ -11124,26 +11113,13 @@ 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; if (fndecl == current_function_decl && decl_binds_to_current_def_p (fndecl)) cfun->machine->recursive_function = true; } } else - { - 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; - } - - fndecl = NULL_TREE; - } + fndecl = NULL_TREE; if (pop == const0_rtx) pop = NULL; @@ -11280,62 +11256,26 @@ ix86_expand_call (rtx retval, rtx fnaddr, rtx callarg1, vec[vec_len++] = pop; } - static const char ix86_call_used_regs[] = CALL_USED_REGISTERS; - - if ((cfun->machine->call_saved_registers - == TYPE_NO_CALLER_SAVED_REGISTERS) - && (!fndecl - || (!TREE_THIS_VOLATILE (fndecl) - && !lookup_attribute ("no_caller_saved_registers", - TYPE_ATTRIBUTES (TREE_TYPE (fndecl)))))) + /* Set here, but it may get cleared later. */ + if (TARGET_64BIT_MS_ABI + && (!callarg2 || INTVAL (callarg2) != -2) + && TARGET_CALL_MS2SYSV_XLOGUES) { - bool is_64bit_ms_abi = (TARGET_64BIT - && ix86_function_abi (fndecl) == MS_ABI); - char c_mask = CALL_USED_REGISTERS_MASK (is_64bit_ms_abi); - - /* If there are no caller-saved registers, add all registers - that are clobbered by the call which returns. */ - 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)) - && !STACK_REGNO_P (i) - && !MMX_REGNO_P (i)) - clobber_reg (&use, - gen_rtx_REG (GET_MODE (regno_reg_rtx[i]), i)); - } - else if (TARGET_64BIT_MS_ABI - && (!callarg2 || INTVAL (callarg2) != -2)) - { - unsigned i; + if (!TARGET_SSE) + ; - for (i = 0; i < NUM_X86_64_MS_CLOBBERED_REGS; i++) - { - int regno = x86_64_ms_sysv_extra_clobbered_registers[i]; - machine_mode mode = SSE_REGNO_P (regno) ? TImode : DImode; + /* Don't break hot-patched functions. */ + else if (ix86_function_ms_hook_prologue (current_function_decl)) + ; - clobber_reg (&use, gen_rtx_REG (mode, regno)); - } + /* TODO: Cases not yet examined. */ + else if (flag_split_stack) + warn_once_call_ms2sysv_xlogues ("-fsplit-stack"); - /* Set here, but it may get cleared later. */ - if (TARGET_CALL_MS2SYSV_XLOGUES) + else { - if (!TARGET_SSE) - ; - - /* Don't break hot-patched functions. */ - else if (ix86_function_ms_hook_prologue (current_function_decl)) - ; - - /* TODO: Cases not yet examined. */ - else if (flag_split_stack) - warn_once_call_ms2sysv_xlogues ("-fsplit-stack"); - - else - { - gcc_assert (!reload_completed); - cfun->machine->call_ms2sysv = true; - } + gcc_assert (!reload_completed); + cfun->machine->call_ms2sysv = true; } } @@ -11353,25 +11293,6 @@ ix86_expand_call (rtx retval, rtx fnaddr, rtx callarg1, clobber_reg (&use, gen_rtx_REG (DImode, R10_REG)); } - if (call_no_callee_saved_registers) - { - /* 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] - && 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)) - clobber_reg (&use, - gen_rtx_REG (GET_MODE (regno_reg_rtx[i]), i)); - } - if (vec_len > 1) call = gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (vec_len, vec)); rtx_insn *call_insn = emit_call_insn (call); diff --git a/gcc/config/i386/i386-features.cc b/gcc/config/i386/i386-features.cc index f5caef29c6e..aef364ba8b7 100644 --- a/gcc/config/i386/i386-features.cc +++ b/gcc/config/i386/i386-features.cc @@ -4505,6 +4505,7 @@ ix86_place_single_tls_call (rtx dest, rtx val, x86_cse_kind kind, symbol = XVECEXP (val, 0, 0); tls = gen_tls_global_dynamic_64 (Pmode, rax, symbol, caddr, rdi); + CALL_INSN_ABI_ID (tls) = ix86_tls_get_addr_abi ().id (); if (GET_MODE (symbol) != Pmode) symbol = gen_rtx_ZERO_EXTEND (Pmode, symbol); @@ -4517,6 +4518,7 @@ ix86_place_single_tls_call (rtx dest, rtx val, x86_cse_kind kind, caddr = ix86_tls_get_addr (); tls = gen_tls_local_dynamic_base_64 (Pmode, rax, caddr, rdi); + CALL_INSN_ABI_ID (tls) = ix86_tls_get_addr_abi ().id (); /* Attach a unique REG_EQUAL to DEST, to allow the RTL optimizers to share the LD_BASE result with other LD model accesses. */ diff --git a/gcc/config/i386/i386-options.cc b/gcc/config/i386/i386-options.cc index 626e1eab929..7aa9daf9ae1 100644 --- a/gcc/config/i386/i386-options.cc +++ b/gcc/config/i386/i386-options.cc @@ -3527,21 +3527,6 @@ ix86_set_current_function (tree fndecl) } ix86_previous_fndecl = fndecl; - static call_saved_registers_type prev_call_saved_registers; - - /* 64-bit MS and SYSV ABI have different set of call used registers. - Avoid expensive re-initialization of init_regs each time we switch - function context. */ - if (TARGET_64BIT - && (call_used_or_fixed_reg_p (SI_REG) - == (cfun->machine->call_abi == MS_ABI))) - reinit_regs (); - /* Need to re-initialize init_regs if caller-saved registers are - changed. */ - else if (prev_call_saved_registers - != cfun->machine->call_saved_registers) - reinit_regs (); - if (cfun->machine->func_type != TYPE_NORMAL || (cfun->machine->call_saved_registers == TYPE_NO_CALLER_SAVED_REGISTERS)) @@ -3589,8 +3574,6 @@ ix86_set_current_function (tree fndecl) = TYPE_DEFAULT_CALL_SAVED_REGISTERS; } } - - prev_call_saved_registers = cfun->machine->call_saved_registers; } /* Implement the TARGET_OFFLOAD_OPTIONS hook. */ diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h index 7dac3ed8e6c..ea23f75804a 100644 --- a/gcc/config/i386/i386-protos.h +++ b/gcc/config/i386/i386-protos.h @@ -286,7 +286,6 @@ 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 @@ -295,6 +294,8 @@ extern bool ix86_gpr_tls_address_pattern_p (rtx); extern bool ix86_tls_address_pattern_p (rtx); extern rtx ix86_rewrite_tls_address (rtx); extern rtx ix86_tls_get_addr (void); +class predefined_function_abi; +extern const predefined_function_abi & ix86_tls_get_addr_abi (void); extern void ix86_expand_vector_init (bool, rtx, rtx); extern void ix86_expand_vector_set (bool, rtx, rtx, int); diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc index 5bcf7254ab2..86bd6caf59f 100644 --- a/gcc/config/i386/i386.cc +++ b/gcc/config/i386/i386.cc @@ -107,6 +107,7 @@ along with GCC; see the file COPYING3. If not see static void ix86_print_operand_address_as (FILE *, rtx, addr_space_t, bool); static void ix86_emit_restore_reg_using_pop (rtx, bool = false); +static const predefined_function_abi & ix86_alternate_abi (void); #ifndef CHECK_STACK_LIMIT @@ -503,17 +504,6 @@ 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; - /* For 32-bit targets, disable the REX registers. */ if (! TARGET_64BIT) { @@ -525,8 +515,10 @@ ix86_conditional_register_usage (void) CLEAR_HARD_REG_BIT (accessible_reg_set, i); } - /* See the definition of CALL_USED_REGISTERS in i386.h. */ - c_mask = CALL_USED_REGISTERS_MASK (TARGET_64BIT_MS_ABI); + /* Set up the call-used registers based on the system ABI (ix86_abi). + + See the definition of CALL_USED_REGISTERS in i386.h. */ + c_mask = CALL_USED_REGISTERS_MASK (TARGET_64BIT && ix86_abi == MS_ABI); CLEAR_HARD_REG_SET (reg_class_contents[(int)CLOBBERED_REGS]); @@ -932,7 +924,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 fntype) { auto type = ix86_fntype_call_saved_registers (fntype); @@ -3871,10 +3863,10 @@ ix86_function_value_regno_p (const unsigned int regno) /* Complex values are returned in %st(0)/%st(1) pair. */ case ST0_REG: case ST1_REG: - /* TODO: The function should depend on current function ABI but - builtins.cc would need updating then. Therefore we use the - default ABI. */ - if (TARGET_64BIT && ix86_cfun_abi () == MS_ABI) + /* TODO: An ABI identifier should be passed as a parameter. + For now, most callers, including those in builtins.cc, + expect us to use the default ABI. */ + if (TARGET_64BIT && ix86_abi == MS_ABI) return false; return TARGET_FLOAT_RETURNS_IN_80387; @@ -6796,8 +6788,6 @@ ix86_hard_regno_scratch_ok (unsigned int regno) bool 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 @@ -6805,41 +6795,12 @@ ix86_save_reg (unsigned int regno, bool maybe_eh_return, bool ignore_outlined) && !cfun->machine->no_drap_save_restore) return true; - 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, we preserve all - registers, except for MMX and x87 registers which aren't - supported when saving and restoring registers. Don't - explicitly save SP register since it is always preserved. - - Don't preserve registers used for function return value. */ - reg = crtl->return_rtx; - if (reg) - { - unsigned int i = REGNO (reg); - unsigned int nregs = REG_NREGS (reg); - while (nregs-- > 0) - if ((i + nregs) == regno) - return false; - } - - return (df_regs_ever_live_p (regno) - && !fixed_regs[regno] - && !STACK_REGNO_P (regno) - && !MMX_REGNO_P (regno) - && (regno != HARD_FRAME_POINTER_REGNUM - || !frame_pointer_needed)); - - case TYPE_NO_CALLEE_SAVED_REGISTERS: - case TYPE_PRESERVE_NONE: - if (regno != HARD_FRAME_POINTER_REGNUM) - return false; - break; - } + /* ??? Treat no_callee_saved_registers as a special case in order + to cope with -mnoreturn-no-callee-saved-registers, which is not + reflected in crtl->abi. */ + if (cfun->machine->call_saved_registers == TYPE_NO_CALLEE_SAVED_REGISTERS + && regno != HARD_FRAME_POINTER_REGNUM) + return false; if (regno == REAL_PIC_OFFSET_TABLE_REGNUM && pic_offset_table_rtx) @@ -12574,6 +12535,18 @@ ix86_tls_get_addr (void) return ix86_tls_symbol; } +/* Return the descriptor of the function ABI type for the tls_get_addr + function. */ + +const predefined_function_abi & +ix86_tls_get_addr_abi (void) +{ + if (ix86_abi == SYSV_ABI) + return default_function_abi; + else + return ix86_alternate_abi (); +} + /* Construct the SYMBOL_REF for the _TLS_MODULE_BASE_ symbol. */ static GTY(()) rtx ix86_tls_module_base_symbol; @@ -12684,8 +12657,10 @@ legitimize_tls_address (rtx x, enum tls_model model, bool for_mov) rtx_insn *insns; start_sequence (); - emit_call_insn + rtx_insn *call_insn = emit_call_insn (gen_tls_global_dynamic_64 (Pmode, rax, x, caddr, rdi)); + CALL_INSN_ABI_ID (call_insn) + = ix86_tls_get_addr_abi ().id (); insns = end_sequence (); if (GET_MODE (x) != Pmode) @@ -12739,8 +12714,10 @@ legitimize_tls_address (rtx x, enum tls_model model, bool for_mov) rtx eqv; start_sequence (); - emit_call_insn + rtx_insn *call_insn = emit_call_insn (gen_tls_local_dynamic_base_64 (Pmode, rax, caddr, rdi)); + CALL_INSN_ABI_ID (call_insn) + = ix86_tls_get_addr_abi ().id (); insns = end_sequence (); /* Attach a unique REG_EQUAL, to allow the RTL optimizers to @@ -21738,6 +21715,219 @@ ix86_hard_regno_mode_ok (unsigned int regno, machine_mode mode) return false; } +/* Initialize function_abis[ABI_ID] with the set of register clobbers + in FULL_REG_CLOBBERS, adjusting for rules that apply to all ABIs. */ + +static void +ix86_initialize_abi (unsigned int abi_id, HARD_REG_SET full_reg_clobbers) +{ + /* The general rule is that fixed registers should be marked as + call-clobbered. This includes global registers, inaccessible + registers, the flags register, and the FPSR. + + Handle the exceptions below. */ + full_reg_clobbers |= fixed_reg_set; + + /* Every ABI (even preserve_none) preserves EBP/RBP. */ + CLEAR_HARD_REG_BIT (full_reg_clobbers, HARD_FRAME_POINTER_REGNUM); + + /* Treat GCC's internal frame-related registers as call-preserved. */ + CLEAR_HARD_REG_BIT (full_reg_clobbers, FRAME_POINTER_REGNUM); + CLEAR_HARD_REG_BIT (full_reg_clobbers, ARG_POINTER_REGNUM); + + function_abis[abi_id].initialize (abi_id, full_reg_clobbers); +} + +/* Return the descriptor of no_callee_saved_registers function type. + None of the enabled registers are preserved, except for the common + rules applied by ix86_initialize_abi. */ + +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 ()) + ix86_initialize_abi (ABI_NO_CALLEE_SAVED, accessible_reg_set); + return no_callee_saved_abi; +} + +/* Return the descriptor of the no_caller_saved_registers function type + with ABI identifier ABI_ID. All registers are preserved, except for: + + - the return registers, which are enumerated in ABI_ID. + + - the common rules applied by ix86_initialize_abi. */ + +static const predefined_function_abi & +ix86_no_caller_saved_abi (unsigned int abi_id) +{ + auto &abi = function_abis[abi_id]; + if (!abi.initialized_p ()) + { + HARD_REG_SET full_reg_clobbers = {}; + + switch (abi_id) + { + case ABI_NO_CALLER_SAVED_RETURN_VOID: + break; + + case ABI_NO_CALLER_SAVED_RETURN_AX_DX: + SET_HARD_REG_BIT (full_reg_clobbers, DX_REG); + /* Fall through. */ + case ABI_NO_CALLER_SAVED_RETURN_AX: + SET_HARD_REG_BIT (full_reg_clobbers, AX_REG); + break; + + case ABI_NO_CALLER_SAVED_RETURN_XMM0_XMM1: + SET_HARD_REG_BIT (full_reg_clobbers, XMM1_REG); + /* Fall through. */ + case ABI_NO_CALLER_SAVED_RETURN_XMM0: + SET_HARD_REG_BIT (full_reg_clobbers, XMM0_REG); + break; + } + + ix86_initialize_abi (abi_id, full_reg_clobbers); + } + return abi; +} + +/* Return the descriptor of the standard function ABI type. If + ABI_TYPE == ABI_ALTERNATE, return the function alternate ABI type. */ + +static const predefined_function_abi & +ix86_standard_abi (int abi_type) +{ + static const char ix86_call_used_regs[] = CALL_USED_REGISTERS; + auto &standard_abi = function_abis[abi_type]; + if (!standard_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 == (abi_type == ABI_ALTERNATE + ? SYSV_ABI : MS_ABI)); + char c_mask = CALL_USED_REGISTERS_MASK (is_64bit_ms_abi); + for (int i = 0; i < FIRST_PSEUDO_REGISTER; i++) + if (ix86_call_used_regs[i] == 1 + || (ix86_call_used_regs[i] & c_mask)) + SET_HARD_REG_BIT (full_reg_clobbers, i); + + ix86_initialize_abi (abi_type, full_reg_clobbers); + } + return standard_abi; +} + +/* Return the descriptor of the function alternate ABI type. */ + +static const predefined_function_abi & +ix86_alternate_abi (void) +{ + return ix86_standard_abi (ABI_ALTERNATE); +} + +/* Return the function ABI ID based on FNTYPE. */ + +static int +ix86_function_abi_id (const_tree fntype) +{ + auto call_saved_registers = ix86_fntype_call_saved_registers (fntype); + if (call_saved_registers == TYPE_PRESERVE_NONE + || call_saved_registers == TYPE_NO_CALLEE_SAVED_REGISTERS) + return ABI_NO_CALLEE_SAVED; + + if (call_saved_registers == TYPE_NO_CALLER_SAVED_REGISTERS) + { + 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; + gcc_unreachable (); + 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_DEFAULT; +} + +/* Implement TARGET_FNTYPE_ABI. */ + +static const predefined_function_abi & +ix86_fntype_abi (const_tree fntype) +{ + unsigned int abi_id = ix86_function_abi_id (fntype); + switch (abi_id) + { + case ABI_DEFAULT: + return default_function_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: + case ABI_NO_CALLER_SAVED_RETURN_AX: + case ABI_NO_CALLER_SAVED_RETURN_AX_DX: + case ABI_NO_CALLER_SAVED_RETURN_XMM0: + case ABI_NO_CALLER_SAVED_RETURN_XMM0_XMM1: + return ix86_no_caller_saved_abi (abi_id); + + default: + gcc_unreachable (); + } + + return default_function_abi; +} + /* Initialize function_abis with corresponding abi_id, currently only handle vzeroupper. */ void @@ -21776,12 +21966,37 @@ 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) + 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_DEFAULT: + 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: + case ABI_NO_CALLER_SAVED_RETURN_XMM0_XMM1: + /* These ABIs return some values in SSE registers and preserve + the rest. The return value registers (XMM0 and possibly XMM1) + are fully rather than partially call-clobbered. */ + return false; + + default: + gcc_unreachable (); + } + return SSE_REGNO_P (regno) && GET_MODE_SIZE (mode) > 16; } @@ -28708,6 +28923,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_CAN_CHANGE_MODE_CLASS #define TARGET_CAN_CHANGE_MODE_CLASS ix86_can_change_mode_class diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index be4b615c542..05d6f6d62f0 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -513,9 +513,33 @@ (define_constants ;; Insn callee abi index. (define_constants - [(ABI_DEFAULT 0) - (ABI_VZEROUPPER 1) - (ABI_UNKNOWN 2)]) + [;; The system ABI; that is, the ABI associated with ix86_abi, and the + ;; ABI that an undecorated "void foo()" would have. + (ABI_DEFAULT 0) + ;; An ABI that describes the effect of vzeroupper. vzeroupper is + ;; represented as a call because calls are the main mechanism for + ;; expression partial register clobbers. + (ABI_VZEROUPPER 1) + ;; ABI_ALTERNATE is the Windows function ABI if ix86_abi == SYSV_ABI + ;; and is the SYSV function ABI if ix86_abi == MS_ABI. + (ABI_ALTERNATE 2) + (ABI_NO_CALLEE_SAVED 3) + ;; Return void. + (ABI_NO_CALLER_SAVED_RETURN_VOID 4) + ;; 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 5) + ;; Return int64 and _Complex int in 32-bit. + ;; Return _Complex int64 in 64-bit. + (ABI_NO_CALLER_SAVED_RETURN_AX_DX 6) + ;; 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 7) + ;; Return _Complex double in SYSV 64-bit. + (ABI_NO_CALLER_SAVED_RETURN_XMM0_XMM1 8) + (ABI_UNKNOWN 9)]) ;; Insns whose names begin with "x86_" are emitted by gen_FOO calls ;; from i386.cc. diff --git a/gcc/testsuite/gcc.target/i386/abi-mix-1.c b/gcc/testsuite/gcc.target/i386/abi-mix-1.c new file mode 100644 index 00000000000..342da642bf2 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/abi-mix-1.c @@ -0,0 +1,20 @@ +/* { dg-options "-O2 -masm=att -mno-mmx -mno-80387 -msse" } */ + +extern void callee_clobbered () [[gnu::preserve_none]]; +extern void callee_preserved () [[gnu::no_caller_saved_registers]]; +extern void callee_sysv () [[gnu::sysv_abi]]; +extern void callee_ms () [[gnu::ms_abi]]; + +#define TEST(PREFIX, ATTR) \ + void PREFIX##_clobbered () [[ATTR]] { callee_clobbered (); } \ + void PREFIX##_preserved () [[ATTR]] { callee_preserved (); } \ + void PREFIX##_sysv () [[ATTR]] { callee_sysv (); } \ + void PREFIX##_ms () [[ATTR]] { callee_ms (); } + +TEST (clobbered, gnu::preserve_none) +TEST (preserved, gnu::no_caller_saved_registers) +TEST (sysv, gnu::sysv_abi) +TEST (ms, gnu::ms_abi) + +/* { dg-final { scan-assembler-not "%st" } } */ +/* { dg-final { scan-assembler "%xmm" } } */ diff --git a/gcc/testsuite/gcc.target/i386/abi-mix-2.c b/gcc/testsuite/gcc.target/i386/abi-mix-2.c new file mode 100644 index 00000000000..14428a6d3a4 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/abi-mix-2.c @@ -0,0 +1,6 @@ +/* { dg-options "-O2 -masm=att -mno-mmx -mno-80387 -mno-sse" } */ + +#include "abi-mix-1.c" + +/* { dg-final { scan-assembler-not "%st" } } */ +/* { dg-final { scan-assembler-not "%xmm" } } */ 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..f64172c737f 100644 --- a/gcc/testsuite/gcc.target/i386/no-callee-saved-19b.c +++ b/gcc/testsuite/gcc.target/i386/no-callee-saved-19b.c @@ -1,4 +1,4 @@ -/* { dg-do compile { target { *-*-linux* && maybe_x32 } } } */ +/* { dg-do compile { target { *-*-linux* && { lp64 && maybe_x32 } } } } */ /* { dg-options "-O2 -mx32 -fno-pic -mtune=generic -msse2 -mno-avx -mno-mmx -mno-80387 -mno-apxf -mtune-ctrl=prologue_using_move,epilogue_using_move" } */ /* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ /* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^\t?\.} } } */ @@ -52,15 +52,14 @@ ** .cfi_startproc ** subl \$376, %esp **... -** movq %rax, 256\(%rsp\) -** movq %rdx, 264\(%rsp\) -** movq %rcx, 272\(%rsp\) -** movq %rbx, 280\(%rsp\) -** movq %rsi, 288\(%rsp\) -** movq %rdi, 296\(%rsp\) +** movq %rdi, 304\(%rsp\) **... ** movl \$code\+4, %edi -** movq %rbp, 304\(%rsp\) +** movq %rax, 264\(%rsp\) +** movq %rdx, 272\(%rsp\) +** movq %rcx, 280\(%rsp\) +** movq %rbx, 288\(%rsp\) +** movq %rsi, 296\(%rsp\) ** movq %r8, 312\(%rsp\) ** movq %r9, 320\(%rsp\) ** movq %r10, 328\(%rsp\) @@ -86,8 +85,8 @@ ** movaps %xmm14, 224\(%rsp\) ** movaps %xmm15, 240\(%rsp\) **... -** movl code\(%rip\), %ebp -** call \*%rbp +** movl code\(%rip\), %eax +** call \*%rax ** movaps \(%rsp\), %xmm0 ** movaps 16\(%rsp\), %xmm1 ** movaps 32\(%rsp\), %xmm2 @@ -104,13 +103,12 @@ ** movaps 208\(%rsp\), %xmm13 ** movaps 224\(%rsp\), %xmm14 ** movaps 240\(%rsp\), %xmm15 -** movq 256\(%rsp\), %rax -** movq 264\(%rsp\), %rdx -** movq 272\(%rsp\), %rcx -** movq 280\(%rsp\), %rbx -** movq 288\(%rsp\), %rsi -** movq 296\(%rsp\), %rdi -** movq 304\(%rsp\), %rbp +** movq 264\(%rsp\), %rax +** movq 272\(%rsp\), %rdx +** movq 280\(%rsp\), %rcx +** movq 288\(%rsp\), %rbx +** movq 296\(%rsp\), %rsi +** movq 304\(%rsp\), %rdi ** movq 312\(%rsp\), %r8 ** movq 320\(%rsp\), %r9 ** movq 328\(%rsp\), %r10 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..b715d9aff8e 100644 --- a/gcc/testsuite/gcc.target/i386/no-callee-saved-19e.c +++ b/gcc/testsuite/gcc.target/i386/no-callee-saved-19e.c @@ -1,4 +1,4 @@ -/* { dg-do compile { target { *-*-linux* && maybe_x32 } } } */ +/* { dg-do compile { target { *-*-linux* && { lp64 && maybe_x32 } } } } */ /* { dg-options "-O2 -mx32 -fno-pic -mtune=generic -msse2 -mno-avx -mno-mmx -mno-80387 -mapxf -mtune-ctrl=prologue_using_move,epilogue_using_move" } */ /* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ /* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^\t?\.} } } */ @@ -52,15 +52,14 @@ ** .cfi_startproc ** subl \$504, %esp **... -** movq %rax, 256\(%rsp\) -** movq %rdx, 264\(%rsp\) -** movq %rcx, 272\(%rsp\) -** movq %rbx, 280\(%rsp\) -** movq %rsi, 288\(%rsp\) -** movq %rdi, 296\(%rsp\) +** movq %rax, 264\(%rsp\) +** movq %rdi, 304\(%rsp\) **... ** movl \$code\+4, %edi -** movq %rbp, 304\(%rsp\) +** movq %rdx, 272\(%rsp\) +** movq %rcx, 280\(%rsp\) +** movq %rbx, 288\(%rsp\) +** movq %rsi, 296\(%rsp\) ** movq %r8, 312\(%rsp\) ** movq %r9, 320\(%rsp\) ** movq %r10, 328\(%rsp\) @@ -85,9 +84,8 @@ ** movq %r29, 480\(%rsp\) ** movq %r30, 488\(%rsp\) ** movq %r31, 496\(%rsp\) -**... -** movl code\(%rip\), %ebp ** movaps %xmm0, \(%rsp\) +** movl code\(%rip\), %eax ** movaps %xmm1, 16\(%rsp\) ** movaps %xmm2, 32\(%rsp\) ** movaps %xmm3, 48\(%rsp\) @@ -104,7 +102,7 @@ ** movaps %xmm14, 224\(%rsp\) ** movaps %xmm15, 240\(%rsp\) **... -** call \*%rbp +** call \*%rax ** movaps \(%rsp\), %xmm0 ** movaps 16\(%rsp\), %xmm1 ** movaps 32\(%rsp\), %xmm2 @@ -121,13 +119,12 @@ ** movaps 208\(%rsp\), %xmm13 ** movaps 224\(%rsp\), %xmm14 ** movaps 240\(%rsp\), %xmm15 -** movq 256\(%rsp\), %rax -** movq 264\(%rsp\), %rdx -** movq 272\(%rsp\), %rcx -** movq 280\(%rsp\), %rbx -** movq 288\(%rsp\), %rsi -** movq 296\(%rsp\), %rdi -** movq 304\(%rsp\), %rbp +** movq 264\(%rsp\), %rax +** movq 272\(%rsp\), %rdx +** movq 280\(%rsp\), %rcx +** movq 288\(%rsp\), %rbx +** movq 296\(%rsp\), %rsi +** movq 304\(%rsp\), %rdi ** movq 312\(%rsp\), %r8 ** movq 320\(%rsp\), %r9 ** movq 328\(%rsp\), %r10 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-20.c b/gcc/testsuite/gcc.target/i386/no-callee-saved-20.c new file mode 100644 index 00000000000..56bf4569d02 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/no-callee-saved-20.c @@ -0,0 +1,92 @@ +/* { dg-do compile { target { *-*-linux* && lp64 } } } */ +/* { dg-options "-O2 -fno-pic -mgeneral-regs-only -mtune=generic -mtune-ctrl=prologue_using_move,epilogue_using_move" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^\t?\.} } } */ + +__attribute__((no_callee_saved_registers, noipa)) +void +foo (void) +{ +} + +/* +**bar: +**.LFB[0-9]+: +** .cfi_startproc +** subq \$376, %rsp +**... +** movq %rax, 264\(%rsp\) +** movq %rdx, 272\(%rsp\) +** movq %rcx, 280\(%rsp\) +** movq %rbx, 288\(%rsp\) +** movq %rsi, 296\(%rsp\) +** movq %rdi, 304\(%rsp\) +** movq %r8, 312\(%rsp\) +** movq %r9, 320\(%rsp\) +** movq %r10, 328\(%rsp\) +** movq %r11, 336\(%rsp\) +** movq %r12, 344\(%rsp\) +** movq %r13, 352\(%rsp\) +** movq %r14, 360\(%rsp\) +** movq %r15, 368\(%rsp\) +** movaps %xmm0, \(%rsp\) +** movaps %xmm1, 16\(%rsp\) +** movaps %xmm2, 32\(%rsp\) +** movaps %xmm3, 48\(%rsp\) +** movaps %xmm4, 64\(%rsp\) +** movaps %xmm5, 80\(%rsp\) +** movaps %xmm6, 96\(%rsp\) +** movaps %xmm7, 112\(%rsp\) +** movaps %xmm8, 128\(%rsp\) +** movaps %xmm9, 144\(%rsp\) +** movaps %xmm10, 160\(%rsp\) +** movaps %xmm11, 176\(%rsp\) +** movaps %xmm12, 192\(%rsp\) +** movaps %xmm13, 208\(%rsp\) +** movaps %xmm14, 224\(%rsp\) +** movaps %xmm15, 240\(%rsp\) +**... +** call foo +** movaps \(%rsp\), %xmm0 +** movaps 16\(%rsp\), %xmm1 +** movaps 32\(%rsp\), %xmm2 +** movaps 48\(%rsp\), %xmm3 +** movaps 64\(%rsp\), %xmm4 +** movaps 80\(%rsp\), %xmm5 +** movaps 96\(%rsp\), %xmm6 +** movaps 112\(%rsp\), %xmm7 +** movaps 128\(%rsp\), %xmm8 +** movaps 144\(%rsp\), %xmm9 +** movaps 160\(%rsp\), %xmm10 +** movaps 176\(%rsp\), %xmm11 +** movaps 192\(%rsp\), %xmm12 +** movaps 208\(%rsp\), %xmm13 +** movq 264\(%rsp\), %rax +** movq 272\(%rsp\), %rdx +** movq 280\(%rsp\), %rcx +** movq 288\(%rsp\), %rbx +** movq 296\(%rsp\), %rsi +** movq 304\(%rsp\), %rdi +** movq 312\(%rsp\), %r8 +** movq 320\(%rsp\), %r9 +** movq 328\(%rsp\), %r10 +** movq 336\(%rsp\), %r11 +** movq 344\(%rsp\), %r12 +** movq 352\(%rsp\), %r13 +** movq 360\(%rsp\), %r14 +** movq 368\(%rsp\), %r15 +** movaps 224\(%rsp\), %xmm14 +** movaps 240\(%rsp\), %xmm15 +** addq \$376, %rsp +**... +** ret +** .cfi_endproc +**... +*/ + +__attribute__((no_caller_saved_registers, target("sse2"))) +void +bar (void) +{ + foo (); +} 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/pr125436-1a.c b/gcc/testsuite/gcc.target/i386/pr125436-1a.c new file mode 100644 index 00000000000..be3c2509fc6 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr125436-1a.c @@ -0,0 +1,130 @@ +/* { dg-do compile { target { *-*-linux* && lp64 } } } */ +/* { dg-options "-O1 -fPIC -mtls-dialect=gnu -mtune-ctrl=^prologue_using_move,^epilogue_using_move -mno-push-args -fomit-frame-pointer -mtune=generic" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^\t?\.} } } */ + +/* +**ms_tls_access: +**.LFB[0-9]+: +** .cfi_startproc +** pushq %rdi +** .cfi_def_cfa_offset 16 +** .cfi_offset 5, -16 +** pushq %rsi +** .cfi_def_cfa_offset 24 +** .cfi_offset 4, -24 +** pushq %rbx +** .cfi_def_cfa_offset 32 +** .cfi_offset 3, -32 +** subq \$160, %rsp +** .cfi_def_cfa_offset 192 +** movaps %xmm6, \(%rsp\) +** movaps %xmm7, 16\(%rsp\) +** movaps %xmm8, 32\(%rsp\) +** movaps %xmm9, 48\(%rsp\) +** movaps %xmm10, 64\(%rsp\) +** movaps %xmm11, 80\(%rsp\) +** movaps %xmm12, 96\(%rsp\) +** movaps %xmm13, 112\(%rsp\) +** movaps %xmm14, 128\(%rsp\) +** movaps %xmm15, 144\(%rsp\) +** .cfi_offset 23, -192 +** .cfi_offset 24, -176 +** .cfi_offset 25, -160 +** .cfi_offset 26, -144 +** .cfi_offset 27, -128 +** .cfi_offset 28, -112 +** .cfi_offset 29, -96 +** .cfi_offset 30, -80 +** .cfi_offset 31, -64 +** .cfi_offset 32, -48 +** movl %ecx, %ebx +** leaq tls_instance@tlsld\(%rip\), %rdi +** call __tls_get_addr@PLT +** addl %ebx, tls_instance@dtpoff\(%rax\) +** movaps \(%rsp\), %xmm6 +** movaps 16\(%rsp\), %xmm7 +** movaps 32\(%rsp\), %xmm8 +** movaps 48\(%rsp\), %xmm9 +** movaps 64\(%rsp\), %xmm10 +** movaps 80\(%rsp\), %xmm11 +** movaps 96\(%rsp\), %xmm12 +** movaps 112\(%rsp\), %xmm13 +** movaps 128\(%rsp\), %xmm14 +** movaps 144\(%rsp\), %xmm15 +** addq \$160, %rsp +** .cfi_restore 32 +** .cfi_restore 31 +** .cfi_restore 30 +** .cfi_restore 29 +** .cfi_restore 28 +** .cfi_restore 27 +** .cfi_restore 26 +** .cfi_restore 25 +** .cfi_restore 24 +** .cfi_restore 23 +** .cfi_def_cfa_offset 32 +** popq %rbx +** .cfi_restore 3 +** .cfi_def_cfa_offset 24 +** popq %rsi +** .cfi_restore 4 +** .cfi_def_cfa_offset 16 +** popq %rdi +** .cfi_restore 5 +** .cfi_def_cfa_offset 8 +** ret +** .cfi_endproc +**... +*/ + +static volatile int magic_number = 0x12345678; + +static __thread int tls_instance = 0; + +__attribute__ ((ms_abi)) +void +ms_tls_access (int i) +{ + tls_instance += i; +} + +__attribute__ ((sysv_abi)) +int +sysv_foo (int i) +{ + double A = magic_number; + double B = magic_number; + int a = magic_number; + int b = magic_number; + int c = magic_number; + int d = magic_number; + int e = magic_number; + int f = magic_number; + int g = magic_number; + int h = magic_number; + + ms_tls_access (i); + + return (a ^ b) ^ (c ^ d) ^ (e ^ f) ^ (g ^ h) + (int)(A - B); +} + +__attribute__ ((ms_abi)) +int +ms_foo (int i) +{ + double A = magic_number; + double B = magic_number; + int a = magic_number; + int b = magic_number; + int c = magic_number; + int d = magic_number; + int e = magic_number; + int f = magic_number; + int g = magic_number; + int h = magic_number; + + ms_tls_access (i); + + return a ^ b ^ c ^ d ^ e ^ f ^ g ^ h + (int)(A - B); +} diff --git a/gcc/testsuite/gcc.target/i386/pr125436-1b.c b/gcc/testsuite/gcc.target/i386/pr125436-1b.c new file mode 100644 index 00000000000..9b6e4a508c9 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr125436-1b.c @@ -0,0 +1,81 @@ +/* { dg-do compile { target { *-*-linux* && lp64 } } } */ +/* { dg-options "-O1 -fPIC -mabi=ms -mtls-dialect=gnu -mtune-ctrl=^prologue_using_move,^epilogue_using_move -mno-push-args -fomit-frame-pointer -mtune=generic" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^\t?\.} } } */ + +/* +**ms_tls_access: +**.LFB[0-9]+: +** .cfi_startproc +** pushq %rdi +** .cfi_def_cfa_offset 16 +** .cfi_offset 5, -16 +** pushq %rsi +** .cfi_def_cfa_offset 24 +** .cfi_offset 4, -24 +** pushq %rbx +** .cfi_def_cfa_offset 32 +** .cfi_offset 3, -32 +** subq \$160, %rsp +** .cfi_def_cfa_offset 192 +** movaps %xmm6, \(%rsp\) +** movaps %xmm7, 16\(%rsp\) +** movaps %xmm8, 32\(%rsp\) +** movaps %xmm9, 48\(%rsp\) +** movaps %xmm10, 64\(%rsp\) +** movaps %xmm11, 80\(%rsp\) +** movaps %xmm12, 96\(%rsp\) +** movaps %xmm13, 112\(%rsp\) +** movaps %xmm14, 128\(%rsp\) +** movaps %xmm15, 144\(%rsp\) +** .cfi_offset 23, -192 +** .cfi_offset 24, -176 +** .cfi_offset 25, -160 +** .cfi_offset 26, -144 +** .cfi_offset 27, -128 +** .cfi_offset 28, -112 +** .cfi_offset 29, -96 +** .cfi_offset 30, -80 +** .cfi_offset 31, -64 +** .cfi_offset 32, -48 +** movl %ecx, %ebx +** leaq tls_instance@tlsld\(%rip\), %rdi +** call __tls_get_addr@PLT +** addl %ebx, tls_instance@dtpoff\(%rax\) +** movaps \(%rsp\), %xmm6 +** movaps 16\(%rsp\), %xmm7 +** movaps 32\(%rsp\), %xmm8 +** movaps 48\(%rsp\), %xmm9 +** movaps 64\(%rsp\), %xmm10 +** movaps 80\(%rsp\), %xmm11 +** movaps 96\(%rsp\), %xmm12 +** movaps 112\(%rsp\), %xmm13 +** movaps 128\(%rsp\), %xmm14 +** movaps 144\(%rsp\), %xmm15 +** addq \$160, %rsp +** .cfi_restore 32 +** .cfi_restore 31 +** .cfi_restore 30 +** .cfi_restore 29 +** .cfi_restore 28 +** .cfi_restore 27 +** .cfi_restore 26 +** .cfi_restore 25 +** .cfi_restore 24 +** .cfi_restore 23 +** .cfi_def_cfa_offset 32 +** popq %rbx +** .cfi_restore 3 +** .cfi_def_cfa_offset 24 +** popq %rsi +** .cfi_restore 4 +** .cfi_def_cfa_offset 16 +** popq %rdi +** .cfi_restore 5 +** .cfi_def_cfa_offset 8 +** ret +** .cfi_endproc +**... +*/ + +#include "pr125436-1a.c" diff --git a/gcc/testsuite/gcc.target/i386/pr125436-2a.c b/gcc/testsuite/gcc.target/i386/pr125436-2a.c new file mode 100644 index 00000000000..9126d3ca2ab --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr125436-2a.c @@ -0,0 +1,132 @@ +/* { dg-do compile { target { *-*-linux* && lp64 } } } */ +/* { dg-options "-O1 -fPIC -mtls-dialect=gnu -mtune-ctrl=^prologue_using_move,^epilogue_using_move -mno-push-args -fomit-frame-pointer -mtune=generic" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^\t?\.} } } */ + +/* +**ms_tls_access: +**.LFB[0-9]+: +** .cfi_startproc +** pushq %rdi +** .cfi_def_cfa_offset 16 +** .cfi_offset 5, -16 +** pushq %rsi +** .cfi_def_cfa_offset 24 +** .cfi_offset 4, -24 +** pushq %rbx +** .cfi_def_cfa_offset 32 +** .cfi_offset 3, -32 +** subq \$160, %rsp +** .cfi_def_cfa_offset 192 +** movaps %xmm6, \(%rsp\) +** movaps %xmm7, 16\(%rsp\) +** movaps %xmm8, 32\(%rsp\) +** movaps %xmm9, 48\(%rsp\) +** movaps %xmm10, 64\(%rsp\) +** movaps %xmm11, 80\(%rsp\) +** movaps %xmm12, 96\(%rsp\) +** movaps %xmm13, 112\(%rsp\) +** movaps %xmm14, 128\(%rsp\) +** movaps %xmm15, 144\(%rsp\) +** .cfi_offset 23, -192 +** .cfi_offset 24, -176 +** .cfi_offset 25, -160 +** .cfi_offset 26, -144 +** .cfi_offset 27, -128 +** .cfi_offset 28, -112 +** .cfi_offset 29, -96 +** .cfi_offset 30, -80 +** .cfi_offset 31, -64 +** .cfi_offset 32, -48 +** movl %ecx, %ebx +** data16 leaq tls_instance@tlsgd\(%rip\), %rdi +** .value 0x6666 +** rex64 +** call __tls_get_addr@PLT +** addl %ebx, \(%rax\) +** movaps \(%rsp\), %xmm6 +** movaps 16\(%rsp\), %xmm7 +** movaps 32\(%rsp\), %xmm8 +** movaps 48\(%rsp\), %xmm9 +** movaps 64\(%rsp\), %xmm10 +** movaps 80\(%rsp\), %xmm11 +** movaps 96\(%rsp\), %xmm12 +** movaps 112\(%rsp\), %xmm13 +** movaps 128\(%rsp\), %xmm14 +** movaps 144\(%rsp\), %xmm15 +** addq \$160, %rsp +** .cfi_restore 32 +** .cfi_restore 31 +** .cfi_restore 30 +** .cfi_restore 29 +** .cfi_restore 28 +** .cfi_restore 27 +** .cfi_restore 26 +** .cfi_restore 25 +** .cfi_restore 24 +** .cfi_restore 23 +** .cfi_def_cfa_offset 32 +** popq %rbx +** .cfi_restore 3 +** .cfi_def_cfa_offset 24 +** popq %rsi +** .cfi_restore 4 +** .cfi_def_cfa_offset 16 +** popq %rdi +** .cfi_restore 5 +** .cfi_def_cfa_offset 8 +** ret +** .cfi_endproc +**... +*/ + +static volatile int magic_number = 0x12345678; + +__thread int tls_instance = 0; + +__attribute__ ((ms_abi)) +void +ms_tls_access (int i) +{ + tls_instance += i; +} + +__attribute__ ((sysv_abi)) +int +sysv_foo (int i) +{ + double A = magic_number; + double B = magic_number; + int a = magic_number; + int b = magic_number; + int c = magic_number; + int d = magic_number; + int e = magic_number; + int f = magic_number; + int g = magic_number; + int h = magic_number; + + ms_tls_access (i); + + return (a ^ b) ^ (c ^ d) ^ (e ^ f) ^ (g ^ h) + (int)(A - B); +} + +__attribute__ ((ms_abi)) +int +ms_foo (int i) +{ + double A = magic_number; + double B = magic_number; + int a = magic_number; + int b = magic_number; + int c = magic_number; + int d = magic_number; + int e = magic_number; + int f = magic_number; + int g = magic_number; + int h = magic_number; + + ms_tls_access (i); + + return a ^ b ^ c ^ d ^ e ^ f ^ g ^ h + (int)(A - B); +} diff --git a/gcc/testsuite/gcc.target/i386/pr125436-2b.c b/gcc/testsuite/gcc.target/i386/pr125436-2b.c new file mode 100644 index 00000000000..4c634c9d8b0 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr125436-2b.c @@ -0,0 +1,83 @@ +/* { dg-do compile { target { *-*-linux* && lp64 } } } */ +/* { dg-options "-O1 -fPIC -mabi=ms -mtls-dialect=gnu -mtune-ctrl=^prologue_using_move,^epilogue_using_move -mno-push-args -fomit-frame-pointer -mtune=generic" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^\t?\.} } } */ + +/* +**ms_tls_access: +**.LFB[0-9]+: +** .cfi_startproc +** pushq %rdi +** .cfi_def_cfa_offset 16 +** .cfi_offset 5, -16 +** pushq %rsi +** .cfi_def_cfa_offset 24 +** .cfi_offset 4, -24 +** pushq %rbx +** .cfi_def_cfa_offset 32 +** .cfi_offset 3, -32 +** subq \$160, %rsp +** .cfi_def_cfa_offset 192 +** movaps %xmm6, \(%rsp\) +** movaps %xmm7, 16\(%rsp\) +** movaps %xmm8, 32\(%rsp\) +** movaps %xmm9, 48\(%rsp\) +** movaps %xmm10, 64\(%rsp\) +** movaps %xmm11, 80\(%rsp\) +** movaps %xmm12, 96\(%rsp\) +** movaps %xmm13, 112\(%rsp\) +** movaps %xmm14, 128\(%rsp\) +** movaps %xmm15, 144\(%rsp\) +** .cfi_offset 23, -192 +** .cfi_offset 24, -176 +** .cfi_offset 25, -160 +** .cfi_offset 26, -144 +** .cfi_offset 27, -128 +** .cfi_offset 28, -112 +** .cfi_offset 29, -96 +** .cfi_offset 30, -80 +** .cfi_offset 31, -64 +** .cfi_offset 32, -48 +** movl %ecx, %ebx +** data16 leaq tls_instance@tlsgd\(%rip\), %rdi +** .value 0x6666 +** rex64 +** call __tls_get_addr@PLT +** addl %ebx, \(%rax\) +** movaps \(%rsp\), %xmm6 +** movaps 16\(%rsp\), %xmm7 +** movaps 32\(%rsp\), %xmm8 +** movaps 48\(%rsp\), %xmm9 +** movaps 64\(%rsp\), %xmm10 +** movaps 80\(%rsp\), %xmm11 +** movaps 96\(%rsp\), %xmm12 +** movaps 112\(%rsp\), %xmm13 +** movaps 128\(%rsp\), %xmm14 +** movaps 144\(%rsp\), %xmm15 +** addq \$160, %rsp +** .cfi_restore 32 +** .cfi_restore 31 +** .cfi_restore 30 +** .cfi_restore 29 +** .cfi_restore 28 +** .cfi_restore 27 +** .cfi_restore 26 +** .cfi_restore 25 +** .cfi_restore 24 +** .cfi_restore 23 +** .cfi_def_cfa_offset 32 +** popq %rbx +** .cfi_restore 3 +** .cfi_def_cfa_offset 24 +** popq %rsi +** .cfi_restore 4 +** .cfi_def_cfa_offset 16 +** popq %rdi +** .cfi_restore 5 +** .cfi_def_cfa_offset 8 +** ret +** .cfi_endproc +**... +*/ + +#include "pr125436-2a.c" diff --git a/gcc/testsuite/gcc.target/i386/pr125436-3.c b/gcc/testsuite/gcc.target/i386/pr125436-3.c new file mode 100644 index 00000000000..939f85a586b --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr125436-3.c @@ -0,0 +1,88 @@ +/* { dg-do compile { target { *-*-linux* && lp64 } } } */ +/* { dg-options "-O1 -fPIC -mtls-dialect=gnu -mtune-ctrl=^prologue_using_move,^epilogue_using_move -mno-push-args -fomit-frame-pointer -mtune=generic" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^\t?\.} } } */ + +/* +**ms_tls_access: +**.LFB[0-9]+: +** .cfi_startproc +** pushq %rdi +** .cfi_def_cfa_offset 16 +** .cfi_offset 5, -16 +** pushq %rsi +** .cfi_def_cfa_offset 24 +** .cfi_offset 4, -24 +** pushq %rbx +** .cfi_def_cfa_offset 32 +** .cfi_offset 3, -32 +** subq \$160, %rsp +** .cfi_def_cfa_offset 192 +** movaps %xmm6, \(%rsp\) +** movaps %xmm7, 16\(%rsp\) +** movaps %xmm8, 32\(%rsp\) +** movaps %xmm9, 48\(%rsp\) +** movaps %xmm10, 64\(%rsp\) +** movaps %xmm11, 80\(%rsp\) +** movaps %xmm12, 96\(%rsp\) +** movaps %xmm13, 112\(%rsp\) +** movaps %xmm14, 128\(%rsp\) +** movaps %xmm15, 144\(%rsp\) +** .cfi_offset 23, -192 +** .cfi_offset 24, -176 +** .cfi_offset 25, -160 +** .cfi_offset 26, -144 +** .cfi_offset 27, -128 +** .cfi_offset 28, -112 +** .cfi_offset 29, -96 +** .cfi_offset 30, -80 +** .cfi_offset 31, -64 +** .cfi_offset 32, -48 +** movl %ecx, %ebx +** leaq tls_instance@tlsld\(%rip\), %rdi +** call __tls_get_addr@PLT +** addl %ebx, tls_instance@dtpoff\(%rax\) +** movaps \(%rsp\), %xmm6 +** movaps 16\(%rsp\), %xmm7 +** movaps 32\(%rsp\), %xmm8 +** movaps 48\(%rsp\), %xmm9 +** movaps 64\(%rsp\), %xmm10 +** movaps 80\(%rsp\), %xmm11 +** movaps 96\(%rsp\), %xmm12 +** movaps 112\(%rsp\), %xmm13 +** movaps 128\(%rsp\), %xmm14 +** movaps 144\(%rsp\), %xmm15 +** addq \$160, %rsp +** .cfi_restore 32 +** .cfi_restore 31 +** .cfi_restore 30 +** .cfi_restore 29 +** .cfi_restore 28 +** .cfi_restore 27 +** .cfi_restore 26 +** .cfi_restore 25 +** .cfi_restore 24 +** .cfi_restore 23 +** .cfi_def_cfa_offset 32 +** popq %rbx +** .cfi_restore 3 +** .cfi_def_cfa_offset 24 +** popq %rsi +** .cfi_restore 4 +** .cfi_def_cfa_offset 16 +** popq %rdi +** .cfi_restore 5 +** .cfi_def_cfa_offset 8 +** ret +** .cfi_endproc +**... +*/ + +static __thread int tls_instance = 0; + +__attribute__ ((ms_abi)) +void +ms_tls_access (int i) +{ + tls_instance += i; +} diff --git a/gcc/testsuite/gcc.target/i386/pr125436-4.c b/gcc/testsuite/gcc.target/i386/pr125436-4.c new file mode 100644 index 00000000000..205595810aa --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr125436-4.c @@ -0,0 +1,88 @@ +/* { dg-do compile { target { *-*-linux* && lp64 } } } */ +/* { dg-options "-O1 -fPIC -mabi=ms -mtls-dialect=gnu -mtune-ctrl=^prologue_using_move,^epilogue_using_move -mno-push-args -fomit-frame-pointer -mtune=generic" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^\t?\.} } } */ + +/* +**ms_tls_access: +**.LFB[0-9]+: +** .cfi_startproc +** pushq %rdi +** .cfi_def_cfa_offset 16 +** .cfi_offset 5, -16 +** pushq %rsi +** .cfi_def_cfa_offset 24 +** .cfi_offset 4, -24 +** pushq %rbx +** .cfi_def_cfa_offset 32 +** .cfi_offset 3, -32 +** subq \$160, %rsp +** .cfi_def_cfa_offset 192 +** movaps %xmm6, \(%rsp\) +** movaps %xmm7, 16\(%rsp\) +** movaps %xmm8, 32\(%rsp\) +** movaps %xmm9, 48\(%rsp\) +** movaps %xmm10, 64\(%rsp\) +** movaps %xmm11, 80\(%rsp\) +** movaps %xmm12, 96\(%rsp\) +** movaps %xmm13, 112\(%rsp\) +** movaps %xmm14, 128\(%rsp\) +** movaps %xmm15, 144\(%rsp\) +** .cfi_offset 23, -192 +** .cfi_offset 24, -176 +** .cfi_offset 25, -160 +** .cfi_offset 26, -144 +** .cfi_offset 27, -128 +** .cfi_offset 28, -112 +** .cfi_offset 29, -96 +** .cfi_offset 30, -80 +** .cfi_offset 31, -64 +** .cfi_offset 32, -48 +** movl %ecx, %ebx +** leaq tls_instance@tlsld\(%rip\), %rdi +** call __tls_get_addr@PLT +** addl %ebx, tls_instance@dtpoff\(%rax\) +** movaps \(%rsp\), %xmm6 +** movaps 16\(%rsp\), %xmm7 +** movaps 32\(%rsp\), %xmm8 +** movaps 48\(%rsp\), %xmm9 +** movaps 64\(%rsp\), %xmm10 +** movaps 80\(%rsp\), %xmm11 +** movaps 96\(%rsp\), %xmm12 +** movaps 112\(%rsp\), %xmm13 +** movaps 128\(%rsp\), %xmm14 +** movaps 144\(%rsp\), %xmm15 +** addq \$160, %rsp +** .cfi_restore 32 +** .cfi_restore 31 +** .cfi_restore 30 +** .cfi_restore 29 +** .cfi_restore 28 +** .cfi_restore 27 +** .cfi_restore 26 +** .cfi_restore 25 +** .cfi_restore 24 +** .cfi_restore 23 +** .cfi_def_cfa_offset 32 +** popq %rbx +** .cfi_restore 3 +** .cfi_def_cfa_offset 24 +** popq %rsi +** .cfi_restore 4 +** .cfi_def_cfa_offset 16 +** popq %rdi +** .cfi_restore 5 +** .cfi_def_cfa_offset 8 +** ret +** .cfi_endproc +**... +*/ + +static __thread int tls_instance = 0; + +__attribute__ ((ms_abi)) +void +ms_tls_access (int i) +{ + tls_instance += i; +} 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 } } } } */ -- 2.54.0
