PR target/38287
authorebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 30 Nov 2008 19:19:06 +0000 (19:19 +0000)
committerebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 30 Nov 2008 19:19:06 +0000 (19:19 +0000)
* 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

gcc/ChangeLog
gcc/config/sparc/sparc.md
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/opt/reload3.C [new file with mode: 0644]

index ea9a94e..5602b5a 100644 (file)
@@ -1,3 +1,13 @@
+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>
 
        PR middle-end/38283
index 7dadde2..0a82e89 100644 (file)
   [(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)
     }
 })
 
+;; 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")
    (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")
   "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")
                    (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")
index fa68f2e..cd0d6c4 100644 (file)
@@ -1,3 +1,7 @@
+2008-11-30  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * g++.dg/opt/reload3.C: New test.
+
 2008-11-30  Paul Thomas  <pault@gcc.gnu.org>
 
        PR fortran/35824
diff --git a/gcc/testsuite/g++.dg/opt/reload3.C b/gcc/testsuite/g++.dg/opt/reload3.C
new file mode 100644 (file)
index 0000000..12f3e66
--- /dev/null
@@ -0,0 +1,39 @@
+// 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;
+}