[AArch64] Make call insns record the callee's arm_pcs
authorRichard Sandiford <richard.sandiford@arm.com>
Tue, 1 Oct 2019 08:53:54 +0000 (08:53 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Tue, 1 Oct 2019 08:53:54 +0000 (08:53 +0000)
At the moment we rely on SYMBOL_REF_DECL to get the ABI of the callee
of a call insn, falling back to the default ABI if the decl isn't
available.  I think it'd be cleaner to attach the ABI directly to the
call instruction instead, which would also have the very minor benefit
of handling indirect calls more efficiently.

2019-10-01  Richard Sandiford  <richard.sandiford@arm.com>

gcc/
* config/aarch64/aarch64-protos.h (aarch64_expand_call): Take an
extra callee_abi argument.
* config/aarch64/aarch64.c (aarch64_expand_call): Likewise.
Insert a CALLEE_ABI unspec into the call pattern as the second
element in the PARALLEL.
(aarch64_simd_call_p): Delete.
(aarch64_insn_callee_abi): Get the arm_pcs of the callee from
the new CALLEE_ABI element of the PARALLEL.
(aarch64_init_cumulative_args): Get the arm_pcs of the callee
from the function type, if given.
(aarch64_function_arg_advance): Handle ARM_PCS_SIMD.
(aarch64_function_arg): Likewise.  Return the arm_pcs of the callee
when passed the function_arg_info end marker.
(aarch64_output_mi_thunk): Pass the arm_pcs of the callee as the
final argument of gen_sibcall.
* config/aarch64/aarch64.md (UNSPEC_CALLEE_ABI): New unspec.
(call): Make operand 2 a const_int_operand and pass it to expand_call.
Wrap it in an UNSPEC_CALLEE_ABI unspec for the dummy define_expand
pattern.
(call_value): Likewise operand 3.
(sibcall): Likewise operand 2.  Place the unspec before rather than
after the return.
(sibcall_value): Likewise operand 3.
(*call_insn, *call_value_insn): Include an UNSPEC_CALLEE_ABI.
(tlsgd_small_<mode>, *tlsgd_small_<mode>): Likewise.
(*sibcall_insn, *sibcall_value_insn): Likewise.  Remove empty
constraint strings.
(untyped_call): Pass const0_rtx as the callee ABI to gen_call.

gcc/testsuite/
* gcc.target/aarch64/torture/simd-abi-10.c: New test.
* gcc.target/aarch64/torture/simd-abi-11.c: Likewise.

From-SVN: r276391

gcc/ChangeLog
gcc/config/aarch64/aarch64-protos.h
gcc/config/aarch64/aarch64.c
gcc/config/aarch64/aarch64.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/aarch64/torture/simd-abi-10.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/torture/simd-abi-11.c [new file with mode: 0644]

index aa44ccd6390902cda087097549b96c2821f1dce2..cfe5f841922a8aa215d55d76375ac5dd6453cc36 100644 (file)
@@ -1,3 +1,34 @@
+2019-10-01  Richard Sandiford  <richard.sandiford@arm.com>
+
+       * config/aarch64/aarch64-protos.h (aarch64_expand_call): Take an
+       extra callee_abi argument.
+       * config/aarch64/aarch64.c (aarch64_expand_call): Likewise.
+       Insert a CALLEE_ABI unspec into the call pattern as the second
+       element in the PARALLEL.
+       (aarch64_simd_call_p): Delete.
+       (aarch64_insn_callee_abi): Get the arm_pcs of the callee from
+       the new CALLEE_ABI element of the PARALLEL.
+       (aarch64_init_cumulative_args): Get the arm_pcs of the callee
+       from the function type, if given.
+       (aarch64_function_arg_advance): Handle ARM_PCS_SIMD.
+       (aarch64_function_arg): Likewise.  Return the arm_pcs of the callee
+       when passed the function_arg_info end marker.
+       (aarch64_output_mi_thunk): Pass the arm_pcs of the callee as the
+       final argument of gen_sibcall.
+       * config/aarch64/aarch64.md (UNSPEC_CALLEE_ABI): New unspec.
+       (call): Make operand 2 a const_int_operand and pass it to expand_call.
+       Wrap it in an UNSPEC_CALLEE_ABI unspec for the dummy define_expand
+       pattern.
+       (call_value): Likewise operand 3.
+       (sibcall): Likewise operand 2.  Place the unspec before rather than
+       after the return.
+       (sibcall_value): Likewise operand 3.
+       (*call_insn, *call_value_insn): Include an UNSPEC_CALLEE_ABI.
+       (tlsgd_small_<mode>, *tlsgd_small_<mode>): Likewise.
+       (*sibcall_insn, *sibcall_value_insn): Likewise.  Remove empty
+       constraint strings.
+       (untyped_call): Pass const0_rtx as the callee ABI to gen_call.
+
 2019-10-01  Richard Sandiford  <richard.sandiford@arm.com>
 
        * regs.h (HARD_REGNO_CALLER_SAVE_MODE): Update call to
index c9a342304b602a17877a5a4248463864067c89d3..919f2b1fd283b05b9cc5a46ac7edab2582bf2296 100644 (file)
@@ -468,7 +468,7 @@ bool aarch64_const_vec_all_same_in_range_p (rtx, HOST_WIDE_INT,
 bool aarch64_constant_address_p (rtx);
 bool aarch64_emit_approx_div (rtx, rtx, rtx);
 bool aarch64_emit_approx_sqrt (rtx, rtx, bool);
-void aarch64_expand_call (rtx, rtx, bool);
+void aarch64_expand_call (rtx, rtx, rtx, bool);
 bool aarch64_expand_cpymem (rtx *);
 bool aarch64_float_const_zero_rtx_p (rtx);
 bool aarch64_float_const_rtx_p (rtx);
index ec180c8bd4f850b101b08d96efedb2c5e53b1f93..85c87bb626b21d1c10b5d76ce5a6e8f9ebdacd14 100644 (file)
@@ -1872,37 +1872,17 @@ aarch64_reg_save_mode (tree fndecl, unsigned regno)
           : (aarch64_simd_decl_p (fndecl) ? E_TFmode : E_DFmode);
 }
 
-/* Return true if the instruction is a call to a SIMD function, false
-   if it is not a SIMD function or if we do not know anything about
-   the function.  */
-
-static bool
-aarch64_simd_call_p (const rtx_insn *insn)
-{
-  rtx symbol;
-  rtx call;
-  tree fndecl;
-
-  gcc_assert (CALL_P (insn));
-  call = get_call_rtx_from (insn);
-  symbol = XEXP (XEXP (call, 0), 0);
-  if (GET_CODE (symbol) != SYMBOL_REF)
-    return false;
-  fndecl = SYMBOL_REF_DECL (symbol);
-  if (!fndecl)
-    return false;
-
-  return aarch64_simd_decl_p (fndecl);
-}
-
 /* Implement TARGET_INSN_CALLEE_ABI.  */
 
 const predefined_function_abi &
 aarch64_insn_callee_abi (const rtx_insn *insn)
 {
-  if (aarch64_simd_call_p (insn))
-    return aarch64_simd_abi ();
-  return default_function_abi;
+  rtx pat = PATTERN (insn);
+  gcc_assert (GET_CODE (pat) == PARALLEL);
+  rtx unspec = XVECEXP (pat, 0, 1);
+  gcc_assert (GET_CODE (unspec) == UNSPEC
+             && XINT (unspec, 1) == UNSPEC_CALLEE_ABI);
+  return function_abis[INTVAL (XVECEXP (unspec, 0, 0))];
 }
 
 /* Implement TARGET_HARD_REGNO_CALL_PART_CLOBBERED.  The callee only saves
@@ -4847,10 +4827,11 @@ static rtx
 aarch64_function_arg (cumulative_args_t pcum_v, const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *pcum = get_cumulative_args (pcum_v);
-  gcc_assert (pcum->pcs_variant == ARM_PCS_AAPCS64);
+  gcc_assert (pcum->pcs_variant == ARM_PCS_AAPCS64
+             || pcum->pcs_variant == ARM_PCS_SIMD);
 
   if (arg.end_marker_p ())
-    return NULL_RTX;
+    return gen_int_mode (pcum->pcs_variant, DImode);
 
   aarch64_layout_arg (pcum_v, arg.mode, arg.type, arg.named);
   return pcum->aapcs_reg;
@@ -4858,16 +4839,19 @@ aarch64_function_arg (cumulative_args_t pcum_v, const function_arg_info &arg)
 
 void
 aarch64_init_cumulative_args (CUMULATIVE_ARGS *pcum,
-                          const_tree fntype ATTRIBUTE_UNUSED,
-                          rtx libname ATTRIBUTE_UNUSED,
-                          const_tree fndecl ATTRIBUTE_UNUSED,
-                          unsigned n_named ATTRIBUTE_UNUSED)
+                             const_tree fntype,
+                             rtx libname ATTRIBUTE_UNUSED,
+                             const_tree fndecl ATTRIBUTE_UNUSED,
+                             unsigned n_named ATTRIBUTE_UNUSED)
 {
   pcum->aapcs_ncrn = 0;
   pcum->aapcs_nvrn = 0;
   pcum->aapcs_nextncrn = 0;
   pcum->aapcs_nextnvrn = 0;
-  pcum->pcs_variant = ARM_PCS_AAPCS64;
+  if (fntype)
+    pcum->pcs_variant = (arm_pcs) fntype_abi (fntype).id ();
+  else
+    pcum->pcs_variant = ARM_PCS_AAPCS64;
   pcum->aapcs_reg = NULL_RTX;
   pcum->aapcs_arg_processed = false;
   pcum->aapcs_stack_words = 0;
@@ -4892,7 +4876,8 @@ aarch64_function_arg_advance (cumulative_args_t pcum_v,
                              const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *pcum = get_cumulative_args (pcum_v);
-  if (pcum->pcs_variant == ARM_PCS_AAPCS64)
+  if (pcum->pcs_variant == ARM_PCS_AAPCS64
+      || pcum->pcs_variant == ARM_PCS_SIMD)
     {
       aarch64_layout_arg (pcum_v, arg.mode, arg.type, arg.named);
       gcc_assert ((pcum->aapcs_reg != NULL_RTX)
@@ -6921,7 +6906,8 @@ aarch64_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
     }
   funexp = XEXP (DECL_RTL (function), 0);
   funexp = gen_rtx_MEM (FUNCTION_MODE, funexp);
-  insn = emit_call_insn (gen_sibcall (funexp, const0_rtx, NULL_RTX));
+  rtx callee_abi = gen_int_mode (fndecl_abi (function).id (), DImode);
+  insn = emit_call_insn (gen_sibcall (funexp, const0_rtx, callee_abi));
   SIBLING_CALL_P (insn) = 1;
 
   insn = get_insns ();
@@ -7999,11 +7985,12 @@ aarch64_fixed_condition_code_regs (unsigned int *p1, unsigned int *p2)
    RESULT is the register in which the result is returned.  It's NULL for
    "call" and "sibcall".
    MEM is the location of the function call.
+   CALLEE_ABI is a const_int that gives the arm_pcs of the callee.
    SIBCALL indicates whether this function call is normal call or sibling call.
    It will generate different pattern accordingly.  */
 
 void
-aarch64_expand_call (rtx result, rtx mem, bool sibcall)
+aarch64_expand_call (rtx result, rtx mem, rtx callee_abi, bool sibcall)
 {
   rtx call, callee, tmp;
   rtvec vec;
@@ -8033,7 +8020,11 @@ aarch64_expand_call (rtx result, rtx mem, bool sibcall)
   else
     tmp = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, LR_REGNUM));
 
