Richard Sandiford <[email protected]> writes:
> 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/.
>
> Tested on aarch64-linux-gnu, powerpc64le-linux-gnu and
> x86_64-linux-gnu. I've cc:ed the RISC-V CI to get testing there.
> OK to install if that testing passes?
FWIW, the RISC-V CI testing passed, except for a long line in the
riscv.md call to gen_sibcall_value_internal, which I've fixed in my
local copy.
Thanks,
Richard
>
> Richard
>
>
> 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.
> ---
> 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 | 49 +++++--------------
> 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, 65 insertions(+), 165 deletions(-)
>
> diff --git a/gcc/calls.cc b/gcc/calls.cc
> index d491a414611..e5d67b6c97a 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 b6f04754f25..1d9ec908dab 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 8d201821e93..89b7752bdce 100644
> --- a/gcc/config/aarch64/aarch64-protos.h
> +++ b/gcc/config/aarch64/aarch64-protos.h
> @@ -887,7 +887,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 cd5ed154c7a..ab6f5ebbf97 100644
> --- a/gcc/config/aarch64/aarch64.cc
> +++ b/gcc/config/aarch64/aarch64.cc
> @@ -2826,29 +2826,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
> @@ -2894,14 +2880,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. */
>
> @@ -8103,7 +8081,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);
> @@ -11133,8 +11110,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 ();
> @@ -33981,9 +33959,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 0ef01e889a6..5a1d756af70 100644
> --- a/gcc/config/aarch64/aarch64.md
> +++ b/gcc/config/aarch64/aarch64.md
> @@ -8119,11 +8119,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 9aecd51119f..7a90196aaeb 100644
> --- a/gcc/config/i386/i386.cc
> +++ b/gcc/config/i386/i386.cc
> @@ -21847,19 +21847,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
> @@ -21881,6 +21868,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. */
> @@ -28779,9 +28767,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 d7fb3c274eb..90f9278fa88 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 681b816d248..0a4f934d9dd 100644
> --- a/gcc/config/riscv/riscv.cc
> +++ b/gcc/config/riscv/riscv.cc
> @@ -3105,8 +3105,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 ();
> @@ -7073,8 +7073,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);
> }
> @@ -7600,30 +7599,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
> @@ -11571,8 +11546,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
> @@ -16102,8 +16077,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 869061e18ae..2d1d10dd6eb 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
>
> @@ -4100,22 +4097,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
> @@ -4127,24 +4119,18 @@
> [(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
> @@ -4155,22 +4141,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))]
> ""
> "@
> @@ -4183,14 +4164,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;
> })
>
> @@ -4198,9 +4176,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))]
> ""
> "@
> @@ -4220,9 +4195,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 4fa4d27506c..dd90a6e58f1 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 a4ae17decb0..e4143c1337f 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 1acda0c264c..4cb2becc4d4 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 e41ec2283b8..ade5ea09c9e 100644
> --- a/gcc/emit-rtl.cc
> +++ b/gcc/emit-rtl.cc
> @@ -4037,6 +4037,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);
> @@ -4226,6 +4229,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;
>
> @@ -6627,6 +6631,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 df1d2e5765b..70304597e2a 100644
> --- a/gcc/function-abi.cc
> +++ b/gcc/function-abi.cc
> @@ -224,10 +224,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 4cae276f1f7..a45a37db6bb 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 ad98fd59172..d5aee14b9f2 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 d60587dc5ce..d6824e5cbb6 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 cdb3a6a6c84..d2f7279f7d2 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 f9d1555b0c8..ac36546331f 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 8f3a7812687..5423705bb18 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