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]

[PATCH] Fix PR c++/5964


Hi!

(note that this bug disappeared from PR, maybe a new one should be created
with what it contained).
The testcase below did not link on sparc -m64 -O0, because SPARC
length computation was pretty inaccurate (e.g. unconditional branches with
nops in delay slots were 1 insn shorter, on the other side conditional
branches with full delay slots were 1 insn longer than they actually were).
Below is an attempt for precise length computation.
Have tested it on the testcase, but as my sparc64-linux box has still
issues with libstdc++ relocations, haven't bootstrapped it.
Could someone please bootstrap this on sparcv9-*-solaris2.[89]?
Thanks.

2002-03-27  Jakub Jelinek  <jakub@redhat.com>

	PR c++/5964
	* config/sparc/sparc.md (empty_delay_slot, branch_type): New
	attributes.
	(length): Compute variable length for branches/calls/jumps here.
	(branch, inverted_branch, normal_fp_branch, inverted_fp_branch,
	normal_fpe_branch, inverted_fpe_branch): Remove length attribute,
	define branch_type attribute.
	(divsi3_sp32): Maximum length is 6 not 7.
	(call_address_struct_value_sp32, call_symbolic_struct_value_sp32,
	call_address_untyped_struct_value_sp32,
	call_symbolic_untyped_struct_value_sp32): Set length to 3 not 2.
	* config/sparc/sparc.c (empty_delay_slot): New function.
	* config/sparc/sparc.h (ADJUST_INSN_LENGTH): Remove.
	* config/sparc/sparc-protos.h (empty_delay_slot): Add prototype.

	* g++.dg/opt/longbranch1.C: New test.

--- gcc/config/sparc/sparc.md.jj	Tue Mar 26 17:57:12 2002
+++ gcc/config/sparc/sparc.md	Wed Mar 27 13:10:00 2002
@@ -87,8 +87,75 @@
   "ialu,compare,shift,load,sload,store,uncond_branch,branch,call,sibcall,call_no_delay_slot,return,imul,idiv,fpload,fpstore,fp,fpmove,fpcmove,fpcmp,fpmul,fpdivs,fpdivd,fpsqrts,fpsqrtd,cmove,multi,misc"
   (const_string "ialu"))
 
