This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [Patch ARM] Fix PR19599
> + if (TARGET_INTERWORK && (decl != NULL_TREE) &&
> + TREE_PUBLIC (decl) && !TREE_ASM_WRITTEN (decl))
> + return false;
>
> This bit has lost its comment. Also, using TREE_PUBLIC +
> TREE_ASM_WRITTEN is the wrong way to do this now, it should be checking
> targetm.binds_local_p().
>
I've updated the comment to mention that this is only a problem for
older binutils and that this check can go away with newer binutils. I am
testing the attached patch that reflects your comments.
Ok to commit if no regressions ?
cheers
Ramana
--
Ramana Radhakrishnan
GNU Tools
ARM Ltd.
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 83db0ec..ef0a75a 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -3660,23 +3660,7 @@ arm_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
/* Never tailcall something for which we have no decl, or if we
are in Thumb mode. */
- if (decl == NULL || TARGET_THUMB)
- return false;
-
- /* The PIC register is live on entry to VxWorks PLT entries, so we
- must make the call before restoring the PIC register. */
- 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 (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). */
- if (TARGET_INTERWORK && TREE_PUBLIC (decl) && !TREE_ASM_WRITTEN (decl))
+ if (TARGET_THUMB)
return false;
func_type = arm_current_func_type ();
@@ -3688,6 +3672,22 @@ arm_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
if (IS_STACKALIGN (func_type))
return false;
+ /* The PIC register is live on entry to VxWorks PLT entries, so we
+ must make the call before restoring the PIC register. */
+ if (TARGET_VXWORKS_RTP && flag_pic &&
+ ((decl != NULL_TREE) && !targetm.binds_local_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). This check
+ will be unnecessary with binutils 2.20 which can handle such
+ interworking between ARM and Thumb state functions within the
+ same compilation unit. */
+ if (TARGET_INTERWORK && (decl != NULL_TREE) &&
+ !targetm.binds_local_p (decl))
+ return false;
+
/* Everything else is ok. */
return true;
}
diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
index 082b5fa..17a85cc 100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -1145,6 +1145,7 @@ enum reg_class
STACK_REG,
BASE_REGS,
HI_REGS,
+ ARM_CALLER_SAVE_REGS,
CC_REG,
VFPCC_REG,
GENERAL_REGS,
@@ -1171,6 +1172,7 @@ enum reg_class
"STACK_REG", \
"BASE_REGS", \
"HI_REGS", \
+ "ARM_CALLER_SAVE_REGS", \
"CC_REG", \
"VFPCC_REG", \
"GENERAL_REGS", \
@@ -1196,6 +1198,7 @@ enum reg_class
{ 0x00002000, 0x00000000, 0x00000000, 0x00000000 }, /* STACK_REG */ \
{ 0x000020FF, 0x00000000, 0x00000000, 0x00000000 }, /* BASE_REGS */ \
{ 0x0000DF00, 0x00000000, 0x00000000, 0x00000000 }, /* HI_REGS */ \
+ { 0x0000100F, 0x00000000, 0x00000000, 0x00000000 }, /* ARM_CALLER_SAVE_REGS */ \
{ 0x01000000, 0x00000000, 0x00000000, 0x00000000 }, /* CC_REG */ \
{ 0x00000000, 0x00000000, 0x00000000, 0x80000000 }, /* VFPCC_REG */ \
{ 0x0200DFFF, 0x00000000, 0x00000000, 0x00000000 }, /* GENERAL_REGS */ \
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 5d12f90..10df081 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -8297,6 +8297,112 @@
(const_int 4)))]
)
+;; We may also be able to do sibcalls for Thumb, but it's much harder...
+(define_expand "sibcall"
+ [(parallel [(call (match_operand 0 "" "")
+ (match_operand 1 "" ""))
+ (return)
+ (use (match_operand 2 "" ""))])]
+ "TARGET_ARM"
+ "
+ {
+ rtx pat;
+ rtx callee = XEXP (operands[0], 0);
+ if ((GET_CODE (callee) == SYMBOL_REF)
+ ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
+ : !REG_P (callee))
+ XEXP (operands[0], 0) = force_reg (Pmode, callee);
+
+ if (operands[2] == NULL_RTX)
+ operands[2] = const0_rtx;
+ }"
+)
+
+
+
+
+(define_insn "*sibcall_insn"
+ [(call (mem:SI (match_operand:SI 0 "call_insn_operand" "Cs,Ss"))
+ (match_operand 1 "" ""))
+ (return)
+ (use (match_operand 2 "" ""))]
+ "TARGET_ARM
+ && SIBLING_CALL_P (insn)"
+ "*
+ if (which_alternative == 1)
+ return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
+ else
+ if (arm_arch5 || arm_arch4t)
+ return \" bx\\t%0\\t%@ indirect register sibling call\";
+ else
+ return \"mov%?\\t%|pc, %0\\t%@ indirect register sibling call\";
+ "
+ [(set_attr "type" "call")]
+)
+
+
+(define_expand "sibcall_value"
+ [(parallel [(set (match_operand 0 "" "")
+ (call (match_operand 1 "" "")
+ (match_operand 2 "" "")))
+ (return)
+ (use (match_operand 3 "" ""))])]
+ "TARGET_ARM"
+ "
+ {
+ rtx pat;
+ rtx callee = XEXP (operands[1], 0);
+
+ if ((GET_CODE (callee) == SYMBOL_REF)
+ ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
+ : !REG_P (callee))
+ XEXP (operands[1], 0) = force_reg (Pmode, callee);
+
+ if (operands[3] == NULL_RTX)
+ operands[3] = const0_rtx;
+
+ pat = gen_sibcall_value_internal (operands[0], operands[1],
+ operands[2], operands[3]);
+
+ emit_call_insn (pat);
+ DONE;
+
+ }"
+)
+
+
+(define_insn "*sibcall_value_insn"
+ [(set (match_operand 0 "register_operand" "")
+ (call (mem:SI (match_operand:SI 1 "call_insn_operand" "Cs,Ss"))
+ (match_operand 2 "" "")))
+ (return)
+ (use (match_operand 3 "" ""))]
+ "TARGET_ARM
+ && SIBLING_CALL_P (insn)
+ && ( REG_P (operands[1]))
+ || ((GET_CODE (operands[1]) == SYMBOL_REF
+ && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))))"
+ "*
+ if (which_alternative == 1)
+ return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
+ else
+ if (arm_arch5 || arm_arch4t)
+ return \"bx%?\\t%1\";
+ else
+ return \"mov%?\\t%|pc, %1\\t%@ indirect sibling call \";
+ "
+ [(set_attr "type" "call")]
+)
+
+(define_insn "sibcall_value_internal"
+ [(parallel [(set (match_operand 0 "" "")
+ (call (match_operand 1 "memory_operand" "")
+ (match_operand 2 "general_operand" "")))
+ (return)
+ (use (match_operand 3 "" ""))])])
+
+
+
(define_expand "call"
[(parallel [(call (match_operand 0 "memory_operand" "")
(match_operand 1 "general_operand" ""))
@@ -8571,58 +8677,6 @@
(set_attr "type" "call")]
)
-;; We may also be able to do sibcalls for Thumb, but it's much harder...
-(define_expand "sibcall"
- [(parallel [(call (match_operand 0 "memory_operand" "")
- (match_operand 1 "general_operand" ""))
- (return)
- (use (match_operand 2 "" ""))])]
- "TARGET_ARM"
- "
- {
- if (operands[2] == NULL_RTX)
- operands[2] = const0_rtx;
- }"
-)
-
-(define_expand "sibcall_value"
- [(parallel [(set (match_operand 0 "" "")
- (call (match_operand 1 "memory_operand" "")
- (match_operand 2 "general_operand" "")))
- (return)
- (use (match_operand 3 "" ""))])]
- "TARGET_ARM"
- "
- {
- if (operands[3] == NULL_RTX)
- operands[3] = const0_rtx;
- }"
-)
-
-(define_insn "*sibcall_insn"
- [(call (mem:SI (match_operand:SI 0 "" "X"))
- (match_operand 1 "" ""))
- (return)
- (use (match_operand 2 "" ""))]
- "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
- "*
- return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
- "
- [(set_attr "type" "call")]
-)
-
-(define_insn "*sibcall_value_insn"
- [(set (match_operand 0 "" "")
- (call (mem:SI (match_operand:SI 1 "" "X"))
- (match_operand 2 "" "")))
- (return)
- (use (match_operand 3 "" ""))]
- "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
- "*
- return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
- "
- [(set_attr "type" "call")]
-)
;; Often the return insn will be the same as loading from memory, so set attr
(define_insn "return"
diff --git a/gcc/config/arm/constraints.md b/gcc/config/arm/constraints.md
index edb0215..b1efd6c 100644
--- a/gcc/config/arm/constraints.md
+++ b/gcc/config/arm/constraints.md
@@ -83,6 +83,9 @@
(define_register_constraint "c" "CC_REG"
"@internal The condition code register.")
+(define_register_constraint "Cs" "ARM_CALLER_SAVE_REGS"
+ "@internal The caller save registers. Useful for sibcalls.")
+
(define_constraint "I"
"In ARM/Thumb-2 state a constant that can be used as an immediate value in a
Data Processing instruction. In Thumb-1 state a constant in the range
@@ -271,3 +274,10 @@
;; Additionally, we used to have a Q constraint in Thumb state, but
;; this wasn't really a valid memory constraint. Again, all uses of
;; this now seem to have been removed.
+
+(define_constraint "Ss"
+ "@internal
+ Ss is a symbol reference."
+ (match_code "symbol_ref")
+)
+
diff --git a/gcc/config/arm/predicates.md b/gcc/config/arm/predicates.md
index d351f44..eff5f9b 100644
--- a/gcc/config/arm/predicates.md
+++ b/gcc/config/arm/predicates.md
@@ -521,3 +521,6 @@
(and (match_code "const_int")
(match_test "INTVAL (op) >= 0 && INTVAL (op) <= 7")))
+(define_predicate "call_insn_operand"
+ (ior (match_code "symbol_ref")
+ (match_operand 0 "s_register_operand")))