-  vec = gen_rtvec (2, call, tmp);
+  gcc_assert (CONST_INT_P (callee_abi));
+  callee_abi = gen_rtx_UNSPEC (DImode, gen_rtvec (1, callee_abi),
+                              UNSPEC_CALLEE_ABI);
+
+  vec = gen_rtvec (3, call, callee_abi, tmp);
   call = gen_rtx_PARALLEL (VOIDmode, vec);
 
   aarch64_emit_call_insn (call);
index fcba5ace8673667f8dadb29ff14c60957fe0a75f..e483572820ccb3680846247b04319d5922114c4c 100644 (file)
     UNSPEC_AUTIB1716
     UNSPEC_AUTIASP
     UNSPEC_AUTIBSP
+    UNSPEC_CALLEE_ABI
     UNSPEC_CASESI
     UNSPEC_CRC32B
     UNSPEC_CRC32CB
 ;; -------------------------------------------------------------------
 
 (define_expand "call"
-  [(parallel [(call (match_operand 0 "memory_operand")
-                   (match_operand 1 "general_operand"))
-             (use (match_operand 2 "" ""))
-             (clobber (reg:DI LR_REGNUM))])]
+  [(parallel
+     [(call (match_operand 0 "memory_operand")
+           (match_operand 1 "general_operand"))
+      (unspec:DI [(match_operand 2 "const_int_operand")] UNSPEC_CALLEE_ABI)
+      (clobber (reg:DI LR_REGNUM))])]
   ""
   "
   {
-    aarch64_expand_call (NULL_RTX, operands[0], false);
+    aarch64_expand_call (NULL_RTX, operands[0], operands[2], false);
     DONE;
   }"
 )
 (define_insn "*call_insn"
   [(call (mem:DI (match_operand:DI 0 "aarch64_call_insn_operand" "r, Usf"))
         (match_operand 1 "" ""))
+   (unspec:DI [(match_operand:DI 2 "const_int_operand")] UNSPEC_CALLEE_ABI)
    (clobber (reg:DI LR_REGNUM))]
   ""
   "@
 )
 
 (define_expand "call_value"
-  [(parallel [(set (match_operand 0 "" "")
-                  (call (match_operand 1 "memory_operand")
-                        (match_operand 2 "general_operand")))
-             (use (match_operand 3 "" ""))
-             (clobber (reg:DI LR_REGNUM))])]
+  [(parallel
+     [(set (match_operand 0 "")
+          (call (match_operand 1 "memory_operand")
+                (match_operand 2 "general_operand")))
+     (unspec:DI [(match_operand 3 "const_int_operand")] UNSPEC_CALLEE_ABI)
+     (clobber (reg:DI LR_REGNUM))])]
   ""
   "
   {
-    aarch64_expand_call (operands[0], operands[1], false);
+    aarch64_expand_call (operands[0], operands[1], operands[3], false);
     DONE;
   }"
 )
   [(set (match_operand 0 "" "")
        (call (mem:DI (match_operand:DI 1 "aarch64_call_insn_operand" "r, Usf"))
                      (match_operand 2 "" "")))
+   (unspec:DI [(match_operand:DI 3 "const_int_operand")] UNSPEC_CALLEE_ABI)
    (clobber (reg:DI LR_REGNUM))]
   ""
   "@
 )
 
 (define_expand "sibcall"
-  [(parallel [(call (match_operand 0 "memory_operand")
-                   (match_operand 1 "general_operand"))
-             (return)
-             (use (match_operand 2 "" ""))])]
+  [(parallel
+     [(call (match_operand 0 "memory_operand")
+           (match_operand 1 "general_operand"))
+      (unspec:DI [(match_operand 2 "const_int_operand")] UNSPEC_CALLEE_ABI)
+      (return)])]
   ""
   {
-    aarch64_expand_call (NULL_RTX, operands[0], true);
+    aarch64_expand_call (NULL_RTX, operands[0], operands[2], true);
     DONE;
   }
 )
 
 (define_expand "sibcall_value"
-  [(parallel [(set (match_operand 0 "" "")
-                  (call (match_operand 1 "memory_operand")
-                        (match_operand 2 "general_operand")))
-             (return)
-             (use (match_operand 3 "" ""))])]
+  [(parallel
+     [(set (match_operand 0 "")
+          (call (match_operand 1 "memory_operand")
+                (match_operand 2 "general_operand")))
+      (unspec:DI [(match_operand 3 "const_int_operand")] UNSPEC_CALLEE_ABI)
+      (return)])]
   ""
   {
-    aarch64_expand_call (operands[0], operands[1], true);
+    aarch64_expand_call (operands[0], operands[1], operands[3], true);
     DONE;
   }
 )
 
 (define_insn "*sibcall_insn"
   [(call (mem:DI (match_operand:DI 0 "aarch64_call_insn_operand" "Ucs, Usf"))
-        (match_operand 1 "" ""))
+        (match_operand 1 ""))
+   (unspec:DI [(match_operand:DI 2 "const_int_operand")] UNSPEC_CALLEE_ABI)
    (return)]
   "SIBLING_CALL_P (insn)"
   "@
 )
 
 (define_insn "*sibcall_value_insn"
-  [(set (match_operand 0 "" "")
+  [(set (match_operand 0 "")
        (call (mem:DI
                (match_operand:DI 1 "aarch64_call_insn_operand" "Ucs, Usf"))
-             (match_operand 2 "" "")))
+             (match_operand 2 "")))
+   (unspec:DI [(match_operand:DI 3 "const_int_operand")] UNSPEC_CALLEE_ABI)
    (return)]
   "SIBLING_CALL_P (insn)"
   "@
 {
   int i;
 
-  emit_call_insn (gen_call (operands[0], const0_rtx, NULL));
+  /* Untyped calls always use the default ABI.  It's only possible to use
+     ABI variants if we know the type of the target function.  */
+  emit_call_insn (gen_call (operands[0], const0_rtx, const0_rtx));
 
   for (i = 0; i < XVECLEN (operands[2], 0); i++)
     {
 (define_expand "tlsgd_small_<mode>"
  [(parallel [(set (match_operand 0 "register_operand")
                   (call (mem:DI (match_dup 2)) (const_int 1)))
+            (unspec:DI [(const_int 0)] UNSPEC_CALLEE_ABI)
             (unspec:DI [(match_operand:PTR 1 "aarch64_valid_symref")] UNSPEC_GOTSMALLTLS)
             (clobber (reg:DI LR_REGNUM))])]
  ""
 (define_insn "*tlsgd_small_<mode>"
   [(set (match_operand 0 "register_operand" "")
        (call (mem:DI (match_operand:DI 2 "" "")) (const_int 1)))
+   (unspec:DI [(const_int 0)] UNSPEC_CALLEE_ABI)
    (unspec:DI [(match_operand:PTR 1 "aarch64_valid_symref" "S")] UNSPEC_GOTSMALLTLS)
    (clobber (reg:DI LR_REGNUM))
   ]
index cc31ac8cd5fc2098b7593de666e8ccbb32192bd2..2bf37cbbebdb48281517b853186fb7bb42b88457 100644 (file)
@@ -1,3 +1,8 @@
+2019-10-01  Richard Sandiford  <richard.sandiford@arm.com>
+
+       * gcc.target/aarch64/torture/simd-abi-10.c: New test.
+       * gcc.target/aarch64/torture/simd-abi-11.c: Likewise.
+
 2019-09-30  Yuliang Wang  <yuliang.wang@arm.com>
 
        * gcc.dg/vect/vect-sdiv-pow2-1.c: New test.
diff --git a/gcc/testsuite/gcc.target/aarch64/torture/simd-abi-10.c b/gcc/testsuite/gcc.target/aarch64/torture/simd-abi-10.c
new file mode 100644 (file)
index 0000000..3d6893e
--- /dev/null
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+
+int __attribute__((aarch64_vector_pcs)) (*callee) (void);
+
+int __attribute__ ((aarch64_vector_pcs))
+caller (int *x)
+{
+  return callee () + 1;
+}
+
+/* { dg-final { scan-assembler-not {\tstp\tq} } } */
+/* { dg-final { scan-assembler-not {\tldp\tq} } } */
+/* { dg-final { scan-assembler-not {\tstr\tq} } } */
+/* { dg-final { scan-assembler-not {\tldr\tq} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/torture/simd-abi-11.c b/gcc/testsuite/gcc.target/aarch64/torture/simd-abi-11.c
new file mode 100644 (file)
index 0000000..de99bd7
--- /dev/null
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+
+int (*callee) (void);
+
+int __attribute__ ((aarch64_vector_pcs))
+caller (int *x)
+{
+  return callee () + 1;
+}
+
+/* { dg-final { scan-assembler {\sstp\tq8, q9} } } */
+/* { dg-final { scan-assembler {\sstp\tq10, q11} } } */
+/* { dg-final { scan-assembler {\sstp\tq12, q13} } } */
+/* { dg-final { scan-assembler {\sstp\tq14, q15} } } */
+/* { dg-final { scan-assembler {\sstp\tq16, q17} } } */
+/* { dg-final { scan-assembler {\sstp\tq18, q19} } } */
+/* { dg-final { scan-assembler {\sstp\tq20, q21} } } */
+/* { dg-final { scan-assembler {\sstp\tq22, q23} } } */
+/* { dg-final { scan-assembler {\sldp\tq8, q9} } } */
+/* { dg-final { scan-assembler {\sldp\tq10, q11} } } */
+/* { dg-final { scan-assembler {\sldp\tq12, q13} } } */
+/* { dg-final { scan-assembler {\sldp\tq14, q15} } } */
+/* { dg-final { scan-assembler {\sldp\tq16, q17} } } */
+/* { dg-final { scan-assembler {\sldp\tq18, q19} } } */
+/* { dg-final { scan-assembler {\sldp\tq20, q21} } } */
+/* { dg-final { scan-assembler {\sldp\tq22, q23} } } */