This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix PR c++/5964
- From: Jakub Jelinek <jakub at redhat dot com>
- To: Richard Henderson <rth at redhat dot com>, Robert Schiele <rschiele at uni-mannheim dot de>, Brad Lucier <lucier at math dot purdue dot edu>
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Wed, 27 Mar 2002 14:45:43 +0100
- Subject: [PATCH] Fix PR c++/5964
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
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