]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR target/38287 (segfault at -O2 -fPIC -mcpu=v8)
authorEric Botcazou <ebotcazou@adacore.com>
Sun, 30 Nov 2008 19:23:38 +0000 (19:23 +0000)
committerEric Botcazou <ebotcazou@gcc.gnu.org>
Sun, 30 Nov 2008 19:23:38 +0000 (19:23 +0000)
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

gcc/ChangeLog
gcc/config/sparc/sparc.md

index 92d7768ead4511e103f7754773a20c8ecb6501ba..f1e0cf2d6b6e80153819d2c170b31f38f4b43ccd 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-06-05  Richard Sandiford  <rdsandiford@googlemail.com>
 
        * config/mips/mips.c (mips_emit_loadgp): Emit a blockage if
index db0348888b0be4f3e7d62e796b044653f8b3f413..a4002e304e7db120f89aa29c6605fb8d446d23f5 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")