aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJiong Wang <jiong.wang@arm.com>2014-05-23 12:13:56 +0000
committerMarcus Shawcroft <mshawcroft@gcc.gnu.org>2014-05-23 12:13:56 +0000
commitfee9ba422f9193fb5e560bd430d7b14c55c128d1 (patch)
tree328b22ad3f498f9acde8e193b6397702b1e9f4a3
parent09af4b4c423bf47d4b7dbcf1fc8ebd31a3a1769d (diff)
downloadgcc-fee9ba422f9193fb5e560bd430d7b14c55c128d1.zip
gcc-fee9ba422f9193fb5e560bd430d7b14c55c128d1.tar.gz
gcc-fee9ba422f9193fb5e560bd430d7b14c55c128d1.tar.bz2
[AARCH64] Support tail indirect function call.
From-SVN: r210861
-rw-r--r--gcc/ChangeLog14
-rw-r--r--gcc/config/aarch64/aarch64.c15
-rw-r--r--gcc/config/aarch64/aarch64.h3
-rw-r--r--gcc/config/aarch64/aarch64.md29
-rw-r--r--gcc/config/aarch64/constraints.md7
-rw-r--r--gcc/config/aarch64/predicates.md4
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.target/aarch64/tail_indirect_call_1.c18
8 files changed, 74 insertions, 20 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 397893d..ec102fe 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,17 @@
+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>
* gimplify.c (omp_notice_variable) <case OMP_CLAUSE_DEFAULT_NONE>:
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index d73c5ef..c2f6c4f 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -1268,18 +1268,10 @@ aarch64_expand_mov_immediate (rtx dest, rtx imm)
}
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. */
- 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;
-
+ /* Currently, always true. */
return true;
}
@@ -4360,6 +4352,7 @@ aarch64_class_max_nregs (reg_class_t regclass, enum machine_mode mode)
{
switch (regclass)
{
+ case CALLER_SAVE_REGS:
case POINTER_REGS:
case GENERAL_REGS:
case ALL_REGS:
diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
index 5c1c404..ced5a5e 100644
--- a/gcc/config/aarch64/aarch64.h
+++ b/gcc/config/aarch64/aarch64.h
@@ -408,6 +408,7 @@ extern unsigned long aarch64_tune_flags;
enum reg_class
{
NO_REGS,
+ CALLER_SAVE_REGS,
GENERAL_REGS,
STACK_REG,
POINTER_REGS,
@@ -422,6 +423,7 @@ enum reg_class
#define REG_CLASS_NAMES \
{ \
"NO_REGS", \
+ "CALLER_SAVE_REGS", \
"GENERAL_REGS", \
"STACK_REG", \
"POINTER_REGS", \
@@ -433,6 +435,7 @@ enum reg_class
#define REG_CLASS_CONTENTS \
{ \
{ 0x00000000, 0x00000000, 0x00000000 }, /* NO_REGS */ \
+ { 0x0007ffff, 0x00000000, 0x00000000 }, /* CALLER_SAVE_REGS */ \
{ 0x7fffffff, 0x00000000, 0x00000003 }, /* GENERAL_REGS */ \
{ 0x80000000, 0x00000000, 0x00000000 }, /* STACK_REG */ \
{ 0xffffffff, 0x00000000, 0x00000003 }, /* POINTER_REGS */ \
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index da9444f..c378314 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -523,6 +523,10 @@
(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)
operands[2] = const0_rtx;
}
@@ -536,31 +540,38 @@
(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)
operands[3] = const0_rtx;
}
)
(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 "" ""))
(return)
(use (match_operand 2 "" ""))]
- "GET_CODE (operands[0]) == SYMBOL_REF"
- "b\\t%a0"
- [(set_attr "type" "branch")]
-
+ "SIBLING_CALL_P (insn)"
+ "@
+ br\\t%0
+ b\\t%a0"
+ [(set_attr "type" "branch, branch")]
)
(define_insn "*sibcall_value_insn"
[(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 "" "")))
(return)
(use (match_operand 3 "" ""))]
- "GET_CODE (operands[1]) == SYMBOL_REF"
- "b\\t%a1"
- [(set_attr "type" "branch")]
+ "SIBLING_CALL_P (insn)"
+ "@
+ br\\t%1
+ b\\t%a1"
+ [(set_attr "type" "branch, branch")]
)
;; Call subroutine returning any type.
diff --git a/gcc/config/aarch64/constraints.md b/gcc/config/aarch64/constraints.md
index 12ab570..807d0b1 100644
--- a/gcc/config/aarch64/constraints.md
+++ b/gcc/config/aarch64/constraints.md
@@ -21,6 +21,9 @@
(define_register_constraint "k" "STACK_REG"
"@internal The stack register.")
+(define_register_constraint "Ucs" "CALLER_SAVE_REGS"
+ "@internal The caller save registers.")
+
(define_register_constraint "w" "FP_REGS"
"Floating point and SIMD vector registers.")
@@ -92,6 +95,10 @@
(and (match_code "const_int")
(match_test "(unsigned HOST_WIDE_INT) ival < 64")))
+(define_constraint "Usf"
+ "@internal Usf is a symbol reference."
+ (match_code "symbol_ref"))
+
(define_constraint "UsM"
"@internal
A constraint that matches the immediate constant -1."
diff --git a/gcc/config/aarch64/predicates.md b/gcc/config/aarch64/predicates.md
index c8e27d8..2702a3c 100644
--- a/gcc/config/aarch64/predicates.md
+++ b/gcc/config/aarch64/predicates.md
@@ -26,6 +26,10 @@
&& 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"
(and (match_code "reg")
(ior (match_test "REGNO_REG_CLASS (REGNO (op)) == FP_LO_REGS")
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index ffbc66d..a765cb8 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+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>
* g++.dg/cpp1y/lambda-init9.C: New.
diff --git a/gcc/testsuite/gcc.target/aarch64/tail_indirect_call_1.c b/gcc/testsuite/gcc.target/aarch64/tail_indirect_call_1.c
new file mode 100644
index 0000000..4759d20
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/tail_indirect_call_1.c
@@ -0,0 +1,18 @@
+/* { 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);
+}