From fee9ba422f9193fb5e560bd430d7b14c55c128d1 Mon Sep 17 00:00:00 2001 From: Jiong Wang Date: Fri, 23 May 2014 12:13:56 +0000 Subject: [PATCH] [AARCH64] Support tail indirect function call. From-SVN: r210861 --- gcc/ChangeLog | 14 +++++++++ gcc/config/aarch64/aarch64.c | 15 +++------- gcc/config/aarch64/aarch64.h | 3 ++ gcc/config/aarch64/aarch64.md | 29 +++++++++++++------ gcc/config/aarch64/constraints.md | 7 +++++ gcc/config/aarch64/predicates.md | 4 +++ gcc/testsuite/ChangeLog | 4 +++ .../gcc.target/aarch64/tail_indirect_call_1.c | 18 ++++++++++++ 8 files changed, 74 insertions(+), 20 deletions(-) create mode 100644 gcc/testsuite/gcc.target/aarch64/tail_indirect_call_1.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 397893d9682..ec102fe4bbf 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,17 @@ +2014-05-23 Jiong Wang + + * 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 * gimplify.c (omp_notice_variable) : diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index d73c5ef6868..c2f6c4f483b 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 5c1c4044c7a..ced5a5e9252 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 da9444fca25..c3783149dd2 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 12ab570c05e..807d0b172c8 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 c8e27d8715d..2702a3c8d83 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 ffbc66d0a3b..a765cb88a52 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2014-05-23 Jiong Wang + + * gcc.target/aarch64/tail_indirect_call_1.c: New. + 2014-05-23 Paolo Carlini * 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 00000000000..4759d20df9c --- /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); +}