Message ID | 533BEEAC.7010808@arm.com |
---|---|
State | New |
Headers | show |
On Wed, Apr 2, 2014 at 12:04 PM, Jiong Wang <jiong.wang@arm.com> wrote: > > On 25/03/14 15:44, Richard Earnshaw wrote: >> >> On 24/03/14 11:26, Jiong Wang wrote: >>> >>> This patch enables tail call optimization for long call on arm. >>> >>> Previously we have too strict check on arm_function_ok_for_sibcall and >>> be lack of the support on sibcall/sibcall_value expand that long call >>> tail oppportunities are lost. >>> >>> OK for next next stage 1? >>> >> I think this is OK for EABI targets (since we can rely on the linker >> generating the right form of interworking veneer), but I'm less certain >> about other systems (do we still support COFF). >> >> I think I'd prefer the patch to factor in TARGET_AAPCS_BASED and to >> assume that if that is true then arbitrary tail-calls are safe. > > > Hi Richard, > > IMHO, this is actually a tail call optimization, we just need to make sure > the register which hold the address be caller saved then it will be OK. > > Updated the change log to fix that "aarch64" typo. No modification on the > patch, but enclose it in this reply to keep wholeness. > > So, is it ok for next stage-1? > This is OK for stage1. Ramana > > Thanks. > > -- > Jiong > > > gcc/ > * config/arm/predicates.md (call_insn_operand): Add long_call check. > * config/arm/arm.md (sibcall, sibcall_value): Force the address to reg > for long_call. > * config/arm/arm.c (arm_function_ok_for_sibcall): Remove long_call > restriction. > > gcc/testsuite > gcc.target/arm/tail-long-call.c: New test.
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index d5f9ff3..8dcdfa8 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -6087,11 +6087,6 @@ arm_function_ok_for_sibcall (tree decl, tree exp) if (TARGET_VXWORKS_RTP && flag_pic && !targetm.binds_local_p (decl)) return false; - /* Cannot tail-call to long calls, since these are out of range of - a branch instruction. */ - if (decl && arm_is_long_call_p (decl)) - return false; - /* If we are interworking and the function is not declared static then we can't tail-call it unless we know that it exists in this compilation unit (since it might be a Thumb routine). */ diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md index 2ddda02..fe285f0 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -9444,8 +9444,10 @@ "TARGET_32BIT" " { - if (!REG_P (XEXP (operands[0], 0)) - && (GET_CODE (XEXP (operands[0], 0)) != SYMBOL_REF)) + if ((!REG_P (XEXP (operands[0], 0)) + && GET_CODE (XEXP (operands[0], 0)) != SYMBOL_REF) + || (GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF + && arm_is_long_call_p (SYMBOL_REF_DECL (XEXP (operands[0], 0))))) XEXP (operands[0], 0) = force_reg (SImode, XEXP (operands[0], 0)); if (operands[2] == NULL_RTX) @@ -9462,8 +9464,10 @@ "TARGET_32BIT" " { - if (!REG_P (XEXP (operands[1], 0)) && - (GET_CODE (XEXP (operands[1],0)) != SYMBOL_REF)) + if ((!REG_P (XEXP (operands[1], 0)) + && GET_CODE (XEXP (operands[1], 0)) != SYMBOL_REF) + || (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF + && arm_is_long_call_p (SYMBOL_REF_DECL (XEXP (operands[1], 0))))) XEXP (operands[1], 0) = force_reg (SImode, XEXP (operands[1], 0)); if (operands[3] == NULL_RTX) diff --git a/gcc/config/arm/predicates.md b/gcc/config/arm/predicates.md index ce5c9a8..3673343 100644 --- a/gcc/config/arm/predicates.md +++ b/gcc/config/arm/predicates.md @@ -673,5 +673,6 @@ (match_code "reg" "0"))) (define_predicate "call_insn_operand" - (ior (match_code "symbol_ref") + (ior (and (match_code "symbol_ref") + (match_test "!arm_is_long_call_p (SYMBOL_REF_DECL (op))")) (match_operand 0 "s_register_operand"))) diff --git a/gcc/testsuite/gcc.target/arm/tail-long-call.c b/gcc/testsuite/gcc.target/arm/tail-long-call.c new file mode 100644 index 0000000..9b27468 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/tail-long-call.c @@ -0,0 +1,12 @@ +/* { dg-skip-if "need at least armv5te" { *-*-* } { "-march=armv[234]*" "-mthumb" } { "" } } */ +/* { dg-options "-O2 -march=armv5te -marm" } */ +/* { dg-final { scan-assembler "bx" } } */ +/* { dg-final { scan-assembler-not "blx" } } */ + +int lcal (int) __attribute__ ((long_call)); + +int +dec (int a) +{ + return lcal (a); +}