https://gcc.gnu.org/g:754c6600fe058f1026098fde57860bbc38cc28fe
commit r17-1257-g754c6600fe058f1026098fde57860bbc38cc28fe Author: Richard Sandiford <[email protected]> Date: Wed Jun 3 13:11:17 2026 +0100 Add CALL_INSN_ABI_ID function-abi.h was originally added to cope with AArch64's vector PCS and SVE PCS variants. One of the key requirements was that a call insn must say precisely which ABI the callee uses, regardless of how the call is created. At the time, I did this by encoding the information as an UNSPEC in the AArch64 call patterns. IIRC, there were three reasons for doing it that way: (1) To make sure that the information is not accidentally dropped. (2) To make sure that calls using different ABIs are distinct (not rtx_equal_p). (3) Because it seemed presumptious to add a new CALL_INSN field for something that only AArch64 was using. However, CALL_INSN_FUNCTION_USAGE and SIBLING_CALL_P also require (1) and at least SIBLING_CALL_P requires (2). I'm not aware that this has been a common source of bugs in practice. As far as (3) goes, RISC-V now uses a similar system, and x86 is also about to use function_abi more heavily (see HJ's patches). Any target that wants to run CPython efficiently will probably want to implement preserve_none, and so adopt the same kind of approach. If we take the view that having multiple ABIs is now going to be common for "major" targets, attaching the information to the CALL_INSN would be both simpler and more compact. As it stands, targets have to smuggle the ABI information from init_cumulative_args (which supplies the function type) through function_arg (which asks the target for the final call operand) to call/call_value/etc. (which receive the information from function_arg). It's all a bit of a mess. This patch therefore adds a new CALL_INSN_ABI_ID field to CALL_INSN and removes the now-redundant insn_callee_abi hook. This makes UNSPEC_CALLEE_CC unnecessary on RISC-V, so the patch reverts the call patterns to something like their state before r14-3733-gfdd59c0f73e9e6 (which is in no way a comment against that patch). In contrast, AArch64 still uses the ABI "cookie" for other information, so it needs to be kept. The patch reflows the CALL_INSN_FUNCTION_USAGE documentation but otherwise just does s/@code{CALL_INSN_FUNCTION_USAGE}/This field/. gcc/ * rtl.def (CALL_INSN): Add a new integer field. * rtl.h (CALL_INSN_ABI_ID): New macro. * target.def (insn_callee_abi): Delete. * doc/rtl.texi: Document CALL_INSN_ABI_ID. * doc/tm.texi.in (TARGET_INSN_CALLEE_ABI): Remove. * doc/tm.texi: Regenerate. * calls.cc: Include regs.h and function-abi.h. (emit_call_1): Initialize CALL_INSN_ABI_ID. * cfgcleanup.cc (old_insns_match_p): Compare CALL_INSN_ABI_IDs. * emit-rtl.cc (try_split): Copy the original insn's CALL_INSN_ABI_ID to the new call. (emit_copy_of_insn_after): Likewise. (make_call_insn_raw): Initialise CALL_INSN_ABI_ID. * function-abi.cc (insn_callee_abi): Remove use of the insn_callee_abi hook and instead use CALL_INSN_ABI_ID. * recog.cc (peep2_attempt): Copy the original insn's CALL_INSN_ABI_ID to the new call. * config/aarch64/aarch64-protos.h (aarch64_gen_callee_cookie): Remove arm_pcs parameter. * config/aarch64/aarch64.cc (aarch64_gen_callee_cookie): Likewise. (aarch64_callee_abi): Delete. (aarch64_insn_callee_abi): Likewise. (aarch64_function_arg): Update call to aarch64_callee_abi. (aarch64_output_mi_thunk): Likewise. Set CALL_INSN_ABI_ID instead. (TARGET_INSN_CALLEE_ABI): Delete. * config/aarch64/aarch64.md (tlsdesc_small_<mode>): Update call to aarch64_callee_abi and set CALL_INSN_ABI_ID instead. * config/i386/i386.cc (ix86_insn_callee_abi): Delete. (ix86_expand_avx_vzeroupper): Set CALL_INSN_ABI_ID. (TARGET_INSN_CALLEE_ABI): Delete. * config/riscv/riscv-sr.cc (riscv_remove_unneeded_save_restore_calls): Remove coding convention from calls to gen_sibcall_internal and gen_sibcall_value_internal. Store the ABI identifier in CALL_INSN_ABI_ID instead. * config/riscv/riscv.cc (riscv_output_mi_thunk): Likewise. (riscv_call_tls_get_addr): Likewise, but calling gen_call_value. (riscv_function_arg): Return null for the end marker. (get_riscv_cc, riscv_insn_callee_abi): Delete. (TARGET_INSN_CALLEE_ABI): Delete. * config/riscv/riscv.md (UNSPEC_CALLEE_CC): Delete. (sibcall): Revert to treating operand 2 as a placeholder. Do not pass it to gen_sibcall_internal. (sibcall_value): Likewise operand 3 and gen_sibcall_value_internal. (call): Likewise operand 2 and gen_call_internal. (call_value): Likewise operand 3 and gen_call_value_internal. (sibcall_internal, call_internal): Remove operand 2. (sibcall_value_internal, call_value_internal): Remove operand 3. (untyped_call): Update call to gen_call. gcc/testsuite/ * gcc.dg/rtl/x86_64/different-structs.c: Initialize CALL_INSN_ABI_ID. * selftests/x86_64/call-insn.rtl: Likewise. Diff: --- gcc/calls.cc | 3 ++ gcc/cfgcleanup.cc | 1 + gcc/config/aarch64/aarch64-protos.h | 2 +- gcc/config/aarch64/aarch64.cc | 33 ++------------ gcc/config/aarch64/aarch64.md | 5 +-- gcc/config/i386/i386.cc | 17 +------- gcc/config/riscv/riscv-sr.cc | 8 ++-- gcc/config/riscv/riscv.cc | 37 +++------------- gcc/config/riscv/riscv.md | 50 ++++++---------------- gcc/doc/rtl.texi | 22 +++++++--- gcc/doc/tm.texi | 11 ----- gcc/doc/tm.texi.in | 2 - gcc/emit-rtl.cc | 5 +++ gcc/function-abi.cc | 5 +-- gcc/recog.cc | 1 + gcc/rtl.def | 6 +-- gcc/rtl.h | 4 ++ gcc/target.def | 13 ------ .../gcc.dg/rtl/x86_64/different-structs.c | 3 +- gcc/testsuite/selftests/x86_64/call-insn.rtl | 3 +- 20 files changed, 66 insertions(+), 165 deletions(-) diff --git a/gcc/calls.cc b/gcc/calls.cc index d491a4146115..e5d67b6c97a5 100644 --- a/gcc/calls.cc +++ b/gcc/calls.cc @@ -61,6 +61,8 @@ along with GCC; see the file COPYING3. If not see #include "value-query.h" #include "tree-pretty-print.h" #include "tree-eh.h" +#include "regs.h" +#include "function-abi.h" /* Like PREFERRED_STACK_BOUNDARY but in units of bytes, not bits. */ #define STACK_BYTES (PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT) @@ -512,6 +514,7 @@ emit_call_1 (rtx funexp, tree fntree ATTRIBUTE_UNUSED, tree fndecl ATTRIBUTE_UNU cfun->calls_setjmp = 1; } + CALL_INSN_ABI_ID (call_insn) = (funtype ? fntype_abi (funtype).id () : 0); SIBLING_CALL_P (call_insn) = ((ecf_flags & ECF_SIBCALL) != 0); /* Restore this now, so that we do defer pops for this call's args diff --git a/gcc/cfgcleanup.cc b/gcc/cfgcleanup.cc index b6f04754f251..1d9ec908dab0 100644 --- a/gcc/cfgcleanup.cc +++ b/gcc/cfgcleanup.cc @@ -1204,6 +1204,7 @@ old_insns_match_p (int mode ATTRIBUTE_UNUSED, rtx_insn *i1, rtx_insn *i2) if (!rtx_equal_p (CALL_INSN_FUNCTION_USAGE (i1), CALL_INSN_FUNCTION_USAGE (i2)) + || CALL_INSN_ABI_ID (i1) != CALL_INSN_ABI_ID (i2) || SIBLING_CALL_P (i1) != SIBLING_CALL_P (i2)) return dir_none; diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h index 513b556398fa..34e770db60c0 100644 --- a/gcc/config/aarch64/aarch64-protos.h +++ b/gcc/config/aarch64/aarch64-protos.h @@ -888,7 +888,7 @@ bool aarch64_emit_approx_div (rtx, rtx, rtx); bool aarch64_emit_approx_sqrt (rtx, rtx, bool); bool aarch64_emit_opt_vec_rotate (rtx, rtx, rtx); tree aarch64_vector_load_decl (tree); -rtx aarch64_gen_callee_cookie (aarch64_isa_mode, arm_pcs, bool); +rtx aarch64_gen_callee_cookie (aarch64_isa_mode, bool); void aarch64_expand_call (rtx, rtx, rtx, bool); bool aarch64_expand_cpymem_mops (rtx *, bool); bool aarch64_expand_cpymem (rtx *, bool); diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc index 5a859e12b1a5..983cef6d6811 100644 --- a/gcc/config/aarch64/aarch64.cc +++ b/gcc/config/aarch64/aarch64.cc @@ -2841,29 +2841,15 @@ aarch64_reg_save_mode (unsigned int regno) /* Return the CONST_INT that should be placed in an UNSPEC_CALLEE_ABI rtx. This value encodes the following information: - the ISA mode on entry to a callee (ISA_MODE) - - the ABI of the callee (PCS_VARIANT) - whether the callee has an indirect_return attribute (INDIRECT_RETURN). */ rtx -aarch64_gen_callee_cookie (aarch64_isa_mode isa_mode, arm_pcs pcs_variant, - bool indirect_return) +aarch64_gen_callee_cookie (aarch64_isa_mode isa_mode, bool indirect_return) { unsigned int im = (unsigned int) isa_mode; unsigned int ir = (indirect_return ? 1 : 0) << AARCH64_NUM_ISA_MODES; - unsigned int pv = (unsigned int) pcs_variant - << (AARCH64_NUM_ABI_ATTRIBUTES + AARCH64_NUM_ISA_MODES); - return gen_int_mode (im | ir | pv, DImode); -} - -/* COOKIE is a CONST_INT from an UNSPEC_CALLEE_ABI rtx. Return the - callee's ABI. */ - -static const predefined_function_abi & -aarch64_callee_abi (rtx cookie) -{ - return function_abis[UINTVAL (cookie) - >> (AARCH64_NUM_ABI_ATTRIBUTES + AARCH64_NUM_ISA_MODES)]; + return gen_int_mode (im | ir, DImode); } /* COOKIE is a CONST_INT from an UNSPEC_CALLEE_ABI rtx. Return the @@ -2909,14 +2895,6 @@ aarch_fun_is_indirect_return (rtx_insn *insn) return aarch64_callee_indirect_return (cookie); } -/* Implement TARGET_INSN_CALLEE_ABI. */ - -const predefined_function_abi & -aarch64_insn_callee_abi (const rtx_insn *insn) -{ - return aarch64_callee_abi (aarch64_insn_callee_cookie (insn)); -} - /* INSN is a call instruction. Return the required ISA mode on entry to the callee, which is also the ISA mode on return from the callee. */ @@ -8114,7 +8092,6 @@ aarch64_function_arg (cumulative_args_t pcum_v, const function_arg_info &arg) if (arg.end_marker_p ()) { rtx abi_cookie = aarch64_gen_callee_cookie (pcum->isa_mode, - pcum->pcs_variant, pcum->indirect_return); rtx sme_mode_switch_args = aarch64_finish_sme_mode_switch_args (pcum); rtx shared_za_flags = gen_int_mode (pcum->shared_za_flags, SImode); @@ -11144,8 +11121,9 @@ aarch64_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED, auto pcs_variant = aarch64_fndecl_abi (function); bool ir = lookup_attribute ("indirect_return", TYPE_ATTRIBUTES (TREE_TYPE (function))); - rtx callee_abi = aarch64_gen_callee_cookie (isa_mode, pcs_variant, ir); + rtx callee_abi = aarch64_gen_callee_cookie (isa_mode, ir); insn = emit_call_insn (gen_sibcall (funexp, const0_rtx, callee_abi)); + CALL_INSN_ABI_ID (insn) = pcs_variant; SIBLING_CALL_P (insn) = 1; insn = get_insns (); @@ -34237,9 +34215,6 @@ aarch64_libgcc_floating_mode_supported_p #define TARGET_HARD_REGNO_CALL_PART_CLOBBERED \ aarch64_hard_regno_call_part_clobbered -#undef TARGET_INSN_CALLEE_ABI -#define TARGET_INSN_CALLEE_ABI aarch64_insn_callee_abi - #undef TARGET_CONSTANT_ALIGNMENT #define TARGET_CONSTANT_ALIGNMENT aarch64_constant_alignment diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index 6c31f7c72114..6c141df40a4b 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -8127,11 +8127,10 @@ { if (TARGET_SVE) { - rtx abi = aarch64_gen_callee_cookie (AARCH64_ISA_MODE, - aarch64_tlsdesc_abi_id (), - false); + rtx abi = aarch64_gen_callee_cookie (AARCH64_ISA_MODE, false); rtx_insn *call = emit_call_insn (gen_tlsdesc_small_sve_<mode> (operands[0], abi)); + CALL_INSN_ABI_ID (call) = aarch64_tlsdesc_abi_id (); RTL_CONST_CALL_P (call) = 1; } else diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc index e1b2cbea12bd..2945081234b3 100644 --- a/gcc/config/i386/i386.cc +++ b/gcc/config/i386/i386.cc @@ -21871,19 +21871,6 @@ ix86_hard_regno_mode_ok (unsigned int regno, machine_mode mode) return false; } -/* Implement TARGET_INSN_CALLEE_ABI. */ - -const predefined_function_abi & -ix86_insn_callee_abi (const rtx_insn *insn) -{ - unsigned int abi_id = 0; - rtx pat = PATTERN (insn); - if (vzeroupper_pattern (pat, VOIDmode)) - abi_id = ABI_VZEROUPPER; - - return function_abis[abi_id]; -} - /* Initialize function_abis with corresponding abi_id, currently only handle vzeroupper. */ void @@ -21905,6 +21892,7 @@ ix86_expand_avx_vzeroupper (void) /* Initialize vzeroupper_abi here. */ ix86_initialize_callee_abi (ABI_VZEROUPPER); rtx_insn *insn = emit_call_insn (gen_avx_vzeroupper_callee_abi ()); + CALL_INSN_ABI_ID (insn) = ABI_VZEROUPPER; /* Return false for non-local goto in can_nonlocal_goto. */ make_reg_eh_region_note (insn, 0, INT_MIN); /* Flag used for call_insn indicates it's a fake call. */ @@ -28818,9 +28806,6 @@ ix86_libgcc_floating_mode_supported_p #define TARGET_HARD_REGNO_CALL_PART_CLOBBERED \ ix86_hard_regno_call_part_clobbered -#undef TARGET_INSN_CALLEE_ABI -#define TARGET_INSN_CALLEE_ABI ix86_insn_callee_abi - #undef TARGET_CAN_CHANGE_MODE_CLASS #define TARGET_CAN_CHANGE_MODE_CLASS ix86_can_change_mode_class diff --git a/gcc/config/riscv/riscv-sr.cc b/gcc/config/riscv/riscv-sr.cc index 531ba66cbb17..e1b2dafc30b9 100644 --- a/gcc/config/riscv/riscv-sr.cc +++ b/gcc/config/riscv/riscv-sr.cc @@ -447,20 +447,18 @@ riscv_remove_unneeded_save_restore_calls (void) && !SIBCALL_REG_P (REGNO (target))) return; - riscv_cc cc = get_riscv_cc (XVECEXP (callpat, 0, 1)); rtx sibcall = NULL; if (set_target != NULL) - sibcall = gen_sibcall_value_internal (set_target, target, const0_rtx, - gen_int_mode (cc, SImode)); + sibcall = gen_sibcall_value_internal (set_target, target, const0_rtx); else - sibcall - = gen_sibcall_internal (target, const0_rtx, gen_int_mode (cc, SImode)); + sibcall = gen_sibcall_internal (target, const0_rtx); rtx_insn *before_call = PREV_INSN (call); remove_insn (call); rtx_insn *insn = emit_call_insn_after_setloc (sibcall, before_call, INSN_LOCATION (call)); REG_NOTES (insn) = REG_NOTES (call); + CALL_INSN_ABI_ID (insn) = CALL_INSN_ABI_ID (call); SIBLING_CALL_P (insn) = 1; /* Now update the prologue and epilogue to take account of the diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index 9ab4ab3cd1d9..362c66c82230 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -3251,8 +3251,8 @@ riscv_call_tls_get_addr (rtx sym, rtx result) start_sequence (); emit_insn (riscv_got_load_tls_gd (a0, sym)); - insn = emit_call_insn (gen_call_value (result, func, const0_rtx, - gen_int_mode (RISCV_CC_BASE, SImode))); + insn = emit_call_insn (gen_call_value (result, func, const0_rtx, NULL_RTX)); + CALL_INSN_ABI_ID (insn) = RISCV_CC_BASE; RTL_CONST_CALL_P (insn) = 1; use_reg (&CALL_INSN_FUNCTION_USAGE (insn), a0); insn = end_sequence (); @@ -7295,8 +7295,7 @@ riscv_function_arg (cumulative_args_t cum_v, const function_arg_info &arg) struct riscv_arg_info info; if (arg.end_marker_p ()) - /* Return the calling convention that used by the current function. */ - return gen_int_mode (cum->variant_cc, SImode); + return nullptr; return riscv_get_arg_info (&info, cum, arg.mode, arg.type, arg.named, false); } @@ -7822,30 +7821,6 @@ riscv_fntype_abi (const_tree fntype) return riscv_fntype_abi_1 (fntype, /* check_only */true); } -/* Return riscv calling convention of call_insn. */ -riscv_cc -get_riscv_cc (const rtx use) -{ - gcc_assert (GET_CODE (use) == USE); - rtx unspec = XEXP (use, 0); - gcc_assert (GET_CODE (unspec) == UNSPEC - && XINT (unspec, 1) == UNSPEC_CALLEE_CC); - riscv_cc cc = (riscv_cc) INTVAL (XVECEXP (unspec, 0, 0)); - gcc_assert (cc < RISCV_CC_UNKNOWN); - return cc; -} - -/* Implement TARGET_INSN_CALLEE_ABI. */ - -const predefined_function_abi & -riscv_insn_callee_abi (const rtx_insn *insn) -{ - rtx pat = PATTERN (insn); - gcc_assert (GET_CODE (pat) == PARALLEL); - riscv_cc cc = get_riscv_cc (XVECEXP (pat, 0, 1)); - return function_abis[cc]; -} - /* Handle an attribute requiring a FUNCTION_DECL; arguments as in struct attribute_spec.handler. */ static tree @@ -11795,8 +11770,8 @@ riscv_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED, } /* Jump to the target function. */ - rtx callee_cc = gen_int_mode (fndecl_abi (function).id (), SImode); - insn = emit_call_insn (gen_sibcall (fnaddr, const0_rtx, callee_cc)); + insn = emit_call_insn (gen_sibcall (fnaddr, const0_rtx, NULL_RTX)); + CALL_INSN_ABI_ID (insn) = fndecl_abi (function).id (); SIBLING_CALL_P (insn) = 1; /* Run just enough of rest_of_compilation. This sequence was @@ -16297,8 +16272,6 @@ riscv_memtag_tag_bitsize () #define TARGET_FUNCTION_ARG_BOUNDARY riscv_function_arg_boundary #undef TARGET_FNTYPE_ABI #define TARGET_FNTYPE_ABI riscv_fntype_abi -#undef TARGET_INSN_CALLEE_ABI -#define TARGET_INSN_CALLEE_ABI riscv_insn_callee_abi #undef TARGET_SHRINK_WRAP_GET_SEPARATE_COMPONENTS #define TARGET_SHRINK_WRAP_GET_SEPARATE_COMPONENTS \ diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md index 5f9f26ee63f4..94f81b9c29eb 100644 --- a/gcc/config/riscv/riscv.md +++ b/gcc/config/riscv/riscv.md @@ -83,9 +83,6 @@ UNSPEC_CLMULH UNSPEC_CLMULR - ;; the calling convention of callee - UNSPEC_CALLEE_CC - ;; String unspecs UNSPEC_STRLEN @@ -4145,22 +4142,17 @@ (define_expand "sibcall" [(parallel [(call (match_operand 0 "") (match_operand 1 "")) - (use (unspec:SI [ - (match_operand 2 "const_int_operand") - ] UNSPEC_CALLEE_CC))])] + (use (match_operand 2 ""))])] "" { rtx target = riscv_legitimize_call_address (XEXP (operands[0], 0)); - emit_call_insn (gen_sibcall_internal (target, operands[1], operands[2])); + emit_call_insn (gen_sibcall_internal (target, operands[1])); DONE; }) (define_insn "sibcall_internal" [(call (mem:SI (match_operand 0 "call_insn_operand" "j,S,U")) - (match_operand 1 "" "")) - (use (unspec:SI [ - (match_operand 2 "const_int_operand") - ] UNSPEC_CALLEE_CC))] + (match_operand 1 "" ""))] "SIBLING_CALL_P (insn)" "@ jr\t%0 @@ -4172,24 +4164,19 @@ [(parallel [(set (match_operand 0 "") (call (match_operand 1 "") (match_operand 2 ""))) - (use (unspec:SI [ - (match_operand 3 "const_int_operand") - ] UNSPEC_CALLEE_CC))])] + (use (match_operand 3 ""))])] "" { rtx target = riscv_legitimize_call_address (XEXP (operands[1], 0)); - emit_call_insn (gen_sibcall_value_internal (operands[0], target, operands[2], - operands[3])); + emit_call_insn (gen_sibcall_value_internal (operands[0], target, + operands[2])); DONE; }) (define_insn "sibcall_value_internal" [(set (match_operand 0 "" "") (call (mem:SI (match_operand 1 "call_insn_operand" "j,S,U")) - (match_operand 2 "" ""))) - (use (unspec:SI [ - (match_operand 3 "const_int_operand") - ] UNSPEC_CALLEE_CC))] + (match_operand 2 "" "")))] "SIBLING_CALL_P (insn)" "@ jr\t%1 @@ -4200,22 +4187,17 @@ (define_expand "call" [(parallel [(call (match_operand 0 "") (match_operand 1 "")) - (use (unspec:SI [ - (match_operand 2 "const_int_operand") - ] UNSPEC_CALLEE_CC))])] + (use (match_operand 2 ""))])] "" { rtx target = riscv_legitimize_call_address (XEXP (operands[0], 0)); - emit_call_insn (gen_call_internal (target, operands[1], operands[2])); + emit_call_insn (gen_call_internal (target, operands[1])); DONE; }) (define_insn "call_internal" [(call (mem:SI (match_operand 0 "call_insn_operand" "l,S,U")) (match_operand 1 "" "")) - (use (unspec:SI [ - (match_operand 2 "const_int_operand") - ] UNSPEC_CALLEE_CC)) (clobber (reg:SI RETURN_ADDR_REGNUM))] "" "@ @@ -4228,14 +4210,11 @@ [(parallel [(set (match_operand 0 "") (call (match_operand 1 "") (match_operand 2 ""))) - (use (unspec:SI [ - (match_operand 3 "const_int_operand") - ] UNSPEC_CALLEE_CC))])] + (use (match_operand 3 ""))])] "" { rtx target = riscv_legitimize_call_address (XEXP (operands[1], 0)); - emit_call_insn (gen_call_value_internal (operands[0], target, operands[2], - operands[3])); + emit_call_insn (gen_call_value_internal (operands[0], target, operands[2])); DONE; }) @@ -4243,9 +4222,6 @@ [(set (match_operand 0 "" "") (call (mem:SI (match_operand 1 "call_insn_operand" "l,S,U")) (match_operand 2 "" ""))) - (use (unspec:SI [ - (match_operand 3 "const_int_operand") - ] UNSPEC_CALLEE_CC)) (clobber (reg:SI RETURN_ADDR_REGNUM))] "" "@ @@ -4265,9 +4241,7 @@ { int i; - /* Untyped calls always use the RISCV_CC_BASE calling convention. */ - emit_call_insn (gen_call (operands[0], const0_rtx, - gen_int_mode (RISCV_CC_BASE, SImode))); + emit_call_insn (gen_call (operands[0], const0_rtx, NULL)); for (i = 0; i < XVECLEN (operands[2], 0); i++) { diff --git a/gcc/doc/rtl.texi b/gcc/doc/rtl.texi index 082cb39372bc..f79571ac6cfa 100644 --- a/gcc/doc/rtl.texi +++ b/gcc/doc/rtl.texi @@ -3800,13 +3800,16 @@ function calls. It is important to distinguish these instructions because they imply that certain registers and memory locations may be altered unpredictably. -@findex CALL_INSN_FUNCTION_USAGE @code{call_insn} insns have the same extra fields as @code{insn} insns, -accessed in the same way and in addition contain a field -@code{CALL_INSN_FUNCTION_USAGE}, which contains a list (chain of -@code{expr_list} expressions) containing @code{use}, @code{clobber} and -sometimes @code{set} expressions that denote hard registers and -@code{mem}s used or clobbered by the called function. +accessed in the same way. They have two further fields: + +@table @code +@findex CALL_INSN_FUNCTION_USAGE +@item CALL_INSN_FUNCTION_USAGE +This field contains a list (chain of @code{expr_list} expressions) +containing @code{use}, @code{clobber} and sometimes @code{set} +expressions that denote hard registers and @code{mem}s used or +clobbered by the called function. A @code{mem} generally points to a stack slot in which arguments passed to the libcall by reference (@pxref{Register Arguments, @@ -3825,6 +3828,13 @@ that the function returns one of its arguments. Such a @code{set} may look like a no-op if the same register holds the argument and the return value. +@findex CALL_INSN_ABI_ID +@item CALL_INSN_ABI_ID +This field identifies the callee's calling convention, as an index in +the range [0, @code{NUM_ABI_IDS} - 1]. See @file{function-abi.h} for +more details about the representation of these calling conventions. +@end table + @findex code_label @findex CODE_LABEL_NUMBER @item code_label diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 1fbf43c6c577..d1e5d1b79521 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -2020,17 +2020,6 @@ descriptor. Targets only need to define this hook if they support interoperability between several ABIs in the same translation unit. @end deftypefn -@deftypefn {Target Hook} {const predefined_function_abi &} TARGET_INSN_CALLEE_ABI (const rtx_insn *@var{insn}) -This hook returns a description of the ABI used by the target of -call instruction @var{insn}; see the definition of -@code{predefined_function_abi} for details of the ABI descriptor. -Only the global function @code{insn_callee_abi} should call this hook -directly. - -Targets only need to define this hook if they support -interoperability between several ABIs in the same translation unit. -@end deftypefn - @cindex call-used register @cindex call-clobbered register @cindex call-saved register diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in index 6ecbeda09ca9..6c9c4658b9d9 100644 --- a/gcc/doc/tm.texi.in +++ b/gcc/doc/tm.texi.in @@ -1743,8 +1743,6 @@ must be defined. Modern ports should define @code{CALL_REALLY_USED_REGISTERS}. @cindex call-saved register @hook TARGET_FNTYPE_ABI -@hook TARGET_INSN_CALLEE_ABI - @cindex call-used register @cindex call-clobbered register @cindex call-saved register diff --git a/gcc/emit-rtl.cc b/gcc/emit-rtl.cc index 7f5d267341ac..4a23eaefe024 100644 --- a/gcc/emit-rtl.cc +++ b/gcc/emit-rtl.cc @@ -4036,6 +4036,9 @@ try_split (rtx pat, rtx_insn *trial, int last) p = &XEXP (*p, 1); *p = CALL_INSN_FUNCTION_USAGE (trial); + /* Preserve the ABI information from the original call. */ + CALL_INSN_ABI_ID (insn) = CALL_INSN_ABI_ID (trial); + /* If the old call was a sibling call, the new one must be too. */ SIBLING_CALL_P (insn) = SIBLING_CALL_P (trial); @@ -4225,6 +4228,7 @@ make_call_insn_raw (rtx pattern) INSN_CODE (insn) = -1; REG_NOTES (insn) = NULL; CALL_INSN_FUNCTION_USAGE (insn) = NULL; + CALL_INSN_ABI_ID (insn) = 0; INSN_LOCATION (insn) = curr_insn_location (); BLOCK_FOR_INSN (insn) = NULL; @@ -6626,6 +6630,7 @@ emit_copy_of_insn_after (rtx_insn *insn, rtx_insn *after) if (CALL_INSN_FUNCTION_USAGE (insn)) CALL_INSN_FUNCTION_USAGE (new_rtx) = copy_insn (CALL_INSN_FUNCTION_USAGE (insn)); + CALL_INSN_ABI_ID (new_rtx) = CALL_INSN_ABI_ID (insn); SIBLING_CALL_P (new_rtx) = SIBLING_CALL_P (insn); RTL_CONST_CALL_P (new_rtx) = RTL_CONST_CALL_P (insn); RTL_PURE_CALL_P (new_rtx) = RTL_PURE_CALL_P (insn); diff --git a/gcc/function-abi.cc b/gcc/function-abi.cc index 53a76dc2341d..277863ecee3c 100644 --- a/gcc/function-abi.cc +++ b/gcc/function-abi.cc @@ -227,10 +227,7 @@ insn_callee_abi (const rtx_insn *insn) if (tree fndecl = get_call_fndecl (insn)) return fndecl_abi (fndecl); - if (targetm.calls.insn_callee_abi) - return targetm.calls.insn_callee_abi (insn); - - return default_function_abi; + return function_abis[CALL_INSN_ABI_ID (insn)]; } /* Return the ABI of the function called by CALL_EXPR EXP. Return the diff --git a/gcc/recog.cc b/gcc/recog.cc index 4cae276f1f70..a45a37db6bb9 100644 --- a/gcc/recog.cc +++ b/gcc/recog.cc @@ -4034,6 +4034,7 @@ peep2_attempt (basic_block bb, rtx_insn *insn, int match_len, rtx_insn *attempt) CALL_INSN_FUNCTION_USAGE (new_insn) = CALL_INSN_FUNCTION_USAGE (old_insn); + CALL_INSN_ABI_ID (new_insn) = CALL_INSN_ABI_ID (old_insn); SIBLING_CALL_P (new_insn) = SIBLING_CALL_P (old_insn); for (note = REG_NOTES (old_insn); diff --git a/gcc/rtl.def b/gcc/rtl.def index c88b4565b3e9..e83d6554c808 100644 --- a/gcc/rtl.def +++ b/gcc/rtl.def @@ -151,9 +151,9 @@ DEF_RTL_EXPR(JUMP_INSN, "jump_insn", "uuBeLie0", RTX_INSN) /* An instruction that can possibly call a subroutine but which will not change which instruction comes next in the current function. - Field ( rtx->u.fld[8] ) is CALL_INSN_FUNCTION_USAGE. - All other fields ( rtx->u.fld[] ) have exact same meaning as INSN's. */ -DEF_RTL_EXPR(CALL_INSN, "call_insn", "uuBeLiee", RTX_INSN) + Field 7 is CALL_INSN_FUNCTION_USAGE and field 8 is CALL_INSN_ABI_ID. + All other fields ( rtx->u.fld[] ) have the same meaning as for INSNs. */ +DEF_RTL_EXPR(CALL_INSN, "call_insn", "uuBeLieei", RTX_INSN) /* Placeholder for tablejump JUMP_INSNs. The pattern of this kind of rtx is always either an ADDR_VEC or an ADDR_DIFF_VEC. These diff --git a/gcc/rtl.h b/gcc/rtl.h index 93315cb58022..747d917ecf2e 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -1669,6 +1669,10 @@ extern const char * const reg_note_name[]; Pseudo registers cannot be mentioned in this list. */ #define CALL_INSN_FUNCTION_USAGE(INSN) XEXP(INSN, 7) +/* Specifies the callee's ABI as an index in the range [0, NUM_ABI_IDS - 1]. + See function-abi.h for more details. */ +#define CALL_INSN_ABI_ID(INSN) XCINT(INSN, 8, CALL_INSN) + /* The label-number of a code-label. The assembler label is made from `L' and the label-number printed in decimal. Label numbers are unique in a compilation. */ diff --git a/gcc/target.def b/gcc/target.def index 25a94559e198..6ade66716a3b 100644 --- a/gcc/target.def +++ b/gcc/target.def @@ -5486,19 +5486,6 @@ interoperability between several ABIs in the same translation unit.", const predefined_function_abi &, (const_tree type), NULL) -DEFHOOK -(insn_callee_abi, - "This hook returns a description of the ABI used by the target of\n\ -call instruction @var{insn}; see the definition of\n\ -@code{predefined_function_abi} for details of the ABI descriptor.\n\ -Only the global function @code{insn_callee_abi} should call this hook\n\ -directly.\n\ -\n\ -Targets only need to define this hook if they support\n\ -interoperability between several ABIs in the same translation unit.", - const predefined_function_abi &, (const rtx_insn *insn), - NULL) - /* ??? Documenting this hook requires a GFDL license grant. */ DEFHOOK_UNDOC (internal_arg_pointer, diff --git a/gcc/testsuite/gcc.dg/rtl/x86_64/different-structs.c b/gcc/testsuite/gcc.dg/rtl/x86_64/different-structs.c index f9d1555b0c8a..ac36546331fa 100644 --- a/gcc/testsuite/gcc.dg/rtl/x86_64/different-structs.c +++ b/gcc/testsuite/gcc.dg/rtl/x86_64/different-structs.c @@ -66,7 +66,8 @@ double __RTL test (struct foo *f, const struct bar *b) (const_int 0))) "../../src/gcc/testsuite/gcc.dg/rtl/x86_64/different-structs.c":23 (expr_list:REG_CALL_DECL (symbol_ref:DI ("sqrt") [flags 0x41] <function_decl 0x7fa24e331d00 sqrt>) (expr_list:REG_EH_REGION (const_int 0))) - (expr_list:DF (use (reg:DF xmm0)))) + (expr_list:DF (use (reg:DF xmm0))) + 0) (edge-to exit (flags "ABNORMAL | SIBCALL")) ) ;; block 2 (cbarrier 18) diff --git a/gcc/testsuite/selftests/x86_64/call-insn.rtl b/gcc/testsuite/selftests/x86_64/call-insn.rtl index 8f3a78126879..5423705bb188 100644 --- a/gcc/testsuite/selftests/x86_64/call-insn.rtl +++ b/gcc/testsuite/selftests/x86_64/call-insn.rtl @@ -10,7 +10,8 @@ (expr_list:REG_EH_REGION (const_int 0) (nil))) (expr_list:DF (use (reg:DF xmm0)) - (nil))) + (nil)) + 0) (edge-to exit (flags "FALLTHRU")) ) ;; block 2 ) ;; insn-chain
