mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-08 03:36:44 +08:00
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
This commit is contained in:
parent
74da3101e5
commit
f99fce0c53
@ -1,3 +1,10 @@
|
||||
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.
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
}"
|
||||
)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user