commit 5d0e570066009d361181be26e8ba858139ee5b8e
Author: Ramana Radhakrishnan <ramana.radhakrishnan@arm.com>
Date: Wed May 15 08:47:20 2013 +0100
Fix PR19599 properly.
@@ -5376,9 +5376,8 @@ arm_function_ok_for_sibcall (tree decl, tree exp)
if (cfun->machine->sibcall_blocked)
return false;
- /* Never tailcall something for which we have no decl, or if we
- are generating code for Thumb-1. */
- if (decl == NULL || TARGET_THUMB1)
+ /* Never tailcall something if we are generating code for Thumb-1. */
+ if (TARGET_THUMB1)
return false;
/* The PIC register is live on entry to VxWorks PLT entries, so we
@@ -5388,13 +5387,14 @@ arm_function_ok_for_sibcall (tree decl, tree exp)
/* Cannot tail-call to long calls, since these are out of range of
a branch instruction. */
- if (arm_is_long_call_p (decl))
+ 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). */
- if (TARGET_INTERWORK && TREE_PUBLIC (decl) && !TREE_ASM_WRITTEN (decl))
+ if (TARGET_INTERWORK && decl && TREE_PUBLIC (decl)
+ && !TREE_ASM_WRITTEN (decl))
return false;
func_type = arm_current_func_type ();
@@ -1142,6 +1142,7 @@ enum reg_class
STACK_REG,
BASE_REGS,
HI_REGS,
+ CALLER_SAVE_REGS,
GENERAL_REGS,
CORE_REGS,
VFP_D0_D7_REGS,
@@ -1168,6 +1169,7 @@ enum reg_class
"STACK_REG", \
"BASE_REGS", \
"HI_REGS", \
+ "CALLER_SAVE_REGS", \
"GENERAL_REGS", \
"CORE_REGS", \
"VFP_D0_D7_REGS", \
@@ -1193,6 +1195,7 @@ enum reg_class
{ 0x00002000, 0x00000000, 0x00000000, 0x00000000 }, /* STACK_REG */ \
{ 0x000020FF, 0x00000000, 0x00000000, 0x00000000 }, /* BASE_REGS */ \
{ 0x00005F00, 0x00000000, 0x00000000, 0x00000000 }, /* HI_REGS */ \
+ { 0x0000100F, 0x00000000, 0x00000000, 0x00000000 }, /* CALLER_SAVE_REGS */ \
{ 0x00005FFF, 0x00000000, 0x00000000, 0x00000000 }, /* GENERAL_REGS */ \
{ 0x00007FFF, 0x00000000, 0x00000000, 0x00000000 }, /* CORE_REGS */ \
{ 0xFFFF0000, 0x00000000, 0x00000000, 0x00000000 }, /* VFP_D0_D7_REGS */ \
@@ -8889,7 +8889,7 @@
(match_operand 1 "" ""))
(use (match_operand 2 "" ""))
(clobber (reg:SI LR_REGNUM))]
- "TARGET_ARM && arm_arch5"
+ "TARGET_ARM && arm_arch5 && !SIBLING_CALL_P (insn)"
"blx%?\\t%0"
[(set_attr "type" "call")]
)
@@ -8899,7 +8899,7 @@
(match_operand 1 "" ""))
(use (match_operand 2 "" ""))
(clobber (reg:SI LR_REGNUM))]
- "TARGET_ARM && !arm_arch5"
+ "TARGET_ARM && !arm_arch5 && !SIBLING_CALL_P (insn)"
"*
return output_call (operands);
"
@@ -8918,7 +8918,7 @@
(match_operand 1 "" ""))
(use (match_operand 2 "" ""))
(clobber (reg:SI LR_REGNUM))]
- "TARGET_ARM && !arm_arch5"
+ "TARGET_ARM && !arm_arch5 && !SIBLING_CALL_P (insn)"
"*
return output_call_mem (operands);
"
@@ -8931,7 +8931,7 @@
(match_operand 1 "" ""))
(use (match_operand 2 "" ""))
(clobber (reg:SI LR_REGNUM))]
- "TARGET_THUMB1 && arm_arch5"
+ "TARGET_THUMB1 && arm_arch5 && !SIBLING_CALL_P (insn)"
"blx\\t%0"
[(set_attr "length" "2")
(set_attr "type" "call")]
@@ -8942,7 +8942,7 @@
(match_operand 1 "" ""))
(use (match_operand 2 "" ""))
(clobber (reg:SI LR_REGNUM))]
- "TARGET_THUMB1 && !arm_arch5"
+ "TARGET_THUMB1 && !arm_arch5 && !SIBLING_CALL_P (insn)"
"*
{
if (!TARGET_CALLER_INTERWORKING)
@@ -9001,7 +9001,7 @@
(match_operand 2 "" "")))
(use (match_operand 3 "" ""))
(clobber (reg:SI LR_REGNUM))]
- "TARGET_ARM && arm_arch5"
+ "TARGET_ARM && arm_arch5 && !SIBLING_CALL_P (insn)"
"blx%?\\t%1"
[(set_attr "type" "call")]
)
@@ -9012,7 +9012,7 @@
(match_operand 2 "" "")))
(use (match_operand 3 "" ""))
(clobber (reg:SI LR_REGNUM))]
- "TARGET_ARM && !arm_arch5"
+ "TARGET_ARM && !arm_arch5 && !SIBLING_CALL_P (insn)"
"*
return output_call (&operands[1]);
"
@@ -9028,7 +9028,8 @@
(match_operand 2 "" "")))
(use (match_operand 3 "" ""))
(clobber (reg:SI LR_REGNUM))]
- "TARGET_ARM && !arm_arch5 && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
+ "TARGET_ARM && !arm_arch5 && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
+ && !SIBLING_CALL_P (insn)"
"*
return output_call_mem (&operands[1]);
"
@@ -9078,6 +9079,7 @@
(use (match_operand 2 "" ""))
(clobber (reg:SI LR_REGNUM))]
"TARGET_32BIT
+ && !SIBLING_CALL_P (insn)
&& (GET_CODE (operands[0]) == SYMBOL_REF)
&& !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
"*
@@ -9094,6 +9096,7 @@
(use (match_operand 3 "" ""))
(clobber (reg:SI LR_REGNUM))]
"TARGET_32BIT
+ && !SIBLING_CALL_P (insn)
&& (GET_CODE (operands[1]) == SYMBOL_REF)
&& !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
"*
@@ -9139,6 +9142,10 @@
"TARGET_32BIT"
"
{
+ if (!REG_P (XEXP (operands[0], 0))
+ && (GET_CODE (XEXP (operands[0], 0)) != SYMBOL_REF))
+ XEXP (operands[0], 0) = force_reg (SImode, XEXP (operands[0], 0));
+
if (operands[2] == NULL_RTX)
operands[2] = const0_rtx;
}"
@@ -9153,32 +9160,52 @@
"TARGET_32BIT"
"
{
+ if (!REG_P (XEXP (operands[1], 0)) &&
+ (GET_CODE (XEXP (operands[1],0)) != SYMBOL_REF))
+ XEXP (operands[1], 0) = force_reg (SImode, XEXP (operands[1], 0));
+
if (operands[3] == NULL_RTX)
operands[3] = const0_rtx;
}"
)
(define_insn "*sibcall_insn"
- [(call (mem:SI (match_operand:SI 0 "" "X"))
+ [(call (mem:SI (match_operand:SI 0 "call_insn_operand" "Cs,Ss"))
(match_operand 1 "" ""))
(return)
(use (match_operand 2 "" ""))]
- "TARGET_32BIT && GET_CODE (operands[0]) == SYMBOL_REF"
+ "TARGET_32BIT && SIBLING_CALL_P (insn)"
"*
- return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
+ 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_insn "*sibcall_value_insn"
- [(set (match_operand 0 "" "")
- (call (mem:SI (match_operand:SI 1 "" "X"))
+ [(set (match_operand 0 "s_register_operand" "")
+ (call (mem:SI (match_operand:SI 1 "call_insn_operand" "Cs,Ss"))
(match_operand 2 "" "")))
(return)
(use (match_operand 3 "" ""))]
- "TARGET_32BIT && GET_CODE (operands[1]) == SYMBOL_REF"
+ "TARGET_32BIT && SIBLING_CALL_P (insn)"
"*
- return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
+ 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")]
)
@@ -96,6 +96,9 @@
(define_register_constraint "c" "CC_REG"
"@internal The condition code register.")
+(define_register_constraint "Cs" "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
@@ -400,3 +403,9 @@
;; 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")
+)
@@ -635,3 +635,7 @@
(define_predicate "mem_noofs_operand"
(and (match_code "mem")
(match_code "reg" "0")))
+
+(define_predicate "call_insn_operand"
+ (ior (match_code "symbol_ref")
+ (match_operand 0 "s_register_operand")))
new file mode 100644
@@ -0,0 +1,10 @@
+/* { dg-skip-if "need at least armv5te" { *-*-* } { "-march=armv[234]*" } { "" } } */
+/* { dg-options "-O2 -march=armv5te -marm" } */
+/* { dg-final { scan-assembler "bx" } } */
+
+int (*indirect_func)();
+
+int indirect_call()
+{
+ return indirect_func();
+}
@@ -2,9 +2,9 @@
/* { dg-options "-O2 -march=armv5te" } */
/* { dg-final { scan-assembler "blx" } } */
-int (*indirect_func)();
+int (*indirect_func)(int x);
int indirect_call()
{
- return indirect_func();
+ return indirect_func(20) + indirect_func (40);
}