Commit fee9ba42 by Jiong Wang Committed by Marcus Shawcroft

[AARCH64] Support tail indirect function call.

From-SVN: r210861
parent 09af4b4c
2014-05-23 Jiong Wang <jiong.wang@arm.com>
* config/aarch64/predicates.md (aarch64_call_insn_operand): New
predicate.
* config/aarch64/constraints.md ("Ucs", "Usf"): New constraints.
* config/aarch64/aarch64.md (*sibcall_insn, *sibcall_value_insn):
Adjust for tailcalling through registers.
* config/aarch64/aarch64.h (enum reg_class): New caller save
register class.
(REG_CLASS_NAMES): Likewise.
(REG_CLASS_CONTENTS): Likewise.
* config/aarch64/aarch64.c (aarch64_function_ok_for_sibcall):
Allow tailcalling without decls.
2014-05-23 Thomas Schwinge <thomas@codesourcery.com> 2014-05-23 Thomas Schwinge <thomas@codesourcery.com>
* gimplify.c (omp_notice_variable) <case OMP_CLAUSE_DEFAULT_NONE>: * gimplify.c (omp_notice_variable) <case OMP_CLAUSE_DEFAULT_NONE>:
......
...@@ -1268,18 +1268,10 @@ aarch64_expand_mov_immediate (rtx dest, rtx imm) ...@@ -1268,18 +1268,10 @@ aarch64_expand_mov_immediate (rtx dest, rtx imm)
} }
static bool static bool
aarch64_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED) aarch64_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED,
tree exp ATTRIBUTE_UNUSED)
{ {
/* Indirect calls are not currently supported. */ /* Currently, always true. */
if (decl == NULL)
return false;
/* Cannot tail-call to long-calls, since these are outside of the
range of a branch instruction (we could handle this if we added
support for indirect tail-calls. */
if (aarch64_decl_is_long_call_p (decl))
return false;
return true; return true;
} }
...@@ -4360,6 +4352,7 @@ aarch64_class_max_nregs (reg_class_t regclass, enum machine_mode mode) ...@@ -4360,6 +4352,7 @@ aarch64_class_max_nregs (reg_class_t regclass, enum machine_mode mode)
{ {
switch (regclass) switch (regclass)
{ {
case CALLER_SAVE_REGS:
case POINTER_REGS: case POINTER_REGS:
case GENERAL_REGS: case GENERAL_REGS:
case ALL_REGS: case ALL_REGS:
......
...@@ -408,6 +408,7 @@ extern unsigned long aarch64_tune_flags; ...@@ -408,6 +408,7 @@ extern unsigned long aarch64_tune_flags;
enum reg_class enum reg_class
{ {
NO_REGS, NO_REGS,
CALLER_SAVE_REGS,
GENERAL_REGS, GENERAL_REGS,
STACK_REG, STACK_REG,
POINTER_REGS, POINTER_REGS,
...@@ -422,6 +423,7 @@ enum reg_class ...@@ -422,6 +423,7 @@ enum reg_class
#define REG_CLASS_NAMES \ #define REG_CLASS_NAMES \
{ \ { \
"NO_REGS", \ "NO_REGS", \
"CALLER_SAVE_REGS", \
"GENERAL_REGS", \ "GENERAL_REGS", \
"STACK_REG", \ "STACK_REG", \
"POINTER_REGS", \ "POINTER_REGS", \
...@@ -433,6 +435,7 @@ enum reg_class ...@@ -433,6 +435,7 @@ enum reg_class
#define REG_CLASS_CONTENTS \ #define REG_CLASS_CONTENTS \
{ \ { \
{ 0x00000000, 0x00000000, 0x00000000 }, /* NO_REGS */ \ { 0x00000000, 0x00000000, 0x00000000 }, /* NO_REGS */ \
{ 0x0007ffff, 0x00000000, 0x00000000 }, /* CALLER_SAVE_REGS */ \
{ 0x7fffffff, 0x00000000, 0x00000003 }, /* GENERAL_REGS */ \ { 0x7fffffff, 0x00000000, 0x00000003 }, /* GENERAL_REGS */ \
{ 0x80000000, 0x00000000, 0x00000000 }, /* STACK_REG */ \ { 0x80000000, 0x00000000, 0x00000000 }, /* STACK_REG */ \
{ 0xffffffff, 0x00000000, 0x00000003 }, /* POINTER_REGS */ \ { 0xffffffff, 0x00000000, 0x00000003 }, /* POINTER_REGS */ \
......
...@@ -523,6 +523,10 @@ ...@@ -523,6 +523,10 @@
(use (match_operand 2 "" ""))])] (use (match_operand 2 "" ""))])]
"" ""
{ {
if (!REG_P (XEXP (operands[0], 0))
&& (GET_CODE (XEXP (operands[0], 0)) != SYMBOL_REF))
XEXP (operands[0], 0) = force_reg (Pmode, XEXP (operands[0], 0));
if (operands[2] == NULL_RTX) if (operands[2] == NULL_RTX)
operands[2] = const0_rtx; operands[2] = const0_rtx;
} }
...@@ -536,31 +540,38 @@ ...@@ -536,31 +540,38 @@
(use (match_operand 3 "" ""))])] (use (match_operand 3 "" ""))])]
"" ""
{ {
if (!REG_P (XEXP (operands[1], 0))
&& (GET_CODE (XEXP (operands[1], 0)) != SYMBOL_REF))
XEXP (operands[1], 0) = force_reg (Pmode, XEXP (operands[1], 0));
if (operands[3] == NULL_RTX) if (operands[3] == NULL_RTX)
operands[3] = const0_rtx; operands[3] = const0_rtx;
} }
) )
(define_insn "*sibcall_insn" (define_insn "*sibcall_insn"
[(call (mem:DI (match_operand:DI 0 "" "X")) [(call (mem:DI (match_operand:DI 0 "aarch64_call_insn_operand" "Ucs, Usf"))
(match_operand 1 "" "")) (match_operand 1 "" ""))
(return) (return)
(use (match_operand 2 "" ""))] (use (match_operand 2 "" ""))]
"GET_CODE (operands[0]) == SYMBOL_REF" "SIBLING_CALL_P (insn)"
"b\\t%a0" "@
[(set_attr "type" "branch")] br\\t%0
b\\t%a0"
[(set_attr "type" "branch, branch")]
) )
(define_insn "*sibcall_value_insn" (define_insn "*sibcall_value_insn"
[(set (match_operand 0 "" "") [(set (match_operand 0 "" "")
(call (mem:DI (match_operand 1 "" "X")) (call (mem:DI (match_operand 1 "aarch64_call_insn_operand" "Ucs, Usf"))
(match_operand 2 "" ""))) (match_operand 2 "" "")))
(return) (return)
(use (match_operand 3 "" ""))] (use (match_operand 3 "" ""))]
"GET_CODE (operands[1]) == SYMBOL_REF" "SIBLING_CALL_P (insn)"
"b\\t%a1" "@
[(set_attr "type" "branch")] br\\t%1
b\\t%a1"
[(set_attr "type" "branch, branch")]
) )
;; Call subroutine returning any type. ;; Call subroutine returning any type.
......
...@@ -21,6 +21,9 @@ ...@@ -21,6 +21,9 @@
(define_register_constraint "k" "STACK_REG" (define_register_constraint "k" "STACK_REG"
"@internal The stack register.") "@internal The stack register.")
(define_register_constraint "Ucs" "CALLER_SAVE_REGS"
"@internal The caller save registers.")
(define_register_constraint "w" "FP_REGS" (define_register_constraint "w" "FP_REGS"
"Floating point and SIMD vector registers.") "Floating point and SIMD vector registers.")
...@@ -92,6 +95,10 @@ ...@@ -92,6 +95,10 @@
(and (match_code "const_int") (and (match_code "const_int")
(match_test "(unsigned HOST_WIDE_INT) ival < 64"))) (match_test "(unsigned HOST_WIDE_INT) ival < 64")))
(define_constraint "Usf"
"@internal Usf is a symbol reference."
(match_code "symbol_ref"))
(define_constraint "UsM" (define_constraint "UsM"
"@internal "@internal
A constraint that matches the immediate constant -1." A constraint that matches the immediate constant -1."
......
...@@ -26,6 +26,10 @@ ...@@ -26,6 +26,10 @@
&& GET_MODE_CLASS (GET_MODE (op)) == MODE_CC")))) && GET_MODE_CLASS (GET_MODE (op)) == MODE_CC"))))
) )
(define_predicate "aarch64_call_insn_operand"
(ior (match_code "symbol_ref")
(match_operand 0 "register_operand")))
(define_predicate "aarch64_simd_register" (define_predicate "aarch64_simd_register"
(and (match_code "reg") (and (match_code "reg")
(ior (match_test "REGNO_REG_CLASS (REGNO (op)) == FP_LO_REGS") (ior (match_test "REGNO_REG_CLASS (REGNO (op)) == FP_LO_REGS")
......
2014-05-23 Jiong Wang <jiong.wang@arm.com>
* gcc.target/aarch64/tail_indirect_call_1.c: New.
2014-05-23 Paolo Carlini <paolo.carlini@oracle.com> 2014-05-23 Paolo Carlini <paolo.carlini@oracle.com>
* g++.dg/cpp1y/lambda-init9.C: New. * g++.dg/cpp1y/lambda-init9.C: New.
......
/* { dg-do compile } */
/* { dg-options "-O2" } */
typedef void FP (int);
/* { dg-final { scan-assembler "br" } } */
/* { dg-final { scan-assembler-not "blr" } } */
void
f1 (FP fp, int n)
{
(fp) (n);
}
void
f2 (int n, FP fp)
{
(fp) (n);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment