aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Earnshaw <rearnsha@arm.com>2000-08-15 15:14:06 +0000
committerRichard Earnshaw <rearnsha@gcc.gnu.org>2000-08-15 15:14:06 +0000
commitf99fce0c53a352c7d1918ad90968480524076243 (patch)
tree0dcafe121ad1c83227ccc61fe56cb93bb123a1b9 /gcc
parent74da3101e564d728a141605cb4f4d0dc99504eaa (diff)
downloadgcc-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/ChangeLog7
-rw-r--r--gcc/config/arm/arm.c35
-rw-r--r--gcc/config/arm/arm.h7
-rw-r--r--gcc/config/arm/arm.md17
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;
- }
}"
)