]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR target/60071 ([SH] internal compiler error: in final_scan_insn, at final.c...
authorOleg Endo <olegendo@gcc.gnu.org>
Sat, 1 Mar 2014 13:16:37 +0000 (13:16 +0000)
committerOleg Endo <olegendo@gcc.gnu.org>
Sat, 1 Mar 2014 13:16:37 +0000 (13:16 +0000)
PR target/60071
* config/sh/sh.md (*mov_t_msb_neg): Split into ...
(*mov_t_msb_neg_negc): ... this new insn.

PR target/60071
* gcc.c-torture/compile/pr60071.c: New.

From-SVN: r208242

gcc/ChangeLog
gcc/config/sh/sh.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/compile/pr60071.c [new file with mode: 0644]

index 56da66051d2d5c637338610e3c0ed162e3276c15..c7936eafaed774801e12f31fc59a835fed8a0691 100644 (file)
@@ -1,3 +1,9 @@
+2014-03-01  Oleg Endo  <olegendo@gcc.gnu.org>
+
+       PR target/60071
+       * config/sh/sh.md (*mov_t_msb_neg): Split into ...
+       (*mov_t_msb_neg_negc): ... this new insn.
+
 2014-02-28  Jason Merrill  <jason@redhat.com>
 
        PR c++/58678
index 410e9689db4e9ea0b88d9f7e893ea70394ef259f..76af3a2e18b7e515c518a0cf898da6258b017aaa 100644 (file)
@@ -11434,6 +11434,10 @@ label:
 ;;     T = 1: 0x80000000 -> reg
 ;;     T = 0: 0x7FFFFFFF -> reg
 ;; This works because 0 - 0x80000000 = 0x80000000.
+;;
+;; This insn must not match again after it has been split into the constant
+;; load and negc.  This is accomplished by the special negc insn that
+;; has a use on the operand.
 (define_insn_and_split "*mov_t_msb_neg"
   [(set (match_operand:SI 0 "arith_reg_dest")
        (minus:SI (const_int -2147483648)  ;; 0x80000000
@@ -11444,12 +11448,23 @@ label:
   "&& can_create_pseudo_p ()"
   [(set (match_dup 2) (const_int -2147483648))
    (parallel [(set (match_dup 0) (minus:SI (neg:SI (match_dup 2))
-                                (reg:SI T_REG)))
-             (clobber (reg:SI T_REG))])]
+                                          (reg:SI T_REG)))
+             (clobber (reg:SI T_REG))
+             (use (match_dup 2))])]
 {
   operands[2] = gen_reg_rtx (SImode);
 })
 
+(define_insn "*mov_t_msb_neg_negc"
+  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
+       (minus:SI (neg:SI (match_operand:SI 1 "arith_reg_operand" "r"))
+                 (match_operand:SI 2 "t_reg_operand")))
+   (clobber (reg:SI T_REG))
+   (use (match_dup 1))]
+  "TARGET_SH1"
+  "negc        %1,%0"
+  [(set_attr "type" "arith")])
+
 ;; These are essentially the same as above, but with the inverted T bit.
 ;; Combine recognizes the split patterns, but does not take them sometimes
 ;; if the T_REG clobber is specified.  Instead it tries to split out the
index 5a831bfdd5cc5cfc73c7b82291805bd48bab0c4a..d7ef999776da59dd1c18f9a6eac1652b27f54645 100644 (file)
@@ -1,3 +1,8 @@
+2014-03-01  Oleg Endo  <olegendo@gcc.gnu.org>
+
+       PR target/60071
+       * gcc.c-torture/compile/pr60071.c: New.
+
 2014-02-28  Janus Weil  <janus@gcc.gnu.org>
 
        PR fortran/60359
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr60071.c b/gcc/testsuite/gcc.c-torture/compile/pr60071.c
new file mode 100644 (file)
index 0000000..8bc2c1f
--- /dev/null
@@ -0,0 +1,8 @@
+int
+foo (int cls, int sign)
+{
+  if (__builtin_expect (cls == 4, 0))
+    return (sign
+            ? (-((int) ((~(unsigned)0) >> 1)))-1
+            : ((int) ((~(unsigned)0) >> 1)));
+}