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?

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
-- 
2.54.0

Reply via email to