]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR c++/5964 (g++ generates code that results in "word displacement will not fit...
authorJakub Jelinek <jakub@redhat.com>
Fri, 29 Mar 2002 08:25:10 +0000 (09:25 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Fri, 29 Mar 2002 08:25:10 +0000 (09:25 +0100)
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.

From-SVN: r51557

gcc/ChangeLog
gcc/config/sparc/sparc-protos.h
gcc/config/sparc/sparc.c
gcc/config/sparc/sparc.h
gcc/config/sparc/sparc.md
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/opt/longbranch1.C [new file with mode: 0644]

index 48a7dcf7aa3caca807338794dc11445bb078bd2d..effce5242f713c1290e800773d1ca218f0ff3f0b 100644 (file)
@@ -1,3 +1,20 @@
+2002-03-29  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.
+
 2002-03-29  Jakub Jelinek  <jakub@redhat.com>
 
        * combine.c (set_nonzero_bits_and_sign_copies): Don't call
index 269844eff7291e19a2cf4388344c87a40d113319..d7433d49037235118d981355d90b68c4625fbff7 100644 (file)
@@ -99,6 +99,7 @@ extern int arith_4096_operand PARAMS ((rtx, enum machine_mode));
 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));
index f6de9c5896d955256abb6f5cc61e0566faf1c937..a6a99c74ba31d6efa8979c2fbd49fb48876da1d9 100644 (file)
@@ -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.  */
 
index 9fed03ca1ea4f1390c5c72c338a30272f337b5fe..e8b9cc38796c741c89f4eef3adad083d3ee79381 100644 (file)
@@ -2654,14 +2654,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)
 \f
 /* Control the assembler format that we output.  */
 
index e1810f66a5c58791b8449980c40febdd14592035..a7769e327645be23cb541cb3ba6719d262ff7fb5 100644 (file)
   "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"))
                         ! 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"
                         ! 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"
                         ! 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"
                         ! 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"
                         ! 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"
                         ! 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.
                          ! 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"
                          ! 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")])
 \f
 ;; Load program counter insns.
 
   [(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")
   "! 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).
   "! 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.
   "! 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"
   "! 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.
index 7f68789c12224b0665d6af665af8ce55ab0fff6e..fec72b83aa3c10380ae69e9294acf48178c7aab8 100644 (file)
@@ -2,6 +2,8 @@
 
        * g++.dg/opt/static1.C: New test.
 
+       * g++.dg/opt/longbranch1.C: New test.
+
 2002-03-28  Hans-Peter Nilsson  <hp@bitrange.com>
 
        * gcc.dg/weak-1.c: Fix typo in scan-assembler pattern.
diff --git a/gcc/testsuite/g++.dg/opt/longbranch1.C b/gcc/testsuite/g++.dg/opt/longbranch1.C
new file mode 100644 (file)
index 0000000..a64a57a
--- /dev/null
@@ -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;
+}