From: Eric Botcazou Date: Sun, 30 Nov 2008 19:23:38 +0000 (+0000) Subject: re PR target/38287 (segfault at -O2 -fPIC -mcpu=v8) X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=76c5e4bca2855f289206c436dbdfd00b1e3b172d;p=thirdparty%2Fgcc.git re PR target/38287 (segfault at -O2 -fPIC -mcpu=v8) PR target/38287 * config/sparc/sparc.md (divsi3 expander): Remove constraints. (divsi3_sp32): Add new alternative with 'K' for operand #2. (cmp_sdiv_cc_set): Factor common string. (udivsi3_sp32): Add new alternative with 'K' for operand #2. Add TARGET_V9 case. (cmp_udiv_cc_set): Factor common string. From-SVN: r142298 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 92d7768ead45..f1e0cf2d6b6e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2008-11-30 Eric Botcazou + + PR target/38287 + * config/sparc/sparc.md (divsi3 expander): Remove constraints. + (divsi3_sp32): Add new alternative with 'K' for operand #2. + (cmp_sdiv_cc_set): Factor common string. + (udivsi3_sp32): Add new alternative with 'K' for operand #2. + Add TARGET_V9 case. + (cmp_udiv_cc_set): Factor common string. + 2008-06-05 Richard Sandiford * config/mips/mips.c (mips_emit_loadgp): Emit a blockage if diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md index db0348888b0b..a4002e304e7d 100644 --- a/gcc/config/sparc/sparc.md +++ b/gcc/config/sparc/sparc.md @@ -5074,14 +5074,11 @@ [(set_attr "type" "multi") (set_attr "length" "2")]) -;; The V8 architecture specifies that there must be 3 instructions between -;; a Y register write and a use of it for correct results. - (define_expand "divsi3" - [(parallel [(set (match_operand:SI 0 "register_operand" "=r,r") - (div:SI (match_operand:SI 1 "register_operand" "r,r") - (match_operand:SI 2 "input_operand" "rI,m"))) - (clobber (match_scratch:SI 3 "=&r,&r"))])] + [(parallel [(set (match_operand:SI 0 "register_operand" "") + (div:SI (match_operand:SI 1 "register_operand" "") + (match_operand:SI 2 "input_operand" ""))) + (clobber (match_scratch:SI 3 ""))])] "TARGET_V8 || TARGET_DEPRECATED_V8_INSNS" { if (TARGET_ARCH64) @@ -5094,24 +5091,40 @@ } }) +;; The V8 architecture specifies that there must be at least 3 instructions +;; between a write to the Y register and a use of it for correct results. +;; We try to fill one of them with a simple constant or a memory load. + (define_insn "divsi3_sp32" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (div:SI (match_operand:SI 1 "register_operand" "r,r") - (match_operand:SI 2 "input_operand" "rI,m"))) - (clobber (match_scratch:SI 3 "=&r,&r"))] - "(TARGET_V8 || TARGET_DEPRECATED_V8_INSNS) - && TARGET_ARCH32" -{ - if (which_alternative == 0) - if (TARGET_V9) - return "sra\t%1, 31, %3\n\twr\t%3, 0, %%y\n\tsdiv\t%1, %2, %0"; - else - return "sra\t%1, 31, %3\n\twr\t%3, 0, %%y\n\tnop\n\tnop\n\tnop\n\tsdiv\t%1, %2, %0"; - else - if (TARGET_V9) - return "sra\t%1, 31, %3\n\twr\t%3, 0, %%y\n\tld\t%2, %3\n\tsdiv\t%1, %3, %0"; - else - return "sra\t%1, 31, %3\n\twr\t%3, 0, %%y\n\tld\t%2, %3\n\tnop\n\tnop\n\tsdiv\t%1, %3, %0"; + [(set (match_operand:SI 0 "register_operand" "=r,r,r") + (div:SI (match_operand:SI 1 "register_operand" "r,r,r") + (match_operand:SI 2 "input_operand" "rI,K,m"))) + (clobber (match_scratch:SI 3 "=&r,&r,&r"))] + "(TARGET_V8 || TARGET_DEPRECATED_V8_INSNS) && TARGET_ARCH32" +{ + output_asm_insn ("sra\t%1, 31, %3", operands); + output_asm_insn ("wr\t%3, 0, %%y", operands); + + switch (which_alternative) + { + case 0: + if (TARGET_V9) + return "sdiv\t%1, %2, %0"; + else + return "nop\n\tnop\n\tnop\n\tsdiv\t%1, %2, %0"; + case 1: + if (TARGET_V9) + return "sethi\t%%hi(%a2), %3\n\tsdiv\t%1, %3, %0"; + else + return "sethi\t%%hi(%a2), %3\n\tnop\n\tnop\n\tsdiv\t%1, %3, %0"; + case 2: + if (TARGET_V9) + return "ld\t%2, %3\n\tsdiv\t%1, %3, %0"; + else + return "ld\t%2, %3\n\tnop\n\tnop\n\tsdiv\t%1, %3, %0"; + default: + gcc_unreachable (); + } } [(set_attr "type" "multi") (set (attr "length") @@ -5146,10 +5159,13 @@ (clobber (match_scratch:SI 3 "=&r"))] "TARGET_V8 || TARGET_DEPRECATED_V8_INSNS" { + output_asm_insn ("sra\t%1, 31, %3", operands); + output_asm_insn ("wr\t%3, 0, %%y", operands); + if (TARGET_V9) - return "sra\t%1, 31, %3\n\twr\t%3, 0, %%y\n\tsdivcc\t%1, %2, %0"; + return "sdivcc\t%1, %2, %0"; else - return "sra\t%1, 31, %3\n\twr\t%3, 0, %%y\n\tnop\n\tnop\n\tnop\n\tsdivcc\t%1, %2, %0"; + return "nop\n\tnop\n\tnop\n\tsdivcc\t%1, %2, %0"; } [(set_attr "type" "multi") (set (attr "length") @@ -5164,29 +5180,48 @@ "TARGET_V8 || TARGET_DEPRECATED_V8_INSNS" "") -;; The V8 architecture specifies that there must be 3 instructions between -;; a Y register write and a use of it for correct results. +;; The V8 architecture specifies that there must be at least 3 instructions +;; between a write to the Y register and a use of it for correct results. +;; We try to fill one of them with a simple constant or a memory load. (define_insn "udivsi3_sp32" - [(set (match_operand:SI 0 "register_operand" "=r,&r,&r") - (udiv:SI (match_operand:SI 1 "nonimmediate_operand" "r,r,m") - (match_operand:SI 2 "input_operand" "rI,m,r")))] - "(TARGET_V8 || TARGET_DEPRECATED_V8_INSNS) - && TARGET_ARCH32" + [(set (match_operand:SI 0 "register_operand" "=r,&r,&r,&r") + (udiv:SI (match_operand:SI 1 "nonimmediate_operand" "r,r,r,m") + (match_operand:SI 2 "input_operand" "rI,K,m,r")))] + "(TARGET_V8 || TARGET_DEPRECATED_V8_INSNS) && TARGET_ARCH32" { - output_asm_insn ("wr\t%%g0, %%g0, %%y", operands); + output_asm_insn ("wr\t%%g0, 0, %%y", operands); + switch (which_alternative) { - default: - return "nop\n\tnop\n\tnop\n\tudiv\t%1, %2, %0"; + case 0: + if (TARGET_V9) + return "udiv\t%1, %2, %0"; + else + return "nop\n\tnop\n\tnop\n\tudiv\t%1, %2, %0"; case 1: - return "ld\t%2, %0\n\tnop\n\tnop\n\tudiv\t%1, %0, %0"; + if (TARGET_V9) + return "sethi\t%%hi(%a2), %0\n\tudiv\t%1, %0, %0"; + else + return "sethi\t%%hi(%a2), %0\n\tnop\n\tnop\n\tudiv\t%1, %0, %0"; case 2: - return "ld\t%1, %0\n\tnop\n\tnop\n\tudiv\t%0, %2, %0"; + if (TARGET_V9) + return "ld\t%2, %0\n\tudiv\t%1, %0, %0"; + else + return "ld\t%2, %0\n\tnop\n\tnop\n\tudiv\t%1, %0, %0"; + case 3: + if (TARGET_V9) + return "ld\t%1, %0\n\tudiv\t%0, %2, %0"; + else + return "ld\t%1, %0\n\tnop\n\tnop\n\tudiv\t%0, %2, %0"; + default: + gcc_unreachable (); } } [(set_attr "type" "multi") - (set_attr "length" "5")]) + (set (attr "length") + (if_then_else (eq_attr "isa" "v9") + (const_int 3) (const_int 5)))]) (define_insn "udivsi3_sp64" [(set (match_operand:SI 0 "register_operand" "=r") @@ -5212,13 +5247,14 @@ (const_int 0))) (set (match_operand:SI 0 "register_operand" "=r") (udiv:SI (match_dup 1) (match_dup 2)))] - "TARGET_V8 - || TARGET_DEPRECATED_V8_INSNS" + "TARGET_V8 || TARGET_DEPRECATED_V8_INSNS" { + output_asm_insn ("wr\t%%g0, 0, %%y", operands); + if (TARGET_V9) - return "wr\t%%g0, %%g0, %%y\n\tudivcc\t%1, %2, %0"; + return "udivcc\t%1, %2, %0"; else - return "wr\t%%g0, %%g0, %%y\n\tnop\n\tnop\n\tnop\n\tudivcc\t%1, %2, %0"; + return "nop\n\tnop\n\tnop\n\tudivcc\t%1, %2, %0"; } [(set_attr "type" "multi") (set (attr "length")