+;; true if branch/call has empty delay slot and will emit a nop in it
+(define_attr "empty_delay_slot" "false,true"
+  (symbol_ref "empty_delay_slot (insn)"))
+
+(define_attr "branch_type" "none,icc,fcc,reg" (const_string "none"))
+
 ;; Length (in # of insns).
-(define_attr "length" "" (const_int 1))
+(define_attr "length" ""
+  (cond [(eq_attr "type" "uncond_branch,call,sibcall")
+	   (if_then_else (eq_attr "empty_delay_slot" "true")
+	     (const_int 2)
+	     (const_int 1))
+	 (eq_attr "branch_type" "icc")
+	   (if_then_else (match_operand 0 "noov_compare64_op" "")
+	     (if_then_else (lt (pc) (match_dup 1))
+	       (if_then_else (lt (minus (match_dup 1) (pc)) (const_int 260000))
+		 (if_then_else (eq_attr "empty_delay_slot" "true")
+		   (const_int 2)
+		   (const_int 1))
+		 (if_then_else (eq_attr "empty_delay_slot" "true")
+		   (const_int 4)
+		   (const_int 3)))
+	       (if_then_else (lt (minus (pc) (match_dup 1)) (const_int 260000))
+		 (if_then_else (eq_attr "empty_delay_slot" "true")
+		   (const_int 2)
+		   (const_int 1))
+		 (if_then_else (eq_attr "empty_delay_slot" "true")
+		   (const_int 4)
+		   (const_int 3))))
+	     (if_then_else (eq_attr "empty_delay_slot" "true")
+	       (const_int 2)
+	       (const_int 1)))
+	 (eq_attr "branch_type" "fcc")
+	   (if_then_else (match_operand 0 "fcc0_reg_operand" "")
+	     (if_then_else (eq_attr "empty_delay_slot" "true")
+	       (const_int 2)
+	       (const_int 1))
+	     (if_then_else (lt (pc) (match_dup 2))
+	       (if_then_else (lt (minus (match_dup 2) (pc)) (const_int 260000))
+		 (if_then_else (eq_attr "empty_delay_slot" "true")
+		   (const_int 2)
+		   (const_int 1))
+		 (if_then_else (eq_attr "empty_delay_slot" "true")
+		   (const_int 4)
+		   (const_int 3)))
+	       (if_then_else (lt (minus (pc) (match_dup 2)) (const_int 260000))
+		 (if_then_else (eq_attr "empty_delay_slot" "true")
+		   (const_int 2)
+		   (const_int 1))
+		 (if_then_else (eq_attr "empty_delay_slot" "true")
+		   (const_int 4)
+		   (const_int 3)))))
+	 (eq_attr "branch_type" "reg")
+	   (if_then_else (lt (pc) (match_dup 2))
+	     (if_then_else (lt (minus (match_dup 2) (pc)) (const_int 32000))
+	       (if_then_else (eq_attr "empty_delay_slot" "true")
+		 (const_int 2)
+		 (const_int 1))
+	       (if_then_else (eq_attr "empty_delay_slot" "true")
+		 (const_int 4)
+		 (const_int 3)))
+	     (if_then_else (lt (minus (pc) (match_dup 2)) (const_int 32000))
+	       (if_then_else (eq_attr "empty_delay_slot" "true")
+		 (const_int 2)
+		 (const_int 1))
+	       (if_then_else (eq_attr "empty_delay_slot" "true")
+		 (const_int 4)
+		 (const_int 3))))
+	 ] (const_int 1)))
 
 ;; FP precision.
 (define_attr "fptype" "single,double" (const_string "single"))
@@ -1898,18 +1965,7 @@
 			 ! final_sequence, insn);
 }"
   [(set_attr "type" "branch")
-   (set (attr "length")
-	(if_then_else (match_operand 0 "noov_compare64_op" "")
-		      (if_then_else (lt (pc) (match_dup 1))
-				    (if_then_else (lt (minus (match_dup 1) (pc))
-						      (const_int 260000))
-						  (const_int 1)
-						  (const_int 3))
-				    (if_then_else (lt (minus (pc) (match_dup 1))
-						      (const_int 260000))
-						  (const_int 1)
-						  (const_int 3)))
-		      (const_int 1)))])
+   (set_attr "branch_type" "icc")])
 
 ;; XXX fpcmp nop braindamage
 (define_insn "*inverted_branch"
@@ -1926,18 +1982,7 @@
 			 ! final_sequence, insn);
 }"
   [(set_attr "type" "branch")
-   (set (attr "length")
-	(if_then_else (match_operand 0 "noov_compare64_op" "")
-		      (if_then_else (lt (pc) (match_dup 1))
-				    (if_then_else (lt (minus (match_dup 1) (pc))
-						      (const_int 260000))
-						  (const_int 1)
-						  (const_int 3))
-				    (if_then_else (lt (minus (pc) (match_dup 1))
-						      (const_int 260000))
-						  (const_int 1)
-						  (const_int 3)))
-		      (const_int 1)))])
+   (set_attr "branch_type" "icc")])
 
 ;; XXX fpcmp nop braindamage
 (define_insn "*normal_fp_branch"
@@ -1955,18 +2000,7 @@
 			 ! final_sequence, insn);
 }"
   [(set_attr "type" "branch")
-   (set (attr "length")
-	(if_then_else (match_operand 0 "fcc0_reg_operand" "")
-		      (const_int 1)
-		      (if_then_else (lt (pc) (match_dup 2))
-				    (if_then_else (lt (minus (match_dup 2) (pc))
-						      (const_int 260000))
-						  (const_int 1)
-						  (const_int 3))
-				    (if_then_else (lt (minus (pc) (match_dup 2))
-						      (const_int 260000))
-						  (const_int 1)
-						  (const_int 3)))))])
+   (set_attr "branch_type" "fcc")])
 
 ;; XXX fpcmp nop braindamage
 (define_insn "*inverted_fp_branch"
@@ -1984,18 +2018,7 @@
 			 ! final_sequence, insn);
 }"
   [(set_attr "type" "branch")
-   (set (attr "length")
-	(if_then_else (match_operand 0 "fcc0_reg_operand" "")
-		      (const_int 1)
-		      (if_then_else (lt (pc) (match_dup 2))
-				    (if_then_else (lt (minus (match_dup 2) (pc))
-						      (const_int 260000))
-						  (const_int 1)
-						  (const_int 3))
-				    (if_then_else (lt (minus (pc) (match_dup 2))
-						      (const_int 260000))
-						  (const_int 1)
-						  (const_int 3)))))])
+   (set_attr "branch_type" "fcc")])
 
 ;; XXX fpcmp nop braindamage
 (define_insn "*normal_fpe_branch"
@@ -2013,18 +2036,7 @@
 			 ! final_sequence, insn);
 }"
   [(set_attr "type" "branch")
-   (set (attr "length")
-	(if_then_else (match_operand 0 "fcc0_reg_operand" "")
-		      (const_int 1)
-		      (if_then_else (lt (pc) (match_dup 2))
-				    (if_then_else (lt (minus (match_dup 2) (pc))
-						      (const_int 260000))
-						  (const_int 1)
-						  (const_int 3))
-				    (if_then_else (lt (minus (pc) (match_dup 2))
-						      (const_int 260000))
-						  (const_int 1)
-						  (const_int 3)))))])
+   (set_attr "branch_type" "fcc")])
 
 ;; XXX fpcmp nop braindamage
 (define_insn "*inverted_fpe_branch"
@@ -2042,18 +2054,7 @@
 			 ! final_sequence, insn);
 }"
   [(set_attr "type" "branch")
-   (set (attr "length")
-	(if_then_else (match_operand 0 "fcc0_reg_operand" "")
-		      (const_int 1)
-		      (if_then_else (lt (pc) (match_dup 2))
-				    (if_then_else (lt (minus (match_dup 2) (pc))
-						      (const_int 260000))
-						  (const_int 1)
-						  (const_int 3))
-				    (if_then_else (lt (minus (pc) (match_dup 2))
-						      (const_int 260000))
-						  (const_int 1)
-						  (const_int 3)))))])
+   (set_attr "branch_type" "fcc")])
 
 ;; Sparc V9-specific jump insns.  None of these are guaranteed to be
 ;; in the architecture.
@@ -2076,16 +2077,7 @@
 			  ! final_sequence, insn);
 }"
   [(set_attr "type" "branch")
-   (set (attr "length")
-        (if_then_else (lt (pc) (match_dup 2))
-		      (if_then_else (lt (minus (match_dup 2) (pc))
-					(const_int 32000))
-				    (const_int 1)
-				    (const_int 3))
-		      (if_then_else (lt (minus (pc) (match_dup 2))
-					(const_int 32000))
-				    (const_int 1)
-				    (const_int 3))))])
+   (set_attr "branch_type" "reg")])
 
 ;; XXX
 (define_insn "*inverted_int_branch_sp64"
@@ -2103,16 +2095,7 @@
 			  ! final_sequence, insn);
 }"
   [(set_attr "type" "branch")
-   (set (attr "length")
-        (if_then_else (lt (pc) (match_dup 2))
-		      (if_then_else (lt (minus (match_dup 2) (pc))
-					(const_int 32000))
-				    (const_int 1)
-				    (const_int 3))
-		      (if_then_else (lt (minus (pc) (match_dup 2))
-					(const_int 32000))
-				    (const_int 1)
-				    (const_int 3))))])
+   (set_attr "branch_type" "reg")])
 
 ;; Load program counter insns.
 
@@ -6473,7 +6456,7 @@
   [(set_attr "type" "multi")
    (set (attr "length")
 	(if_then_else (eq_attr "isa" "v9")
-		      (const_int 4) (const_int 7)))])
+		      (const_int 4) (const_int 6)))])
 
 (define_insn "divsi3_sp64"
   [(set (match_operand:SI 0 "register_operand" "=r")
@@ -8499,7 +8482,7 @@
   "! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 0"
   "call\\t%a0, %1\\n\\tnop\\n\\tunimp\\t%2"
   [(set_attr "type" "call_no_delay_slot")
-   (set_attr "length" "2")])
+   (set_attr "length" "3")])
 
 ;; This is a call that wants a structure value.
 ;; There is no such critter for v9 (??? we may need one anyway).
@@ -8512,7 +8495,7 @@
   "! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 0"
   "call\\t%a0, %1\\n\\tnop\\n\\tunimp\\t%2"
   [(set_attr "type" "call_no_delay_slot")
-   (set_attr "length" "2")])
+   (set_attr "length" "3")])
 
 ;; This is a call that may want a structure value.  This is used for
 ;; untyped_calls.
@@ -8525,7 +8508,7 @@
   "! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0"
   "call\\t%a0, %1\\n\\tnop\\n\\tnop"
   [(set_attr "type" "call_no_delay_slot")
-   (set_attr "length" "2")])
+   (set_attr "length" "3")])
 
 ;; This is a call that wants a structure value.
 (define_insn "*call_symbolic_untyped_struct_value_sp32"
@@ -8537,7 +8520,7 @@
   "! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0"
   "call\\t%a0, %1\\n\\tnop\\n\\tnop"
   [(set_attr "type" "call_no_delay_slot")
-   (set_attr "length" "2")])
+   (set_attr "length" "3")])
 
 (define_expand "call_value"
   ;; Note that this expression is not used for generating RTL.
--- gcc/config/sparc/sparc.c.jj	Wed Mar 27 11:48:55 2002
+++ gcc/config/sparc/sparc.c	Wed Mar 27 13:39:05 2002
@@ -2459,6 +2459,26 @@ leaf_return_peephole_ok ()
   return (actual_fsize == 0);
 }
 
+/* Return nonzero if a branch/jump/call instruction will be emitting
+   nop into its delay slot.  */
+
+int
+empty_delay_slot (insn)
+     rtx insn;
+{
+  rtx seq;
+
+  /* If no previous instruction (should not happen), return true.  */
+  if (PREV_INSN (insn) == NULL)
+    return 1;
+
+  seq = NEXT_INSN (PREV_INSN (insn));
+  if (GET_CODE (PATTERN (seq)) == SEQUENCE)
+    return 0;
+
+  return 1;
+}
+
 /* Return nonzero if TRIAL can go into the function epilogue's
    delay slot.  SLOT is the slot we are trying to fill.  */
 
--- gcc/config/sparc/sparc.h.jj	Wed Mar 27 11:51:21 2002
+++ gcc/config/sparc/sparc.h	Wed Mar 27 14:10:49 2002
@@ -2666,14 +2666,6 @@ do {                                    
   case FLOAT:						\
   case FIX:						\
     return 19;
-
-/* Conditional branches with empty delay slots have a length of two.  */
-#define ADJUST_INSN_LENGTH(INSN, LENGTH)				\
-do {									\
-  if (GET_CODE (INSN) == CALL_INSN					\
-      || (GET_CODE (INSN) == JUMP_INSN && ! simplejump_p (insn)))	\
-    LENGTH += 1;							\
-} while (0)
 
 /* Control the assembler format that we output.  */
 
--- gcc/config/sparc/sparc-protos.h.jj	Tue Mar 26 17:54:47 2002
+++ gcc/config/sparc/sparc-protos.h	Wed Mar 27 14:11:23 2002
@@ -99,6 +99,7 @@ extern int arith_4096_operand PARAMS ((r
 extern int zero_operand PARAMS ((rtx, enum machine_mode));
 extern int fp_zero_operand PARAMS ((rtx, enum machine_mode));
 extern int reg_or_0_operand PARAMS ((rtx, enum machine_mode));
+extern int empty_delay_slot PARAMS ((rtx));
 extern int eligible_for_epilogue_delay PARAMS ((rtx, int));
 extern int eligible_for_return_delay PARAMS ((rtx));
 extern int eligible_for_sibcall_delay PARAMS ((rtx));
--- gcc/testsuite/g++.dg/opt/longbranch1.C.jj	Wed Mar 27 14:17:43 2002
+++ gcc/testsuite/g++.dg/opt/longbranch1.C	Wed Mar 27 14:17:40 2002
@@ -0,0 +1,36 @@
+// PR c++/5964
+// This testcase failed to link on sparc -m64 -O0, because instruction
+// lengths were incorrectly computed
+// { dg-do link }
+// { dg-options "-O0" }
+
+#define makecode for (int i = 1; i < 1000; ++i) i *= 3
+#define muchcode \
+        makecode; makecode; makecode; makecode; makecode; makecode; \
+        makecode; makecode; makecode; makecode; makecode; makecode; \
+        makecode; makecode; makecode; makecode; makecode; makecode; \
+        makecode; makecode; makecode; makecode; makecode; makecode
+
+#define verymuchcode \
+        muchcode; muchcode; muchcode; muchcode; muchcode; muchcode; \
+        muchcode; muchcode; muchcode; muchcode; muchcode; muchcode; \
+        muchcode; muchcode; muchcode; muchcode; muchcode; muchcode; \
+        muchcode; muchcode; muchcode; muchcode; muchcode; muchcode; \
+        muchcode; muchcode; muchcode; muchcode; muchcode; muchcode; \
+        muchcode; muchcode; muchcode; muchcode; muchcode; muchcode; \
+        muchcode; muchcode; muchcode; muchcode; muchcode; muchcode; \
+        muchcode; muchcode; muchcode; muchcode; muchcode; muchcode; \
+        muchcode; muchcode; muchcode; muchcode; muchcode; muchcode; \
+        muchcode; muchcode; muchcode; muchcode; muchcode; muchcode; \
+        muchcode; muchcode; muchcode; muchcode; muchcode; muchcode; \
+        muchcode; muchcode; muchcode; muchcode; muchcode; muchcode; \
+        muchcode; muchcode; muchcode; muchcode; muchcode; muchcode
+
+int
+main (int argc, char **argv)
+{
+loop:
+  verymuchcode;
+  delete[] argv;
+  goto loop;
+}

	Jakub


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