Commit 0e517585 authored by ebotcazou's avatar ebotcazou
Browse files

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.


git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@142295 138bc75d-0d04-0410-961f-82ee72b054a4
parent 1f6a423f
2008-11-30 Eric Botcazou <ebotcazou@adacore.com>
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-11-30 John David Anglin <dave.anglin@nrc-cnrc.gc.ca> 2008-11-30 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
   
PR middle-end/38283 PR middle-end/38283
...@@ -4895,14 +4895,11 @@ ...@@ -4895,14 +4895,11 @@
[(set_attr "type" "multi") [(set_attr "type" "multi")
(set_attr "length" "2")]) (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" (define_expand "divsi3"
[(parallel [(set (match_operand:SI 0 "register_operand" "=r,r") [(parallel [(set (match_operand:SI 0 "register_operand" "")
(div:SI (match_operand:SI 1 "register_operand" "r,r") (div:SI (match_operand:SI 1 "register_operand" "")
(match_operand:SI 2 "input_operand" "rI,m"))) (match_operand:SI 2 "input_operand" "")))
(clobber (match_scratch:SI 3 "=&r,&r"))])] (clobber (match_scratch:SI 3 ""))])]
"TARGET_V8 || TARGET_DEPRECATED_V8_INSNS" "TARGET_V8 || TARGET_DEPRECATED_V8_INSNS"
{ {
if (TARGET_ARCH64) if (TARGET_ARCH64)
...@@ -4915,24 +4912,40 @@ ...@@ -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" (define_insn "divsi3_sp32"
[(set (match_operand:SI 0 "register_operand" "=r,r") [(set (match_operand:SI 0 "register_operand" "=r,r,r")
(div:SI (match_operand:SI 1 "register_operand" "r,r") (div:SI (match_operand:SI 1 "register_operand" "r,r,r")
(match_operand:SI 2 "input_operand" "rI,m"))) (match_operand:SI 2 "input_operand" "rI,K,m")))
(clobber (match_scratch:SI 3 "=&r,&r"))] (clobber (match_scratch:SI 3 "=&r,&r,&r"))]
"(TARGET_V8 || TARGET_DEPRECATED_V8_INSNS) "(TARGET_V8 || TARGET_DEPRECATED_V8_INSNS) && TARGET_ARCH32"
&& TARGET_ARCH32" {
{ output_asm_insn ("sra\t%1, 31, %3", operands);
if (which_alternative == 0) 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\tsdiv\t%1, %2, %0"; switch (which_alternative)
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"; case 0:
else if (TARGET_V9)
if (TARGET_V9) return "sdiv\t%1, %2, %0";
return "sra\t%1, 31, %3\n\twr\t%3, 0, %%y\n\tld\t%2, %3\n\tsdiv\t%1, %3, %0"; else
else return "nop\n\tnop\n\tnop\n\tsdiv\t%1, %2, %0";
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"; 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 "type" "multi")
(set (attr "length") (set (attr "length")
...@@ -4967,10 +4980,13 @@ ...@@ -4967,10 +4980,13 @@
(clobber (match_scratch:SI 3 "=&r"))] (clobber (match_scratch:SI 3 "=&r"))]
"TARGET_V8 || TARGET_DEPRECATED_V8_INSNS" "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) 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 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 "type" "multi")
(set (attr "length") (set (attr "length")
...@@ -4985,29 +5001,48 @@ ...@@ -4985,29 +5001,48 @@
"TARGET_V8 || TARGET_DEPRECATED_V8_INSNS" "TARGET_V8 || TARGET_DEPRECATED_V8_INSNS"
"") "")
;; The V8 architecture specifies that there must be 3 instructions between ;; The V8 architecture specifies that there must be at least 3 instructions
;; a Y register write and a use of it for correct results. ;; 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" (define_insn "udivsi3_sp32"
[(set (match_operand:SI 0 "register_operand" "=r,&r,&r") [(set (match_operand:SI 0 "register_operand" "=r,&r,&r,&r")
(udiv:SI (match_operand:SI 1 "nonimmediate_operand" "r,r,m") (udiv:SI (match_operand:SI 1 "nonimmediate_operand" "r,r,r,m")
(match_operand:SI 2 "input_operand" "rI,m,r")))] (match_operand:SI 2 "input_operand" "rI,K,m,r")))]
"(TARGET_V8 || TARGET_DEPRECATED_V8_INSNS) "(TARGET_V8 || TARGET_DEPRECATED_V8_INSNS) && TARGET_ARCH32"
&& TARGET_ARCH32"
{ {
output_asm_insn ("wr\t%%g0, %%g0, %%y", operands); output_asm_insn ("wr\t%%g0, 0, %%y", operands);
switch (which_alternative) switch (which_alternative)
{ {
default: case 0:
return "nop\n\tnop\n\tnop\n\tudiv\t%1, %2, %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: 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: 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 "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" (define_insn "udivsi3_sp64"
[(set (match_operand:SI 0 "register_operand" "=r") [(set (match_operand:SI 0 "register_operand" "=r")
...@@ -5033,13 +5068,14 @@ ...@@ -5033,13 +5068,14 @@
(const_int 0))) (const_int 0)))
(set (match_operand:SI 0 "register_operand" "=r") (set (match_operand:SI 0 "register_operand" "=r")
(udiv:SI (match_dup 1) (match_dup 2)))] (udiv:SI (match_dup 1) (match_dup 2)))]
"TARGET_V8 "TARGET_V8 || TARGET_DEPRECATED_V8_INSNS"
|| TARGET_DEPRECATED_V8_INSNS"
{ {
output_asm_insn ("wr\t%%g0, 0, %%y", operands);
if (TARGET_V9) if (TARGET_V9)
return "wr\t%%g0, %%g0, %%y\n\tudivcc\t%1, %2, %0"; return "udivcc\t%1, %2, %0";
else 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 "type" "multi")
(set (attr "length") (set (attr "length")
......
2008-11-30 Eric Botcazou <ebotcazou@adacore.com>
* g++.dg/opt/reload3.C: New test.
2008-11-30 Paul Thomas <pault@gcc.gnu.org> 2008-11-30 Paul Thomas <pault@gcc.gnu.org>
PR fortran/35824 PR fortran/35824
......
// PR target/38287
// { dg-do run }
// { dg-options "-O2 -mcpu=v8 -fPIC" { target { { sparc*-*-* } && { ilp32 && fpic } } } }
#include <cstdlib>
class QTime
{
public:
explicit QTime(int ms = 0) : ds(ms) {}
static QTime currentTime() { return QTime(); }
QTime addMSecs(int ms) const;
int msecs() const { return ds; }
private:
unsigned ds;
};
static const unsigned MSECS_PER_DAY = 86400000;
QTime QTime::addMSecs(int ms) const
{
QTime t;
if ( ms < 0 ) {
// % not well-defined for -ve, but / is.
int negdays = (MSECS_PER_DAY-ms) / MSECS_PER_DAY;
t.ds = ((int)ds + ms + negdays*MSECS_PER_DAY)
% MSECS_PER_DAY;
} else {
t.ds = ((int)ds + ms) % MSECS_PER_DAY;
}
return t;
}
int main()
{
if (QTime(1).addMSecs(1).msecs() != 2)
abort ();
return 0;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment