aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/sparc
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@adacore.com>2008-11-30 19:19:06 +0000
committerEric Botcazou <ebotcazou@gcc.gnu.org>2008-11-30 19:19:06 +0000
commit72b415c58668d3bd757fb8ec3be70302c339d544 (patch)
tree33022bd1a0dd08243666dacc662f7541d956d15e /gcc/config/sparc
parent07c9463afe8ebcb06ac6071305ff893520e30239 (diff)
downloadgcc-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.md122
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")