diff options
author | Eric Botcazou <ebotcazou@adacore.com> | 2008-11-30 19:19:06 +0000 |
---|---|---|
committer | Eric Botcazou <ebotcazou@gcc.gnu.org> | 2008-11-30 19:19:06 +0000 |
commit | 72b415c58668d3bd757fb8ec3be70302c339d544 (patch) | |
tree | 33022bd1a0dd08243666dacc662f7541d956d15e /gcc/config/sparc | |
parent | 07c9463afe8ebcb06ac6071305ff893520e30239 (diff) | |
download | gcc-72b415c58668d3bd757fb8ec3be70302c339d544.zip gcc-72b415c58668d3bd757fb8ec3be70302c339d544.tar.gz gcc-72b415c58668d3bd757fb8ec3be70302c339d544.tar.bz2 |
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: r142295
Diffstat (limited to 'gcc/config/sparc')
-rw-r--r-- | gcc/config/sparc/sparc.md | 122 |
1 files changed, 79 insertions, 43 deletions
diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md index 7dadde2..0a82e89 100644 --- a/gcc/config/sparc/sparc.md +++ b/gcc/config/sparc/sparc.md @@ -4895,14 +4895,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) @@ -4915,24 +4912,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") @@ -4967,10 +4980,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") @@ -4985,29 +5001,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") @@ -5033,13 +5068,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") |