diff options
author | Richard Earnshaw <rearnsha@arm.com> | 2000-08-15 15:14:06 +0000 |
---|---|---|
committer | Richard Earnshaw <rearnsha@gcc.gnu.org> | 2000-08-15 15:14:06 +0000 |
commit | f99fce0c53a352c7d1918ad90968480524076243 (patch) | |
tree | 0dcafe121ad1c83227ccc61fe56cb93bb123a1b9 /gcc | |
parent | 74da3101e564d728a141605cb4f4d0dc99504eaa (diff) | |
download | gcc-f99fce0c53a352c7d1918ad90968480524076243.zip gcc-f99fce0c53a352c7d1918ad90968480524076243.tar.gz gcc-f99fce0c53a352c7d1918ad90968480524076243.tar.bz2 |
arm.c (arm_function_ok_for_sibcall): New function.
* arm.c (arm_function_ok_for_sibcall): New function.
* arm.h (FUNCTION_OK_FOR_SIBCALL): Define.
* arm.md (call expanders): Don't check here for calls that can't
be sibling calls.
From-SVN: r35708
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/config/arm/arm.c | 35 | ||||
-rw-r--r-- | gcc/config/arm/arm.h | 7 | ||||
-rw-r--r-- | gcc/config/arm/arm.md | 17 |
4 files changed, 49 insertions, 17 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8192bbe..71c99bc 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,12 @@ 2000-08-15 Richard Earnshaw <rearnsha@arm.com> + * arm.c (arm_function_ok_for_sibcall): New function. + * arm.h (FUNCTION_OK_FOR_SIBCALL): Define. + * arm.md (call expanders): Don't check here for calls that can't + be sibling calls. + +2000-08-15 Richard Earnshaw <rearnsha@arm.com> + * arm.md (splits generating cond_exec): Disable. 2000-08-15 Richard Earnshaw <rearnsha@arm.com> diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index e905dae..d559d00 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -1830,6 +1830,41 @@ arm_is_longcall_p (sym_ref, call_cookie, call_symbol) || ENCODED_LONG_CALL_ATTR_P (XSTR (sym_ref, 0)) || TARGET_LONG_CALLS; } + +/* Return non-zero if it is ok to make a tail-call to DECL. */ +int +arm_function_ok_for_sibcall (decl) + tree decl; +{ + int call_type = TARGET_LONG_CALLS ? CALL_LONG : CALL_NORMAL; + + /* Never tailcall something for which we have no decl, or if we + are in Thumb mode. */ + if (decl == NULL || TARGET_THUMB) + return 0; + + /* Get the calling method. */ + if (lookup_attribute ("short_call", TYPE_ATTRIBUTES (TREE_TYPE (decl)))) + call_type = CALL_SHORT; + else if (lookup_attribute ("long_call", TYPE_ATTRIBUTES (TREE_TYPE (decl)))) + call_type = CALL_LONG; + + /* Cannot tail-call to long calls, since these are out of range of + a branch instruction. However, if not compiling PIC, we know + we can reach the symbol if it is in this compilation unit. */ + if (call_type == CALL_LONG && (flag_pic || ! TREE_ASM_WRITTEN (decl))) + return 0; + + /* 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). */ + if (TARGET_INTERWORK && TREE_PUBLIC (decl) && ! TREE_ASM_WRITTEN (decl)) + return 0; + + /* Everything else is ok. */ + return 1; +} + int legitimate_pic_operand_p (x) diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h index 04702f1..b94e8b4 100644 --- a/gcc/config/arm/arm.h +++ b/gcc/config/arm/arm.h @@ -1450,6 +1450,13 @@ typedef struct #define FUNCTION_ARG_REGNO_P(REGNO) \ ((REGNO) >= 0 && (REGNO) <= 3) + +/* Tail calling. */ + +/* A C expression that evaluates to true if it is ok to perform a sibling + call to DECL. */ +#define FUNCTION_OK_FOR_SIBCALL(DECL) arm_function_ok_for_sibcall ((DECL)) + /* Perform any actions needed for a function that is receiving a variable number of arguments. CUM is as above. MODE and TYPE are the mode and type of the current parameter. PRETEND_SIZE is a variable that should be set to diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md index 46bf515..379b308 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -6265,14 +6265,6 @@ { if (operands[2] == NULL_RTX) operands[2] = const0_rtx; - - /* If we need to emit a long-call, we can't do it as a sibling call, - so fail over to a normal call. */ - if (arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0)) - { - emit_call_insn (gen_call (operands[0], operands[1], operands[2])); - DONE; - } }" ) @@ -6286,15 +6278,6 @@ { if (operands[3] == NULL_RTX) operands[3] = const0_rtx; - - /* If we need to emit a long-call, we can't do it as a sibling call, - so fail over to a normal call. */ - if (arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0)) - { - emit_call_insn (gen_call_value (operands[0], operands[1], operands[2], - operands[3])); - DONE; - } }" ) |