From: Jakub Jelinek Date: Fri, 29 Mar 2002 08:25:10 +0000 (+0100) Subject: re PR c++/5964 (g++ generates code that results in "word displacement will not fit... X-Git-Tag: releases/gcc-3.3.0~6043 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=f17f93326d7d690113c87abf1532bd9f4be8301f;p=thirdparty%2Fgcc.git re PR c++/5964 (g++ generates code that results in "word displacement will not fit in 16 bits" on sparcv9) 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 48a7dcf7aa3c..effce5242f71 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,20 @@ +2002-03-29 Jakub Jelinek + + 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 * combine.c (set_nonzero_bits_and_sign_copies): Don't call diff --git a/gcc/config/sparc/sparc-protos.h b/gcc/config/sparc/sparc-protos.h index 269844eff729..d7433d490372 100644 --- a/gcc/config/sparc/sparc-protos.h +++ b/gcc/config/sparc/sparc-protos.h @@ -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)); diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c index f6de9c5896d9..a6a99c74ba31 100644 --- a/gcc/config/sparc/sparc.c +++ b/gcc/config/sparc/sparc.c @@ -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. */ diff --git a/gcc/config/sparc/sparc.h b/gcc/config/sparc/sparc.h index 9fed03ca1ea4..e8b9cc38796c 100644 --- a/gcc/config/sparc/sparc.h +++ b/gcc/config/sparc/sparc.h @@ -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) /* Control the assembler format that we output. */ diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md index e1810f66a5c5..a7769e327645 100644 --- a/gcc/config/sparc/sparc.md +++ b/gcc/config/sparc/sparc.md @@ -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. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 7f68789c1222..fec72b83aa3c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -2,6 +2,8 @@ * g++.dg/opt/static1.C: New test. + * g++.dg/opt/longbranch1.C: New test. + 2002-03-28 Hans-Peter Nilsson * 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 index 000000000000..a64a57aea2ad --- /dev/null +++ b/gcc/testsuite/g++.dg/opt/longbranch1.C @@ -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; +}