This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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")))

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]