re PR target/64180 (PowerPC carry bit improvements)
authorSegher Boessenkool <segher@kernel.crashing.org>
Wed, 10 Dec 2014 18:37:58 +0000 (19:37 +0100)
committerSegher Boessenkool <segher@gcc.gnu.org>
Wed, 10 Dec 2014 18:37:58 +0000 (19:37 +0100)
PR target/64180
* config/rs6000/predicates.md (unsigned_comparison_operator): New.
(signed_comparison_operator): New.
* config/rs6000/rs6000-protos.h (rs6000_emit_eqne): Declare.
* config/rs6000/rs6000.c (rs6000_emit_eqne): New function.
(rs6000_emit_sCOND): Remove ISEL test (move it to the expander).
* config/rs6000/rs6000.md (add<mode>3 for SDI): Expand DImode
add to addc,adde directly, if !TARGET_POWERPC64.
(sub<mode>3 for SDI): Expand DImode sub to subfc,subfe directly,
if !TARGET_POWERPC64.
(neg<mode>2): Delete expander.
(*neg<mode>2): Rename to "neg<mode>2".
(addti3, subti3): Delete.
(addti3, subti3): New expanders.
(*adddi3_noppc64, *subdi3_noppc64, *negdi2_noppc64): Delete.
(cstore<mode>4_unsigned): New expander.
(cstore<mode>4): Allow GPR as output (not just SI).  Rewrite.
(cstore<mode>4 for FP): Remove superfluous quotes.
(*eq<mode>, *eq<mode>_compare, *plus_eqsi and splitter,
*compare_plus_eqsi and splitter, *plus_eqsi_compare and splitter,
*neg_eq0<mode>, *neg_eq<mode>, *ne0_<mode>, plus_ne0_<mode>,
compare_plus_ne0_<mode> and splitter, *compare_plus_ne0_<mode>_1 and
splitter, *plus_ne0_<mode>_compare and splitter, *leu<mode>,
*leu<mode>_compare and splitter, *plus_leu<mode>, *neg_leu<mode>,
*and_neg_leu<mode>, *ltu<mode>, *ltu<mode>_compare, *plus_ltu<mode>,
*plus_ltu<mode>_1, *plus_ltu<mode>compare, *neg_ltu<mode>, *geu<mode>,
*geu<mode>_compare and splitter, *plus_geu<mode>, *neg_geu<mode>,
*and_neg_geu<mode>, *plus_gt0<mode>, *gtu<mode>, *gtu<mode>_compare,
*plus_gtu<mode>, *plus_gtu<mode>_1, *plus_gtu<mode>_compare,
*neg_gtu<mode>, 12 anonymous insns, and 12 anonymous splitters):
Delete.
(eq<mode>3, ne<mode>3): New.
(*neg_eq_<mode>, *neg_ne_<mode>): New.
(*plus_eq_<mode>, *plus_ne_<mode>): New.
(*minus_eq_<mode>, *minus_ne_<mode>): New.

From-SVN: r218595

gcc/ChangeLog
gcc/config/rs6000/predicates.md
gcc/config/rs6000/rs6000-protos.h
gcc/config/rs6000/rs6000.c
gcc/config/rs6000/rs6000.md

index f70d81646ed9e7b40fea37ca1c09bf6834053f01..ccca30945e90fac72d91d42482df37633db41b4b 100644 (file)
@@ -1,3 +1,41 @@
+2014-12-10  Segher Boessenkool  <segher@kernel.crashing.org>
+
+       PR target/64180
+       * config/rs6000/predicates.md (unsigned_comparison_operator): New.
+       (signed_comparison_operator): New.
+       * config/rs6000/rs6000-protos.h (rs6000_emit_eqne): Declare.
+       * config/rs6000/rs6000.c (rs6000_emit_eqne): New function.
+       (rs6000_emit_sCOND): Remove ISEL test (move it to the expander).
+       * config/rs6000/rs6000.md (add<mode>3 for SDI): Expand DImode
+       add to addc,adde directly, if !TARGET_POWERPC64.
+       (sub<mode>3 for SDI): Expand DImode sub to subfc,subfe directly,
+       if !TARGET_POWERPC64.
+       (neg<mode>2): Delete expander.
+       (*neg<mode>2): Rename to "neg<mode>2".
+       (addti3, subti3): Delete.
+       (addti3, subti3): New expanders.
+       (*adddi3_noppc64, *subdi3_noppc64, *negdi2_noppc64): Delete.
+       (cstore<mode>4_unsigned): New expander.
+       (cstore<mode>4): Allow GPR as output (not just SI).  Rewrite.
+       (cstore<mode>4 for FP): Remove superfluous quotes.
+       (*eq<mode>, *eq<mode>_compare, *plus_eqsi and splitter,
+       *compare_plus_eqsi and splitter, *plus_eqsi_compare and splitter,
+       *neg_eq0<mode>, *neg_eq<mode>, *ne0_<mode>, plus_ne0_<mode>,
+       compare_plus_ne0_<mode> and splitter, *compare_plus_ne0_<mode>_1 and
+       splitter, *plus_ne0_<mode>_compare and splitter, *leu<mode>,
+       *leu<mode>_compare and splitter, *plus_leu<mode>, *neg_leu<mode>,
+       *and_neg_leu<mode>, *ltu<mode>, *ltu<mode>_compare, *plus_ltu<mode>,
+       *plus_ltu<mode>_1, *plus_ltu<mode>compare, *neg_ltu<mode>, *geu<mode>,
+       *geu<mode>_compare and splitter, *plus_geu<mode>, *neg_geu<mode>,
+       *and_neg_geu<mode>, *plus_gt0<mode>, *gtu<mode>, *gtu<mode>_compare,
+       *plus_gtu<mode>, *plus_gtu<mode>_1, *plus_gtu<mode>_compare,
+       *neg_gtu<mode>, 12 anonymous insns, and 12 anonymous splitters):
+       Delete.
+       (eq<mode>3, ne<mode>3): New.
+       (*neg_eq_<mode>, *neg_ne_<mode>): New.
+       (*plus_eq_<mode>, *plus_ne_<mode>): New.
+       (*minus_eq_<mode>, *minus_ne_<mode>): New.
+
 2014-12-10  Segher Boessenkool  <segher@kernel.crashing.org>
 
        PR target/64180
index a19cb2fd39e468b37cf02ec10bc8880c92510a1b..8b68f9ce4649258b916502a83086eba61d0f367c 100644 (file)
                                   (match_code ("unlt,unle,ungt,unge"))))
                (match_operand 0 "comparison_operator")))
 
+;; Return 1 if OP is an unsigned comparison operator.
+(define_predicate "unsigned_comparison_operator"
+  (match_code "ltu,gtu,leu,geu"))
+
+;; Return 1 if OP is a signed comparison operator.
+(define_predicate "signed_comparison_operator"
+  (match_code "lt,gt,le,ge"))
+
 ;; Return 1 if OP is a comparison operation that is valid for an SCC insn --
 ;; it must be a positive comparison.
 (define_predicate "scc_comparison_operator"
index 8d27a6986eadb14abf7127f0f30419623121f683..eb64598352b95b8fcf7752d9f95b96b38b13fd24 100644 (file)
@@ -109,6 +109,7 @@ extern void print_operand (FILE *, rtx, int);
 extern void print_operand_address (FILE *, rtx);
 extern enum rtx_code rs6000_reverse_condition (machine_mode,
                                               enum rtx_code);
+extern rtx rs6000_emit_eqne (machine_mode, rtx, rtx, rtx);
 extern void rs6000_emit_sISEL (machine_mode, rtx[]);
 extern void rs6000_emit_sCOND (machine_mode, rtx[]);
 extern void rs6000_emit_cbranch (machine_mode, rtx[]);
index 1c2070bd3058828d465c4a25423ef8769b0795d2..fc81b79c23b39d0f40448102695822f332219beb 100644 (file)
@@ -19422,6 +19422,27 @@ rs6000_emit_sISEL (machine_mode mode ATTRIBUTE_UNUSED, rtx operands[])
   rs6000_emit_int_cmove (operands[0], operands[1], const1_rtx, const0_rtx);
 }
 
+/* Emit RTL that sets a register to zero if OP1 and OP2 are equal.  SCRATCH
+   can be used as that dest register.  Return the dest register.  */
+
+rtx
+rs6000_emit_eqne (machine_mode mode, rtx op1, rtx op2, rtx scratch)
+{
+  if (op2 == const0_rtx)
+    return op1;
+
+  if (GET_CODE (scratch) == SCRATCH)
+    scratch = gen_reg_rtx (mode);
+
+  if (logical_operand (op2, mode))
+    emit_insn (gen_rtx_SET (VOIDmode, scratch, gen_rtx_XOR (mode, op1, op2)));
+  else
+    emit_insn (gen_rtx_SET (VOIDmode, scratch,
+                           gen_rtx_PLUS (mode, op1, negate_rtx (mode, op2))));
+
+  return scratch;
+}
+
 void
 rs6000_emit_sCOND (machine_mode mode, rtx operands[])
 {
@@ -19430,12 +19451,6 @@ rs6000_emit_sCOND (machine_mode mode, rtx operands[])
   enum rtx_code cond_code;
   rtx result = operands[0];
 
-  if (TARGET_ISEL && (mode == SImode || mode == DImode))
-    {
-      rs6000_emit_sISEL (mode, operands);
-      return;
-    }
-
   condition_rtx = rs6000_generate_compare (operands[1], mode);
   cond_code = GET_CODE (condition_rtx);
 
index 733cc390f299b7b70a8506a8595d1e23c0de8f8d..233f7e67d5fa10c3af261e12ebdd4cf1e9c67a08 100644 (file)
                  (match_operand:SDI 2 "reg_or_add_cint_operand" "")))]
   ""
 {
-  if (<MODE>mode == DImode && ! TARGET_POWERPC64)
+  if (<MODE>mode == DImode && !TARGET_POWERPC64)
     {
-      if (non_short_cint_operand (operands[2], DImode))
-       FAIL;
+      rtx lo0 = gen_lowpart (SImode, operands[0]);
+      rtx lo1 = gen_lowpart (SImode, operands[1]);
+      rtx lo2 = gen_lowpart (SImode, operands[2]);
+      rtx hi0 = gen_highpart (SImode, operands[0]);
+      rtx hi1 = gen_highpart (SImode, operands[1]);
+      rtx hi2 = gen_highpart_mode (SImode, DImode, operands[2]);
+
+      if (!reg_or_short_operand (lo2, SImode))
+       lo2 = force_reg (SImode, lo2);
+      if (!adde_operand (hi2, SImode))
+       hi2 = force_reg (SImode, hi2);
+
+      emit_insn (gen_addsi3_carry (lo0, lo1, lo2));
+      emit_insn (gen_addsi3_carry_in (hi0, hi1, hi2));
+      DONE;
     }
-  else if (GET_CODE (operands[2]) == CONST_INT
-          && ! add_operand (operands[2], <MODE>mode))
+
+  if (CONST_INT_P (operands[2]) && !add_operand (operands[2], <MODE>mode))
     {
       rtx tmp = ((!can_create_pseudo_p ()
                  || rtx_equal_p (operands[0], operands[1]))
                   (match_operand:SDI 2 "gpc_reg_operand" "")))]
   ""
 {
-  if (short_cint_operand (operands[1], <MODE>mode)
-      && !(<MODE>mode == DImode && !TARGET_POWERPC64))
+  if (<MODE>mode == DImode && !TARGET_POWERPC64)
+    {
+      rtx lo0 = gen_lowpart (SImode, operands[0]);
+      rtx lo1 = gen_lowpart (SImode, operands[1]);
+      rtx lo2 = gen_lowpart (SImode, operands[2]);
+      rtx hi0 = gen_highpart (SImode, operands[0]);
+      rtx hi1 = gen_highpart_mode (SImode, DImode, operands[1]);
+      rtx hi2 = gen_highpart (SImode, operands[2]);
+
+      if (!reg_or_short_operand (lo1, SImode))
+       lo1 = force_reg (SImode, lo1);
+      if (!adde_operand (hi1, SImode))
+       hi1 = force_reg (SImode, hi1);
+
+      emit_insn (gen_subfsi3_carry (lo0, lo2, lo1));
+      emit_insn (gen_subfsi3_carry_in (hi0, hi2, hi1));
+      DONE;
+    }
+
+  if (short_cint_operand (operands[1], <MODE>mode))
     {
       emit_insn (gen_subf<mode>3_imm (operands[0], operands[2], operands[1]));
       DONE;
   [(set_attr "type" "add")])
 
 
-(define_expand "neg<mode>2"
-  [(set (match_operand:SDI 0 "gpc_reg_operand" "")
-       (neg:SDI (match_operand:SDI 1 "gpc_reg_operand" "")))]
-  ""
-  "")
-
-(define_insn "*neg<mode>2"
+(define_insn "neg<mode>2"
   [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
        (neg:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")))]
   ""
 ;; (for example, having an input in 7,8 and an output in 6,7).  We
 ;; also allow for the output being the same as one of the inputs.
 
-(define_insn "addti3"
-  [(set (match_operand:TI 0 "gpc_reg_operand" "=&r,&r,r,r")
-       (plus:TI (match_operand:TI 1 "gpc_reg_operand" "%r,r,0,0")
-                (match_operand:TI 2 "reg_or_short_operand" "r,I,r,I")))]
-  "TARGET_64BIT"
-{
-  if (WORDS_BIG_ENDIAN)
-    return (GET_CODE (operands[2])) != CONST_INT
-           ? \"addc %L0,%L1,%L2\;adde %0,%1,%2\"
-           : \"addic %L0,%L1,%2\;add%G2e %0,%1\";
-  else
-    return (GET_CODE (operands[2])) != CONST_INT
-           ? \"addc %0,%1,%2\;adde %L0,%L1,%L2\"
-           : \"addic %0,%1,%2\;add%G2e %L0,%L1\";
-}
-  [(set_attr "type" "two")
-   (set_attr "length" "8")])
-
-(define_insn "subti3"
-  [(set (match_operand:TI 0 "gpc_reg_operand" "=&r,&r,r,r,r")
-       (minus:TI (match_operand:TI 1 "reg_or_short_operand" "r,I,0,r,I")
-                 (match_operand:TI 2 "gpc_reg_operand" "r,r,r,0,0")))]
+(define_expand "addti3"
+  [(set (match_operand:TI 0 "gpc_reg_operand" "")
+       (plus:TI (match_operand:TI 1 "gpc_reg_operand" "")
+                (match_operand:TI 2 "reg_or_short_operand" "")))]
   "TARGET_64BIT"
 {
-  if (WORDS_BIG_ENDIAN)
-    return (GET_CODE (operands[1]) != CONST_INT)
-           ? \"subfc %L0,%L2,%L1\;subfe %0,%2,%1\"
-           : \"subfic %L0,%L2,%1\;subf%G1e %0,%2\";
-  else
-    return (GET_CODE (operands[1]) != CONST_INT)
-           ? \"subfc %0,%2,%1\;subfe %L0,%L2,%L1\"
-           : \"subfic %0,%2,%1\;subf%G1e %L0,%L2\";
-}
-  [(set_attr "type" "two")
-   (set_attr "length" "8")])
+  rtx lo0 = gen_lowpart (DImode, operands[0]);
+  rtx lo1 = gen_lowpart (DImode, operands[1]);
+  rtx lo2 = gen_lowpart (DImode, operands[2]);
+  rtx hi0 = gen_highpart (DImode, operands[0]);
+  rtx hi1 = gen_highpart (DImode, operands[1]);
+  rtx hi2 = gen_highpart_mode (DImode, TImode, operands[2]);
 
+  if (!reg_or_short_operand (lo2, DImode))
+    lo2 = force_reg (DImode, lo2);
+  if (!adde_operand (hi2, DImode))
+    hi2 = force_reg (DImode, hi2);
 
-;; Define the DImode operations that can be done in a small number
-;; of instructions.  The & constraints are to prevent the register
-;; allocator from allocating registers that overlap with the inputs
-;; (for example, having an input in 7,8 and an output in 6,7).  We
-;; also allow for the output being the same as one of the inputs.
+  emit_insn (gen_adddi3_carry (lo0, lo1, lo2));
+  emit_insn (gen_adddi3_carry_in (hi0, hi1, hi2));
+  DONE;
+})
 
-(define_insn "*adddi3_noppc64"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=&r,&r,r,r")
-       (plus:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,0,0")
-                (match_operand:DI 2 "reg_or_short_operand" "r,I,r,I")))]
-  "! TARGET_POWERPC64"
-  "*
+(define_expand "subti3"
+  [(set (match_operand:TI 0 "gpc_reg_operand" "")
+       (minus:TI (match_operand:TI 1 "reg_or_short_operand" "")
+                 (match_operand:TI 2 "gpc_reg_operand" "")))]
+  "TARGET_64BIT"
 {
-  if (WORDS_BIG_ENDIAN)
-    return (GET_CODE (operands[2])) != CONST_INT
-           ? \"addc %L0,%L1,%L2\;adde %0,%1,%2\"
-           : \"addic %L0,%L1,%2\;add%G2e %0,%1\";
-  else
-    return (GET_CODE (operands[2])) != CONST_INT
-           ? \"addc %0,%1,%2\;adde %L0,%L1,%L2\"
-           : \"addic %0,%1,%2\;add%G2e %L0,%L1\";
-}"
-  [(set_attr "type" "two")
-   (set_attr "length" "8")])
+  rtx lo0 = gen_lowpart (DImode, operands[0]);
+  rtx lo1 = gen_lowpart (DImode, operands[1]);
+  rtx lo2 = gen_lowpart (DImode, operands[2]);
+  rtx hi0 = gen_highpart (DImode, operands[0]);
+  rtx hi1 = gen_highpart_mode (DImode, TImode, operands[1]);
+  rtx hi2 = gen_highpart (DImode, operands[2]);
 
-(define_insn "*subdi3_noppc64"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=&r,&r,r,r,r")
-       (minus:DI (match_operand:DI 1 "reg_or_short_operand" "r,I,0,r,I")
-                 (match_operand:DI 2 "gpc_reg_operand" "r,r,r,0,0")))]
-  "! TARGET_POWERPC64"
-  "*
-{
-  if (WORDS_BIG_ENDIAN)
-    return (GET_CODE (operands[1]) != CONST_INT)
-           ? \"subfc %L0,%L2,%L1\;subfe %0,%2,%1\"
-           : \"subfic %L0,%L2,%1\;subf%G1e %0,%2\";
-  else
-    return (GET_CODE (operands[1]) != CONST_INT)
-           ? \"subfc %0,%2,%1\;subfe %L0,%L2,%L1\"
-           : \"subfic %0,%2,%1\;subf%G1e %L0,%L2\";
-}"
-  [(set_attr "type" "two")
-   (set_attr "length" "8")])
+  if (!reg_or_short_operand (lo1, DImode))
+    lo1 = force_reg (DImode, lo1);
+  if (!adde_operand (hi1, DImode))
+    hi1 = force_reg (DImode, hi1);
 
-(define_insn "*negdi2_noppc64"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=&r,r")
-       (neg:DI (match_operand:DI 1 "gpc_reg_operand" "r,0")))]
-  "! TARGET_POWERPC64"
-  "*
-{
-  return (WORDS_BIG_ENDIAN)
-    ? \"subfic %L0,%L1,0\;subfze %0,%1\"
-    : \"subfic %0,%1,0\;subfze %L0,%L1\";
-}"
-  [(set_attr "type" "two")
-   (set_attr "length" "8")])
+  emit_insn (gen_subfdi3_carry (lo0, lo2, lo1));
+  emit_insn (gen_subfdi3_carry_in (hi0, hi2, hi1));
+  DONE;
+})
 
 
 ;; Shift by a variable amount is too complex to be worth open-coding.  We
   DONE;
 }")
 
+(define_expand "cstore<mode>4_unsigned"
+  [(use (match_operator 1 "unsigned_comparison_operator"
+         [(match_operand:P 2 "gpc_reg_operand" "")
+          (match_operand:P 3 "reg_or_short_operand" "")]))
+   (clobber (match_operand:P 0 "register_operand"))]
+  ""
+{
+  enum rtx_code cond_code = GET_CODE (operands[1]);
+
+  rtx op0 = operands[0];
+  rtx op1 = operands[2];
+  rtx op2 = operands[3];
+
+  if (cond_code == GEU || cond_code == LTU)
+    {
+      cond_code = swap_condition (cond_code);
+      op1 = operands[3];
+      op2 = operands[2];
+    }
+
+  if (!gpc_reg_operand (op1, <MODE>mode))
+    op1 = force_reg (<MODE>mode, op1);
+  if (!reg_or_short_operand (op2, <MODE>mode))
+    op2 = force_reg (<MODE>mode, op2);
+
+  rtx tmp = gen_reg_rtx (<MODE>mode);
+  rtx tmp2 = gen_reg_rtx (<MODE>mode);
+
+  emit_insn (gen_subf<mode>3_carry (tmp, op1, op2));
+  emit_insn (gen_subf<mode>3_carry_in_xx (tmp2));
+
+  if (cond_code == LEU)
+    emit_insn (gen_add<mode>3 (op0, tmp2, const1_rtx));
+  else
+    emit_insn (gen_neg<mode>2 (op0, tmp2));
+
+  DONE;
+})
+
 (define_expand "cstore<mode>4"
   [(use (match_operator 1 "rs6000_cbranch_operator"
          [(match_operand:GPR 2 "gpc_reg_operand" "")
           (match_operand:GPR 3 "reg_or_short_operand" "")]))
-   (clobber (match_operand:SI 0 "register_operand"))]
+   (clobber (match_operand:GPR 0 "register_operand"))]
   ""
-  "
 {
-  /* Take care of the possibility that operands[3] might be negative but
-     this might be a logical operation.  That insn doesn't exist.  */
-  if (GET_CODE (operands[3]) == CONST_INT
-      && INTVAL (operands[3]) < 0)
+  /* Use ISEL if the user asked for it.  */
+  if (TARGET_ISEL)
+    rs6000_emit_sISEL (<MODE>mode, operands);
+
+  /* Expanding EQ and NE directly to some machine instructions does not help
+     but does hurt combine.  So don't.  */
+  else if (GET_CODE (operands[1]) == EQ)
+    emit_insn (gen_eq<mode>3 (operands[0], operands[2], operands[3]));
+  else if (<MODE>mode == Pmode
+          && GET_CODE (operands[1]) == NE)
+    emit_insn (gen_ne<mode>3 (operands[0], operands[2], operands[3]));
+  else if (GET_CODE (operands[1]) == NE)
     {
-      operands[3] = force_reg (<MODE>mode, operands[3]);
-      operands[1] = gen_rtx_fmt_ee (GET_CODE (operands[1]),
-                                   GET_MODE (operands[1]),
-                                   operands[2], operands[3]);
+      rtx tmp = gen_reg_rtx (<MODE>mode);
+      emit_insn (gen_eq<mode>3 (tmp, operands[2], operands[3]));
+      emit_insn (gen_xor<mode>3 (operands[0], tmp, const1_rtx));
     }
 
-  /* For SNE, we would prefer that the xor/abs sequence be used for integers.
-     For SEQ, likewise, except that comparisons with zero should be done
-     with an scc insns.  However, due to the order that combine see the
-     resulting insns, we must, in fact, allow SEQ for integers.  Fail in
-     the cases we don't want to handle or are best handled by portable
-     code.  */
-  if (GET_CODE (operands[1]) == NE)
+  /* Expanding the unsigned comparisons however helps a lot: all the neg_ltu
+     etc. combinations magically work out just right.  */
+  else if (<MODE>mode == Pmode
+          && unsigned_comparison_operator (operands[1], VOIDmode))
+    emit_insn (gen_cstore<mode>4_unsigned (operands[0], operands[1],
+                                          operands[2], operands[3]));
+
+  /* The generic code knows tricks to compute signed comparisons against
+     zero.  Let it do its thing.  */
+  else if (operands[3] == const0_rtx
+          && signed_comparison_operator (operands[1], VOIDmode))
     FAIL;
-  if ((GET_CODE (operands[1]) == LT || GET_CODE (operands[1]) == LE
-       || GET_CODE (operands[1]) == GT || GET_CODE (operands[1]) == GE)
-      && operands[3] == const0_rtx)
-    FAIL;
-  rs6000_emit_sCOND (<MODE>mode, operands);
+
+  /* Everything else, use the mfcr brute force.  */
+  else
+    rs6000_emit_sCOND (<MODE>mode, operands);
+
   DONE;
-}")
+})
 
 (define_expand "cstore<mode>4"
   [(use (match_operator 1 "rs6000_cbranch_operator"
           (match_operand:FP 3 "gpc_reg_operand" "")]))
    (clobber (match_operand:SI 0 "register_operand"))]
   ""
-  "
 {
   rs6000_emit_sCOND (<MODE>mode, operands);
   DONE;
-}")
+})
 
 
 (define_expand "stack_protect_set"
   [(set_attr "type" "mfcr")
    (set_attr "length" "12")])
 
-;; There are some scc insns that can be done directly, without a compare.
-;; These are faster because they don't involve the communications between
-;; the FXU and branch units.   In fact, we will be replacing all of the
-;; integer scc insns here or in the portable methods in emit_store_flag.
-;;
-;; Also support (neg (scc ..)) since that construct is used to replace
-;; branches, (plus (scc ..) ..) since that construct is common and
-;; takes no more insns than scc, and (and (neg (scc ..)) ..) in the
-;; cases where it is no more expensive than (neg (scc ..)).
-
-;; Have reload force a constant into a register for the simple insns that
-;; otherwise won't accept constants.  We do this because it is faster than
-;; the cmp/mfcr sequence we would otherwise generate.
 
 (define_mode_attr scc_eq_op2 [(SI "rKLI")
                              (DI "rKJI")])
 
-(define_insn_and_split "*eq<mode>"
+(define_insn_and_split "eq<mode>3"
   [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
        (eq:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")
-               (match_operand:GPR 2 "scc_eq_operand" "<scc_eq_op2>")))]
+               (match_operand:GPR 2 "scc_eq_operand" "<scc_eq_op2>")))
+   (clobber (match_scratch:GPR 3 "=r"))
+   (clobber (match_scratch:GPR 4 "=r"))]
   ""
   "#"
   ""
-  [(set (match_dup 0)
+  [(set (match_dup 4)
        (clz:GPR (match_dup 3)))
    (set (match_dup 0)
-       (lshiftrt:GPR (match_dup 0) (match_dup 4)))]
-  {
-    if (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != 0)
-      {
-       /* Use output operand as intermediate.  */
-       operands[3] = operands[0];
-
-       if (logical_operand (operands[2], <MODE>mode))
-         emit_insn (gen_rtx_SET (VOIDmode, operands[3],
-                                 gen_rtx_XOR (<MODE>mode,
-                                              operands[1], operands[2])));
-       else
-         emit_insn (gen_rtx_SET (VOIDmode, operands[3],
-                                 gen_rtx_PLUS (<MODE>mode, operands[1],
-                                               negate_rtx (<MODE>mode,
-                                                           operands[2]))));
-      }
-    else
-      operands[3] = operands[1];
-
-    operands[4] = GEN_INT (exact_log2 (GET_MODE_BITSIZE (<MODE>mode)));
-  })
-
-(define_insn_and_split "*eq<mode>_compare"
-  [(set (match_operand:CC 3 "cc_reg_operand" "=y")
-       (compare:CC
-        (eq:P (match_operand:P 1 "gpc_reg_operand" "=r")
-              (match_operand:P 2 "scc_eq_operand" "<scc_eq_op2>"))
-        (const_int 0)))
-   (set (match_operand:P 0 "gpc_reg_operand" "=r")
-       (eq:P (match_dup 1) (match_dup 2)))]
-  "optimize_size"
-  "#"
-  "optimize_size"
-  [(set (match_dup 0)
-       (clz:P (match_dup 4)))
-   (parallel [(set (match_dup 3)
-                  (compare:CC (lshiftrt:P (match_dup 0) (match_dup 5))
-                              (const_int 0)))
-             (set (match_dup 0)
-                  (lshiftrt:P (match_dup 0) (match_dup 5)))])]
-  {
-    if (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != 0)
-      {
-       /* Use output operand as intermediate.  */
-       operands[4] = operands[0];
-
-       if (logical_operand (operands[2], <MODE>mode))
-         emit_insn (gen_rtx_SET (VOIDmode, operands[4],
-                                 gen_rtx_XOR (<MODE>mode,
-                                              operands[1], operands[2])));
-       else
-         emit_insn (gen_rtx_SET (VOIDmode, operands[4],
-                                 gen_rtx_PLUS (<MODE>mode, operands[1],
-                                               negate_rtx (<MODE>mode,
-                                                           operands[2]))));
-      }
-    else
-      operands[4] = operands[1];
-
-    operands[5] = GEN_INT (exact_log2 (GET_MODE_BITSIZE (<MODE>mode)));
-  })
-
-;; We have insns of the form shown by the first define_insn below.  If
-;; there is something inside the comparison operation, we must split it.
-(define_split
-  [(set (match_operand:SI 0 "gpc_reg_operand" "")
-       (plus:SI (match_operator 1 "comparison_operator"
-                                [(match_operand:SI 2 "" "")
-                                 (match_operand:SI 3
-                                                   "reg_or_cint_operand" "")])
-                (match_operand:SI 4 "gpc_reg_operand" "")))
-   (clobber (match_operand:SI 5 "register_operand" ""))]
-  "! gpc_reg_operand (operands[2], SImode)"
-  [(set (match_dup 5) (match_dup 2))
-   (set (match_dup 0) (plus:SI (match_op_dup 1 [(match_dup 5) (match_dup 3)])
-                              (match_dup 4)))])
-
-(define_insn "*plus_eqsi"
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=&r,&r,&r,&r,&r")
-       (plus:SI (eq:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r,r,r,r")
-                       (match_operand:SI 2 "scc_eq_operand" "r,O,K,L,I"))
-                (match_operand:SI 3 "gpc_reg_operand" "r,r,r,r,r")))]
-  "TARGET_32BIT"
-  "@
-   xor %0,%1,%2\;subfic %0,%0,0\;addze %0,%3
-   subfic %0,%1,0\;addze %0,%3
-   xori %0,%1,%b2\;subfic %0,%0,0\;addze %0,%3
-   xoris %0,%1,%u2\;subfic %0,%0,0\;addze %0,%3
-   subfic %0,%1,%2\;subfic %0,%0,0\;addze %0,%3"
-  [(set_attr "type" "three,two,three,three,three")
-   (set_attr "length" "12,8,12,12,12")])
+       (lshiftrt:GPR (match_dup 4)
+                     (match_dup 5)))]
+{
+  operands[3] = rs6000_emit_eqne (<MODE>mode,
+                                 operands[1], operands[2], operands[3]);
 
-(define_insn "*compare_plus_eqsi"
-  [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,x,x,x,?y,?y,?y,?y,?y")
-       (compare:CC
-        (plus:SI
-         (eq:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r,r,r,r,r,r,r,r,r")
-                (match_operand:SI 2 "scc_eq_operand" "r,O,K,L,I,r,O,K,L,I"))
-         (match_operand:SI 3 "gpc_reg_operand" "r,r,r,r,r,r,r,r,r,r"))
-        (const_int 0)))
-   (clobber (match_scratch:SI 4 "=&r,&r,&r,&r,&r,&r,&r,&r,&r,&r"))]
-  "TARGET_32BIT && optimize_size"
-  "@
-   xor %4,%1,%2\;subfic %4,%4,0\;addze. %4,%3
-   subfic %4,%1,0\;addze. %4,%3
-   xori %4,%1,%b2\;subfic %4,%4,0\;addze. %4,%3
-   xoris %4,%1,%u2\;subfic %4,%4,0\;addze. %4,%3
-   subfic %4,%1,%2\;subfic %4,%4,0\;addze. %4,%3
-   #
-   #
-   #
-   #
-   #"
-  [(set_attr "type" "compare")
-   (set_attr "length" "12,8,12,12,12,16,12,16,16,16")])
+  if (GET_CODE (operands[4]) == SCRATCH)
+    operands[4] = gen_reg_rtx (<MODE>mode);
 
-(define_split
-  [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
-       (compare:CC
-        (plus:SI
-         (eq:SI (match_operand:SI 1 "gpc_reg_operand" "")
-                (match_operand:SI 2 "scc_eq_operand" ""))
-         (match_operand:SI 3 "gpc_reg_operand" ""))
-        (const_int 0)))
-   (clobber (match_scratch:SI 4 ""))]
-  "TARGET_32BIT && optimize_size && reload_completed"
-  [(set (match_dup 4)
-       (plus:SI (eq:SI (match_dup 1)
-                (match_dup 2))
-         (match_dup 3)))
-   (set (match_dup 0)
-       (compare:CC (match_dup 4)
-                   (const_int 0)))]
-  "")
+  operands[5] = GEN_INT (exact_log2 (GET_MODE_BITSIZE (<MODE>mode)));
+}
+  [(set (attr "length")
+       (if_then_else (match_test "operands[2] == const0_rtx")
+                     (const_string "8")
+                     (const_string "12")))])
 
-(define_insn "*plus_eqsi_compare"
-  [(set (match_operand:CC 4 "cc_reg_operand" "=x,x,x,x,x,?y,?y,?y,?y,?y")
-       (compare:CC
-        (plus:SI
-         (eq:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r,r,r,r,r,r,r,r,r")
-                (match_operand:SI 2 "scc_eq_operand" "r,O,K,L,I,r,O,K,L,I"))
-         (match_operand:SI 3 "gpc_reg_operand" "r,r,r,r,r,r,r,r,r,r"))
-        (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "=&r,&r,&r,&r,&r,&r,&r,&r,&r,&r")
-       (plus:SI (eq:SI (match_dup 1) (match_dup 2)) (match_dup 3)))]
-  "TARGET_32BIT && optimize_size"
-  "@
-   xor %0,%1,%2\;subfic %0,%0,0\;addze. %0,%3
-   subfic %0,%1,0\;addze. %0,%3
-   xori %0,%1,%b2\;subfic %0,%0,0\;addze. %0,%3
-   xoris %0,%1,%u2\;subfic %0,%0,0\;addze. %0,%3
-   subfic %0,%1,%2\;subfic %0,%0,0\;addze. %0,%3
-   #
-   #
-   #
-   #
-   #"
-  [(set_attr "type" "compare")
-   (set_attr "length" "12,8,12,12,12,16,12,16,16,16")])
+(define_insn_and_split "ne<mode>3"
+  [(set (match_operand:P 0 "gpc_reg_operand" "=r")
+       (ne:P (match_operand:P 1 "gpc_reg_operand" "r")
+             (match_operand:P 2 "scc_eq_operand" "<scc_eq_op2>")))
+   (clobber (match_scratch:P 3 "=r"))
+   (clobber (match_scratch:P 4 "=r"))
+   (clobber (reg:P CA_REGNO))]
+  "!TARGET_ISEL"
+  "#"
+  ""
+  [(parallel [(set (match_dup 4)
+                  (plus:P (match_dup 3)
+                          (const_int -1)))
+             (set (reg:P CA_REGNO)
+                  (ne:P (match_dup 3)
+                        (const_int 0)))])
+   (parallel [(set (match_dup 0)
+                  (plus:P (plus:P (not:P (match_dup 4))
+                                  (reg:P CA_REGNO))
+                          (match_dup 3)))
+             (clobber (reg:P CA_REGNO))])]
+{
+  operands[3] = rs6000_emit_eqne (<MODE>mode,
+                                 operands[1], operands[2], operands[3]);
 
-(define_split
-  [(set (match_operand:CC 4 "cc_reg_not_cr0_operand" "")
-       (compare:CC
-        (plus:SI
-         (eq:SI (match_operand:SI 1 "gpc_reg_operand" "")
-                (match_operand:SI 2 "scc_eq_operand" ""))
-         (match_operand:SI 3 "gpc_reg_operand" ""))
-        (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "")
-       (plus:SI (eq:SI (match_dup 1) (match_dup 2)) (match_dup 3)))]
-  "TARGET_32BIT && optimize_size && reload_completed"
-  [(set (match_dup 0)
-       (plus:SI (eq:SI (match_dup 1) (match_dup 2)) (match_dup 3)))
-   (set (match_dup 4)
-       (compare:CC (match_dup 0)
-                   (const_int 0)))]
-  "")
+  if (GET_CODE (operands[4]) == SCRATCH)
+    operands[4] = gen_reg_rtx (<MODE>mode);
+}
+  [(set (attr "length")
+       (if_then_else (match_test "operands[2] == const0_rtx")
+                     (const_string "8")
+                     (const_string "12")))])
 
-(define_insn "*neg_eq0<mode>"
+(define_insn_and_split "*neg_eq_<mode>"
   [(set (match_operand:P 0 "gpc_reg_operand" "=r")
        (neg:P (eq:P (match_operand:P 1 "gpc_reg_operand" "r")
-                    (const_int 0))))]
+                    (match_operand:P 2 "scc_eq_operand" "<scc_eq_op2>"))))
+   (clobber (match_scratch:P 3 "=r"))
+   (clobber (match_scratch:P 4 "=r"))
+   (clobber (reg:P CA_REGNO))]
   ""
-  "addic %0,%1,-1\;subfe %0,%0,%0"
-  [(set_attr "type" "two")
-   (set_attr "length" "8")])
+  "#"
+  ""
+  [(parallel [(set (match_dup 4)
+                  (plus:P (match_dup 3)
+                          (const_int -1)))
+             (set (reg:P CA_REGNO)
+                  (ne:P (match_dup 3)
+                        (const_int 0)))])
+   (parallel [(set (match_dup 0)
+                  (plus:P (reg:P CA_REGNO)
+                          (const_int -1)))
+             (clobber (reg:P CA_REGNO))])]
+{
+  operands[3] = rs6000_emit_eqne (<MODE>mode,
+                                 operands[1], operands[2], operands[3]);
 
-(define_insn_and_split "*neg_eq<mode>"
+  if (GET_CODE (operands[4]) == SCRATCH)
+    operands[4] = gen_reg_rtx (<MODE>mode);
+}
+  [(set (attr "length")
+       (if_then_else (match_test "operands[2] == const0_rtx")
+                     (const_string "8")
+                     (const_string "12")))])
+
+(define_insn_and_split "*neg_ne_<mode>"
   [(set (match_operand:P 0 "gpc_reg_operand" "=r")
-       (neg:P (eq:P (match_operand:P 1 "gpc_reg_operand" "%r")
-                    (match_operand:P 2 "scc_eq_operand" "<scc_eq_op2>"))))]
+       (neg:P (ne:P (match_operand:P 1 "gpc_reg_operand" "r")
+                    (match_operand:P 2 "scc_eq_operand" "<scc_eq_op2>"))))
+   (clobber (match_scratch:P 3 "=r"))
+   (clobber (match_scratch:P 4 "=r"))
+   (clobber (reg:P CA_REGNO))]
   ""
   "#"
   ""
-  [(set (match_dup 0) (neg:P (eq:P (match_dup 3) (const_int 0))))]
-  {
-    if (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != 0)
-      {
-       /* Use output operand as intermediate.  */
-       operands[3] = operands[0];
-
-       if (logical_operand (operands[2], <MODE>mode))
-         emit_insn (gen_rtx_SET (VOIDmode, operands[3],
-                                 gen_rtx_XOR (<MODE>mode,
-                                              operands[1], operands[2])));
-       else
-         emit_insn (gen_rtx_SET (VOIDmode, operands[3],
-                                 gen_rtx_PLUS (<MODE>mode, operands[1],
-                                               negate_rtx (<MODE>mode,
-                                                           operands[2]))));
-      }
-    else
-      operands[3] = operands[1];
-  })
+  [(parallel [(set (match_dup 4)
+                  (neg:P (match_dup 3)))
+             (set (reg:P CA_REGNO)
+                  (eq:P (match_dup 3)
+                        (const_int 0)))])
+   (parallel [(set (match_dup 0)
+                  (plus:P (reg:P CA_REGNO)
+                          (const_int -1)))
+             (clobber (reg:P CA_REGNO))])]
+{
+  operands[3] = rs6000_emit_eqne (<MODE>mode,
+                                 operands[1], operands[2], operands[3]);
+
+  if (GET_CODE (operands[4]) == SCRATCH)
+    operands[4] = gen_reg_rtx (<MODE>mode);
+}
+  [(set (attr "length")
+       (if_then_else (match_test "operands[2] == const0_rtx")
+                     (const_string "8")
+                     (const_string "12")))])
 
-(define_insn "*ne0_<mode>"
+(define_insn_and_split "*plus_eq_<mode>"
   [(set (match_operand:P 0 "gpc_reg_operand" "=r")
-       (ne:P (match_operand:P 1 "gpc_reg_operand" "r")
-             (const_int 0)))
-   (clobber (match_scratch:P 2 "=&r"))]
-  "!(TARGET_32BIT && TARGET_ISEL)"
-  "addic %2,%1,-1\;subfe %0,%2,%1"
-  [(set_attr "type" "two")
-   (set_attr "length" "8")])
+       (plus:P (eq:P (match_operand:P 1 "gpc_reg_operand" "r")
+                     (match_operand:P 2 "scc_eq_operand" "<scc_eq_op2>"))
+               (match_operand:P 3 "gpc_reg_operand" "r")))
+   (clobber (match_scratch:P 4 "=r"))
+   (clobber (match_scratch:P 5 "=r"))
+   (clobber (reg:P CA_REGNO))]
+  ""
+  "#"
+  ""
+  [(parallel [(set (match_dup 5)
+                  (neg:P (match_dup 4)))
+             (set (reg:P CA_REGNO)
+                  (eq:P (match_dup 4)
+                        (const_int 0)))])
+   (parallel [(set (match_dup 0)
+                  (plus:P (match_dup 3)
+                          (reg:P CA_REGNO)))
+             (clobber (reg:P CA_REGNO))])]
+{
+  operands[4] = rs6000_emit_eqne (<MODE>mode,
+                                 operands[1], operands[2], operands[4]);
+
+  if (GET_CODE (operands[5]) == SCRATCH)
+    operands[5] = gen_reg_rtx (<MODE>mode);
+}
+  [(set (attr "length")
+       (if_then_else (match_test "operands[2] == const0_rtx")
+                     (const_string "8")
+                     (const_string "12")))])
 
-(define_insn "*plus_ne0_<mode>"
+(define_insn_and_split "*plus_ne_<mode>"
   [(set (match_operand:P 0 "gpc_reg_operand" "=r")
        (plus:P (ne:P (match_operand:P 1 "gpc_reg_operand" "r")
-                     (const_int 0))
-               (match_operand:P 2 "gpc_reg_operand" "r")))
-   (clobber (match_scratch:P 3 "=&r"))]
+                     (match_operand:P 2 "scc_eq_operand" "<scc_eq_op2>"))
+               (match_operand:P 3 "gpc_reg_operand" "r")))
+   (clobber (match_scratch:P 4 "=r"))
+   (clobber (match_scratch:P 5 "=r"))
+   (clobber (reg:P CA_REGNO))]
   ""
-  "addic %3,%1,-1\;addze %0,%2"
-  [(set_attr "type" "two")
-   (set_attr "length" "8")])
-
-(define_insn "*compare_plus_ne0_<mode>"
-  [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
-       (compare:CC (plus:P (ne:P (match_operand:P 1 "gpc_reg_operand" "r,r")
-                                 (const_int 0))
-                           (match_operand:P 2 "gpc_reg_operand" "r,r"))
-                   (const_int 0)))
-   (clobber (match_scratch:P 3 "=&r,&r"))
-   (clobber (match_scratch:P 4 "=X,&r"))]
+  "#"
   ""
-  "@
-   addic %3,%1,-1\;addze. %3,%2
-   #"
-  [(set_attr "type" "compare")
-   (set_attr "length" "8,12")])
+  [(parallel [(set (match_dup 5)
+                  (plus:P (match_dup 4)
+                          (const_int -1)))
+             (set (reg:P CA_REGNO)
+                  (ne:P (match_dup 4)
+                        (const_int 0)))])
+   (parallel [(set (match_dup 0)
+                  (plus:P (match_dup 3)
+                          (reg:P CA_REGNO)))
+             (clobber (reg:P CA_REGNO))])]
+{
+  operands[4] = rs6000_emit_eqne (<MODE>mode,
+                                 operands[1], operands[2], operands[4]);
 
-(define_split
-  [(set (match_operand:CC 0 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC (ne:P (match_operand:SI 1 "gpc_reg_operand" "")
-                         (const_int 0))
-                   (neg:P (match_operand:P 2 "gpc_reg_operand" ""))))
-   (clobber (match_scratch:P 3 ""))
-   (clobber (match_scratch:P 4 ""))]
-  "reload_completed"
-  [(parallel [(set (match_dup 3)
-                  (plus:P (ne:P (match_dup 1)
-                                (const_int 0))
-                          (match_dup 2)))
-              (clobber (match_dup 4))])
-   (set (match_dup 0)
-       (compare:CC (match_dup 3)
-                   (const_int 0)))]
-  "")
+  if (GET_CODE (operands[5]) == SCRATCH)
+    operands[5] = gen_reg_rtx (<MODE>mode);
+}
+  [(set (attr "length")
+       (if_then_else (match_test "operands[2] == const0_rtx")
+                     (const_string "8")
+                     (const_string "12")))])
 
-; For combine.
-(define_insn "*compare_plus_ne0_<mode>_1"
-  [(set (match_operand:CCEQ 0 "cc_reg_operand" "=x,?y")
-       (compare:CCEQ (ne:P (match_operand:P 1 "gpc_reg_operand" "r,r")
-                           (const_int 0))
-                     (neg:P (match_operand:P 2 "gpc_reg_operand" "r,r"))))
-   (clobber (match_scratch:P 3 "=&r,&r"))
-   (clobber (match_scratch:P 4 "=X,&r"))]
+(define_insn_and_split "*minus_eq_<mode>"
+  [(set (match_operand:P 0 "gpc_reg_operand" "=r")
+       (minus:P (match_operand:P 3 "gpc_reg_operand" "r")
+                (eq:P (match_operand:P 1 "gpc_reg_operand" "r")
+                      (match_operand:P 2 "scc_eq_operand" "<scc_eq_op2>"))))
+   (clobber (match_scratch:P 4 "=r"))
+   (clobber (match_scratch:P 5 "=r"))
+   (clobber (reg:P CA_REGNO))]
   ""
-  "@
-   addic %3,%1,-1\;addze. %3,%2
-   #"
-  [(set_attr "type" "compare")
-   (set_attr "length" "8,12")])
+  "#"
+  ""
+  [(parallel [(set (match_dup 5)
+                  (plus:P (match_dup 4)
+                          (const_int -1)))
+             (set (reg:P CA_REGNO)
+                  (ne:P (match_dup 4)
+                        (const_int 0)))])
+   (parallel [(set (match_dup 0)
+                  (plus:P (plus:P (match_dup 3)
+                                  (reg:P CA_REGNO))
+                          (const_int -1)))
+             (clobber (reg:P CA_REGNO))])]
+{
+  operands[4] = rs6000_emit_eqne (<MODE>mode,
+                                 operands[1], operands[2], operands[4]);
 
-(define_split
-  [(set (match_operand:CCEQ 0 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CCEQ (ne:P (match_operand:SI 1 "gpc_reg_operand" "")
-                           (const_int 0))
-                     (neg:P (match_operand:P 2 "gpc_reg_operand" ""))))
-   (clobber (match_scratch:P 3 ""))
-   (clobber (match_scratch:P 4 ""))]
-  "reload_completed"
-  [(parallel [(set (match_dup 3)
-                  (plus:P (ne:P (match_dup 1)
-                                (const_int 0))
-                          (match_dup 2)))
-              (clobber (match_dup 4))])
-   (set (match_dup 0)
-       (compare:CC (match_dup 3)
-                   (const_int 0)))]
-  "")
+  if (GET_CODE (operands[5]) == SCRATCH)
+    operands[5] = gen_reg_rtx (<MODE>mode);
+}
+  [(set (attr "length")
+       (if_then_else (match_test "operands[2] == const0_rtx")
+                     (const_string "8")
+                     (const_string "12")))])
 
-(define_insn "*plus_ne0_<mode>_compare"
-  [(set (match_operand:CC 4 "cc_reg_operand" "=x,?y")
-       (compare:CC
-        (plus:P (ne:P (match_operand:P 1 "gpc_reg_operand" "r,r")
-                      (const_int 0))
-                (match_operand:P 2 "gpc_reg_operand" "r,r"))
-        (const_int 0)))
-   (set (match_operand:P 0 "gpc_reg_operand" "=r,r")
-       (plus:P (ne:P (match_dup 1)
-                     (const_int 0))
-               (match_dup 2)))
-   (clobber (match_scratch:P 3 "=&r,&r"))]
+(define_insn_and_split "*minus_ne_<mode>"
+  [(set (match_operand:P 0 "gpc_reg_operand" "=r")
+       (minus:P (match_operand:P 3 "gpc_reg_operand" "r")
+                (ne:P (match_operand:P 1 "gpc_reg_operand" "r")
+                      (match_operand:P 2 "scc_eq_operand" "<scc_eq_op2>"))))
+   (clobber (match_scratch:P 4 "=r"))
+   (clobber (match_scratch:P 5 "=r"))
+   (clobber (reg:P CA_REGNO))]
   ""
-  "@
-   addic %3,%1,-1\;addze. %0,%2
-   #"
-  [(set_attr "type" "compare")
-   (set_attr "length" "8,12")])
-
-(define_split
-  [(set (match_operand:CC 4 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC
-        (plus:P (ne:P (match_operand:P 1 "gpc_reg_operand" "")
-                      (const_int 0))
-                (match_operand:P 2 "gpc_reg_operand" ""))
-        (const_int 0)))
-   (set (match_operand:P 0 "gpc_reg_operand" "")
-       (plus:P (ne:P (match_dup 1)
-                     (const_int 0))
-               (match_dup 2)))
-   (clobber (match_scratch:P 3 ""))]
-  "reload_completed"
-  [(parallel [(set (match_dup 0)
-                  (plus:P (ne:P (match_dup 1)
-                                (const_int 0))
-                          (match_dup 2)))
-             (clobber (match_dup 3))])
-   (set (match_dup 4)
-       (compare:CC (match_dup 0)
-                   (const_int 0)))]
-  "")
-
-(define_insn "*leu<mode>"
-  [(set (match_operand:P 0 "gpc_reg_operand" "=r")
-       (leu:P (match_operand:P 1 "gpc_reg_operand" "r")
-              (match_operand:P 2 "reg_or_short_operand" "rI")))]
-  ""
-  "subf%I2c %0,%1,%2\;li %0,0\;adde %0,%0,%0"
-  [(set_attr "type" "three")
-   (set_attr "length" "12")])
-
-(define_insn "*leu<mode>_compare"
-  [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
-       (compare:CC
-        (leu:P (match_operand:P 1 "gpc_reg_operand" "r,r")
-               (match_operand:P 2 "reg_or_short_operand" "rI,rI"))
-        (const_int 0)))
-   (set (match_operand:P 0 "gpc_reg_operand" "=r,r")
-       (leu:P (match_dup 1) (match_dup 2)))]
-  ""
-  "@
-   subf%I2c %0,%1,%2\;li %0,0\;adde. %0,%0,%0
-   #"
-  [(set_attr "type" "compare")
-   (set_attr "length" "12,16")])
-
-(define_split
-  [(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "")
-       (compare:CC
-        (leu:P (match_operand:P 1 "gpc_reg_operand" "")
-               (match_operand:P 2 "reg_or_short_operand" ""))
-        (const_int 0)))
-   (set (match_operand:P 0 "gpc_reg_operand" "")
-       (leu:P (match_dup 1) (match_dup 2)))]
-  "reload_completed"
-  [(set (match_dup 0)
-       (leu:P (match_dup 1) (match_dup 2)))
-   (set (match_dup 3)
-       (compare:CC (match_dup 0)
-                   (const_int 0)))]
-  "")
-
-(define_insn "*plus_leu<mode>"
-  [(set (match_operand:P 0 "gpc_reg_operand" "=&r")
-       (plus:P (leu:P (match_operand:P 1 "gpc_reg_operand" "r")
-                      (match_operand:P 2 "reg_or_short_operand" "rI"))
-               (match_operand:P 3 "gpc_reg_operand" "r")))]
-  ""
-  "subf%I2c %0,%1,%2\;addze %0,%3"
-  [(set_attr "type" "two")
-   (set_attr "length" "8")])
-
-(define_insn ""
-  [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
-       (compare:CC
-        (plus:SI (leu:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
-                         (match_operand:SI 2 "reg_or_short_operand" "rI,rI"))
-                 (match_operand:SI 3 "gpc_reg_operand" "r,r"))
-        (const_int 0)))
-   (clobber (match_scratch:SI 4 "=&r,&r"))]
-  "TARGET_32BIT"
-  "@
-   subf%I2c %4,%1,%2\;addze. %4,%3
-   #"
-  [(set_attr "type" "compare")
-   (set_attr "length" "8,12")])
-
-(define_split
-  [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
-       (compare:CC
-        (plus:SI (leu:SI (match_operand:SI 1 "gpc_reg_operand" "")
-                         (match_operand:SI 2 "reg_or_short_operand" ""))
-                 (match_operand:SI 3 "gpc_reg_operand" ""))
-        (const_int 0)))
-   (clobber (match_scratch:SI 4 ""))]
-  "TARGET_32BIT && reload_completed"
-  [(set (match_dup 4)
-       (plus:SI (leu:SI (match_dup 1) (match_dup 2))
-                 (match_dup 3)))
-   (set (match_dup 0)
-       (compare:CC (match_dup 4)
-                   (const_int 0)))]
-  "")
-
-(define_insn ""
-  [(set (match_operand:CC 4 "cc_reg_operand" "=x,?y")
-       (compare:CC
-        (plus:SI (leu:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
-                         (match_operand:SI 2 "reg_or_short_operand" "rI,rI"))
-                 (match_operand:SI 3 "gpc_reg_operand" "r,r"))
-        (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "=&r,&r")
-       (plus:SI (leu:SI (match_dup 1) (match_dup 2)) (match_dup 3)))]
-  "TARGET_32BIT"
-  "@
-   subf%I2c %0,%1,%2\;addze. %0,%3
-   #"
-  [(set_attr "type" "compare")
-   (set_attr "length" "8,12")])
-
-(define_split
-  [(set (match_operand:CC 4 "cc_reg_not_cr0_operand" "")
-       (compare:CC
-        (plus:SI (leu:SI (match_operand:SI 1 "gpc_reg_operand" "")
-                         (match_operand:SI 2 "reg_or_short_operand" ""))
-                 (match_operand:SI 3 "gpc_reg_operand" ""))
-        (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "")
-       (plus:SI (leu:SI (match_dup 1) (match_dup 2)) (match_dup 3)))]
-  "TARGET_32BIT && reload_completed"
-  [(set (match_dup 0)
-       (plus:SI (leu:SI (match_dup 1) (match_dup 2)) (match_dup 3)))
-   (set (match_dup 4)
-       (compare:CC (match_dup 0)
-                   (const_int 0)))]
-  "")
-
-(define_insn "*neg_leu<mode>"
-  [(set (match_operand:P 0 "gpc_reg_operand" "=r")
-       (neg:P (leu:P (match_operand:P 1 "gpc_reg_operand" "r")
-                     (match_operand:P 2 "reg_or_short_operand" "rI"))))]
-  ""
-  "subf%I2c %0,%1,%2\;subfe %0,%0,%0\;nand %0,%0,%0"
-   [(set_attr "type" "three")
-    (set_attr "length" "12")])
-
-(define_insn "*and_neg_leu<mode>"
-  [(set (match_operand:P 0 "gpc_reg_operand" "=&r")
-       (and:P (neg:P
-                (leu:P (match_operand:P 1 "gpc_reg_operand" "r")
-                       (match_operand:P 2 "reg_or_short_operand" "rI")))
-               (match_operand:P 3 "gpc_reg_operand" "r")))]
-  ""
-  "subf%I2c %0,%1,%2\;subfe %0,%0,%0\;andc %0,%3,%0"
-  [(set_attr "type" "three")
-   (set_attr "length" "12")])
-
-(define_insn ""
-  [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
-       (compare:CC
-        (and:SI (neg:SI
-                 (leu:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
-                         (match_operand:SI 2 "reg_or_short_operand" "rI,rI")))
-                (match_operand:SI 3 "gpc_reg_operand" "r,r"))
-        (const_int 0)))
-   (clobber (match_scratch:SI 4 "=&r,&r"))]
-  "TARGET_32BIT"
-  "@
-   subf%I2c %4,%1,%2\;subfe %4,%4,%4\;andc. %4,%3,%4
-   #"
-  [(set_attr "type" "compare")
-   (set_attr "length" "12,16")])
-
-(define_split
-  [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
-       (compare:CC
-        (and:SI (neg:SI
-                 (leu:SI (match_operand:SI 1 "gpc_reg_operand" "")
-                         (match_operand:SI 2 "reg_or_short_operand" "")))
-                (match_operand:SI 3 "gpc_reg_operand" ""))
-        (const_int 0)))
-   (clobber (match_scratch:SI 4 ""))]
-  "TARGET_32BIT && reload_completed"
-  [(set (match_dup 4)
-       (and:SI (neg:SI (leu:SI (match_dup 1) (match_dup 2)))
-               (match_dup 3)))
-   (set (match_dup 0)
-       (compare:CC (match_dup 4)
-                   (const_int 0)))]
-  "")
-
-(define_insn ""
-  [(set (match_operand:CC 4 "cc_reg_operand" "=x,?y")
-       (compare:CC
-        (and:SI (neg:SI
-                 (leu:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
-                         (match_operand:SI 2 "reg_or_short_operand" "rI,rI")))
-                (match_operand:SI 3 "gpc_reg_operand" "r,r"))
-        (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "=&r,&r")
-       (and:SI (neg:SI (leu:SI (match_dup 1) (match_dup 2))) (match_dup 3)))]
-  "TARGET_32BIT"
-  "@
-   subf%I2c %0,%1,%2\;subfe %0,%0,%0\;andc. %0,%3,%0
-   #"
-  [(set_attr "type" "compare")
-   (set_attr "length" "12,16")])
-
-(define_split
-  [(set (match_operand:CC 4 "cc_reg_not_cr0_operand" "")
-       (compare:CC
-        (and:SI (neg:SI
-                 (leu:SI (match_operand:SI 1 "gpc_reg_operand" "")
-                         (match_operand:SI 2 "reg_or_short_operand" "")))
-                (match_operand:SI 3 "gpc_reg_operand" ""))
-        (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "")
-       (and:SI (neg:SI (leu:SI (match_dup 1) (match_dup 2))) (match_dup 3)))]
-  "TARGET_32BIT && reload_completed"
-  [(set (match_dup 0)
-       (and:SI (neg:SI (leu:SI (match_dup 1) (match_dup 2)))
-               (match_dup 3)))
-   (set (match_dup 4)
-       (compare:CC (match_dup 0)
-                   (const_int 0)))]
-  "")
-
-(define_insn_and_split "*ltu<mode>"
-  [(set (match_operand:P 0 "gpc_reg_operand" "=r,r")
-       (ltu:P (match_operand:P 1 "gpc_reg_operand" "r,r")
-              (match_operand:P 2 "reg_or_neg_short_operand" "r,P")))]
-  ""
-  "#"
-  ""
-  [(set (match_dup 0) (neg:P (ltu:P (match_dup 1) (match_dup 2))))
-   (set (match_dup 0) (neg:P (match_dup 0)))]
-  "")
-
-(define_insn_and_split "*ltu<mode>_compare"
-  [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,?y,?y")
-       (compare:CC
-        (ltu:P (match_operand:P 1 "gpc_reg_operand" "r,r,r,r")
-               (match_operand:P 2 "reg_or_neg_short_operand" "r,P,r,P"))
-        (const_int 0)))
-   (set (match_operand:P 0 "gpc_reg_operand" "=r,r,r,r")
-       (ltu:P (match_dup 1) (match_dup 2)))]
-  ""
-  "#"
-  ""
-  [(set (match_dup 0) (neg:P (ltu:P (match_dup 1) (match_dup 2))))
-   (parallel [(set (match_dup 3)
-                  (compare:CC (neg:P (match_dup 0)) (const_int 0)))
-             (set (match_dup 0) (neg:P (match_dup 0)))])]
-  "")
-
-(define_insn_and_split "*plus_ltu<mode>"
-  [(set (match_operand:P 0 "gpc_reg_operand" "=&r,r")
-       (plus:P (ltu:P (match_operand:P 1 "gpc_reg_operand" "r,r")
-                      (match_operand:P 2 "reg_or_neg_short_operand" "r,P"))
-               (match_operand:P 3 "gpc_reg_operand" "r,r")))]
-  ""
-  "#"
-  "&& !reg_overlap_mentioned_p (operands[0], operands[3])"
-  [(set (match_dup 0) (neg:P (ltu:P (match_dup 1) (match_dup 2))))
-   (set (match_dup 0) (minus:P (match_dup 3) (match_dup 0)))]
-  "")
-
-(define_insn_and_split "*plus_ltu<mode>_1"
-  [(set (match_operand:P 0 "gpc_reg_operand" "=&r,r")
-       (plus:P (ltu:P (match_operand:P 1 "gpc_reg_operand" "r,r")
-                      (match_operand:P 2 "reg_or_neg_short_operand" "r,P"))
-               (match_operand:P 3 "short_cint_operand" "I,I")))]
-  ""
-  "#"
-  "&& !reg_overlap_mentioned_p (operands[0], operands[3])"
-  [(set (match_dup 0) (neg:P (ltu:P (match_dup 1) (match_dup 2))))
-   (parallel [(set (match_dup 0) (minus:P (match_dup 3) (match_dup 0)))
-             (clobber (reg:P CA_REGNO))])]
-  "")
-
-(define_insn_and_split "*plus_ltu<mode>_compare"
-  [(set (match_operand:CC 4 "cc_reg_operand" "=x,x,?y,?y")
-       (compare:CC
-        (plus:P (ltu:P (match_operand:P 1 "gpc_reg_operand" "r,r,r,r")
-                       (match_operand:P 2 "reg_or_neg_short_operand" "r,P,r,P"))
-                (match_operand:P 3 "gpc_reg_operand" "r,r,r,r"))
-        (const_int 0)))
-   (set (match_operand:P 0 "gpc_reg_operand" "=&r,&r,&r,&r")
-       (plus:P (ltu:P (match_dup 1) (match_dup 2)) (match_dup 3)))]
-  ""
-  "#"
-  "&& !reg_overlap_mentioned_p (operands[0], operands[3])"
-  [(set (match_dup 0) (neg:P (ltu:P (match_dup 1) (match_dup 2))))
-   (parallel [(set (match_dup 4)
-                  (compare:CC (minus:P (match_dup 3) (match_dup 0))
-                              (const_int 0)))
-             (set (match_dup 0) (minus:P (match_dup 3) (match_dup 0)))])]
-  "")
-
-(define_insn "*neg_ltu<mode>"
-  [(set (match_operand:P 0 "gpc_reg_operand" "=r,r")
-       (neg:P (ltu:P (match_operand:P 1 "gpc_reg_operand" "r,r")
-                     (match_operand:P 2 "reg_or_neg_short_operand" "r,P"))))]
-  ""
-  "@
-   subfc %0,%2,%1\;subfe %0,%0,%0
-   addic %0,%1,%n2\;subfe %0,%0,%0"
-  [(set_attr "type" "two")
-   (set_attr "length" "8")])
-
-(define_insn "*geu<mode>"
-  [(set (match_operand:P 0 "gpc_reg_operand" "=r,r")
-       (geu:P (match_operand:P 1 "gpc_reg_operand" "r,r")
-              (match_operand:P 2 "reg_or_neg_short_operand" "r,P")))]
-  ""
-  "@
-   subfc %0,%2,%1\;li %0,0\;adde %0,%0,%0
-   addic %0,%1,%n2\;li %0,0\;adde %0,%0,%0"
-  [(set_attr "type" "three")
-   (set_attr "length" "12")])
-
-(define_insn "*geu<mode>_compare"
-  [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,?y,?y")
-       (compare:CC
-        (geu:P (match_operand:P 1 "gpc_reg_operand" "r,r,r,r")
-               (match_operand:P 2 "reg_or_neg_short_operand" "r,P,r,P"))
-        (const_int 0)))
-   (set (match_operand:P 0 "gpc_reg_operand" "=r,r,r,r")
-       (geu:P (match_dup 1) (match_dup 2)))]
-  ""
-  "@
-   subfc %0,%2,%1\;li %0,0\;adde. %0,%0,%0
-   addic %0,%1,%n2\;li %0,0\;adde. %0,%0,%0
-   #
-   #"
-  [(set_attr "type" "compare")
-   (set_attr "length" "12,12,16,16")])
-
-(define_split
-  [(set (match_operand:CC 3 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC
-        (geu:P (match_operand:P 1 "gpc_reg_operand" "")
-               (match_operand:P 2 "reg_or_neg_short_operand" ""))
-        (const_int 0)))
-   (set (match_operand:P 0 "gpc_reg_operand" "")
-       (geu:P (match_dup 1) (match_dup 2)))]
-  "reload_completed"
-  [(set (match_dup 0)
-       (geu:P (match_dup 1) (match_dup 2)))
-   (set (match_dup 3)
-       (compare:CC (match_dup 0)
-                   (const_int 0)))]
-  "")
-
-(define_insn "*plus_geu<mode>"
-  [(set (match_operand:P 0 "gpc_reg_operand" "=&r,&r")
-       (plus:P (geu:P (match_operand:P 1 "gpc_reg_operand" "r,r")
-                      (match_operand:P 2 "reg_or_neg_short_operand" "r,P"))
-               (match_operand:P 3 "gpc_reg_operand" "r,r")))]
-  ""
-  "@
-   subfc %0,%2,%1\;addze %0,%3
-   addic %0,%1,%n2\;addze %0,%3"
-  [(set_attr "type" "two")
-   (set_attr "length" "8")])
-
-(define_insn ""
-  [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y")
-       (compare:CC
-        (plus:SI (geu:SI (match_operand:SI 1 "gpc_reg_operand" "r,r,r,r")
-                         (match_operand:SI 2 "reg_or_neg_short_operand" "r,P,r,P"))
-                 (match_operand:SI 3 "gpc_reg_operand" "r,r,r,r"))
-        (const_int 0)))
-   (clobber (match_scratch:SI 4 "=&r,&r,&r,&r"))]
-  "TARGET_32BIT"
-  "@
-   subfc %4,%2,%1\;addze. %4,%3
-   addic %4,%1,%n2\;addze. %4,%3
-   #
-   #"
-  [(set_attr "type" "compare")
-   (set_attr "length" "8,8,12,12")])
-
-(define_split
-  [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
-       (compare:CC
-        (plus:SI (geu:SI (match_operand:SI 1 "gpc_reg_operand" "")
-                         (match_operand:SI 2 "reg_or_neg_short_operand" ""))
-                 (match_operand:SI 3 "gpc_reg_operand" ""))
-        (const_int 0)))
-   (clobber (match_scratch:SI 4 ""))]
-  "TARGET_32BIT && reload_completed"
-  [(set (match_dup 4)
-       (plus:SI (geu:SI (match_dup 1) (match_dup 2))
-                 (match_dup 3)))
-   (set (match_dup 0)
-       (compare:CC (match_dup 4)
-                   (const_int 0)))]
-  "")
-
-(define_insn ""
-  [(set (match_operand:CC 4 "cc_reg_operand" "=x,x,?y,?y")
-       (compare:CC
-        (plus:SI (geu:SI (match_operand:SI 1 "gpc_reg_operand" "r,r,r,r")
-                         (match_operand:SI 2 "reg_or_neg_short_operand" "r,P,r,P"))
-                 (match_operand:SI 3 "gpc_reg_operand" "r,r,r,r"))
-        (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "=&r,&r,&r,&r")
-       (plus:SI (geu:SI (match_dup 1) (match_dup 2)) (match_dup 3)))]
-  "TARGET_32BIT"
-  "@
-   subfc %0,%2,%1\;addze. %0,%3
-   addic %0,%1,%n2\;addze. %0,%3
-   #
-   #"
-  [(set_attr "type" "compare")
-   (set_attr "length" "8,8,12,12")])
-
-(define_split
-  [(set (match_operand:CC 4 "cc_reg_not_cr0_operand" "")
-       (compare:CC
-        (plus:SI (geu:SI (match_operand:SI 1 "gpc_reg_operand" "")
-                         (match_operand:SI 2 "reg_or_neg_short_operand" ""))
-                 (match_operand:SI 3 "gpc_reg_operand" ""))
-        (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "")
-       (plus:SI (geu:SI (match_dup 1) (match_dup 2)) (match_dup 3)))]
-  "TARGET_32BIT && reload_completed"
-  [(set (match_dup 0)
-       (plus:SI (geu:SI (match_dup 1) (match_dup 2)) (match_dup 3)))
-   (set (match_dup 4)
-       (compare:CC (match_dup 0)
-                   (const_int 0)))]
-  "")
-
-(define_insn "*neg_geu<mode>"
-  [(set (match_operand:P 0 "gpc_reg_operand" "=r,r")
-       (neg:P (geu:P (match_operand:P 1 "gpc_reg_operand" "r,r")
-                     (match_operand:P 2 "reg_or_short_operand" "r,I"))))]
-  ""
-  "@
-   subfc %0,%2,%1\;subfe %0,%0,%0\;nand %0,%0,%0
-   subfic %0,%1,-1\;add%I2c %0,%0,%2\;subfe %0,%0,%0"
-  [(set_attr "type" "three")
-   (set_attr "length" "12")])
-
-(define_insn "*and_neg_geu<mode>"
-  [(set (match_operand:P 0 "gpc_reg_operand" "=&r,&r")
-       (and:P (neg:P
-                (geu:P (match_operand:P 1 "gpc_reg_operand" "r,r")
-                       (match_operand:P 2 "reg_or_neg_short_operand" "r,P")))
-               (match_operand:P 3 "gpc_reg_operand" "r,r")))]
-  ""
-  "@
-   subfc %0,%2,%1\;subfe %0,%0,%0\;andc %0,%3,%0
-   addic %0,%1,%n2\;subfe %0,%0,%0\;andc %0,%3,%0"
-  [(set_attr "type" "three")
-   (set_attr "length" "12")])
-
-(define_insn ""
-  [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y")
-       (compare:CC
-        (and:SI (neg:SI
-                 (geu:SI (match_operand:SI 1 "gpc_reg_operand" "r,r,r,r")
-                         (match_operand:SI 2 "reg_or_neg_short_operand" "r,P,r,P")))
-                (match_operand:SI 3 "gpc_reg_operand" "r,r,r,r"))
-        (const_int 0)))
-   (clobber (match_scratch:SI 4 "=&r,&r,&r,&r"))]
-  "TARGET_32BIT"
-  "@
-   subfc %4,%2,%1\;subfe %4,%4,%4\;andc. %4,%3,%4
-   addic %4,%1,%n2\;subfe %4,%4,%4\;andc. %4,%3,%4
-   #
-   #"
-  [(set_attr "type" "compare")
-   (set_attr "length" "12,12,16,16")])
-
-(define_split
-  [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
-       (compare:CC
-        (and:SI (neg:SI
-                 (geu:SI (match_operand:SI 1 "gpc_reg_operand" "")
-                         (match_operand:SI 2 "reg_or_neg_short_operand" "")))
-                (match_operand:SI 3 "gpc_reg_operand" ""))
-        (const_int 0)))
-   (clobber (match_scratch:SI 4 ""))]
-  "TARGET_32BIT && reload_completed"
-  [(set (match_dup 4)
-       (and:SI (neg:SI (geu:SI (match_dup 1) (match_dup 2)))
-               (match_dup 3)))
-   (set (match_dup 0)
-       (compare:CC (match_dup 4)
-                   (const_int 0)))]
-  "")
-
-(define_insn ""
-  [(set (match_operand:CC 4 "cc_reg_operand" "=x,x,?y,?y")
-       (compare:CC
-        (and:SI (neg:SI
-                 (geu:SI (match_operand:SI 1 "gpc_reg_operand" "r,r,r,r")
-                         (match_operand:SI 2 "reg_or_neg_short_operand" "r,P,r,P")))
-                (match_operand:SI 3 "gpc_reg_operand" "r,r,r,r"))
-        (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "=&r,&r,&r,&r")
-       (and:SI (neg:SI (geu:SI (match_dup 1) (match_dup 2))) (match_dup 3)))]
-  "TARGET_32BIT"
-  "@
-   subfc %0,%2,%1\;subfe %0,%0,%0\;andc. %0,%3,%0
-   addic %0,%1,%n2\;subfe %0,%0,%0\;andc. %0,%3,%0
-   #
-   #"
-  [(set_attr "type" "compare")
-   (set_attr "length" "12,12,16,16")])
-
-(define_split
-  [(set (match_operand:CC 4 "cc_reg_not_cr0_operand" "")
-       (compare:CC
-        (and:SI (neg:SI
-                 (geu:SI (match_operand:SI 1 "gpc_reg_operand" "")
-                         (match_operand:SI 2 "reg_or_neg_short_operand" "")))
-                (match_operand:SI 3 "gpc_reg_operand" ""))
-        (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "")
-       (and:SI (neg:SI (geu:SI (match_dup 1) (match_dup 2))) (match_dup 3)))]
-  "TARGET_32BIT && reload_completed"
-  [(set (match_dup 0)
-       (and:SI (neg:SI (geu:SI (match_dup 1) (match_dup 2))) (match_dup 3)))
-   (set (match_dup 4)
-       (compare:CC (match_dup 0)
-                   (const_int 0)))]
-  "")
-
-(define_insn "*plus_gt0<mode>"
-  [(set (match_operand:P 0 "gpc_reg_operand" "=&r")
-       (plus:P (gt:P (match_operand:P 1 "gpc_reg_operand" "r")
-                     (const_int 0))
-                (match_operand:P 2 "gpc_reg_operand" "r")))]
-  ""
-  "addc %0,%1,%1\;subfe %0,%1,%0\;addze %0,%2"
-  [(set_attr "type" "three")
-   (set_attr "length" "12")])
-
-(define_insn ""
-  [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
-       (compare:CC
-        (plus:SI (gt:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
-                        (const_int 0))
-                 (match_operand:SI 2 "gpc_reg_operand" "r,r"))
-        (const_int 0)))
-   (clobber (match_scratch:SI 3 "=&r,&r"))]
-  "TARGET_32BIT"
-  "@
-   addc %3,%1,%1\;subfe %3,%1,%3\;addze. %3,%2
-   #"
-  [(set_attr "type" "compare")
-   (set_attr "length" "12,16")])
-
-(define_split
-  [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
-       (compare:CC
-        (plus:SI (gt:SI (match_operand:SI 1 "gpc_reg_operand" "")
-                        (const_int 0))
-                 (match_operand:SI 2 "gpc_reg_operand" ""))
-        (const_int 0)))
-   (clobber (match_scratch:SI 3 ""))]
-  "TARGET_32BIT && reload_completed"
-  [(set (match_dup 3)
-       (plus:SI (gt:SI (match_dup 1) (const_int 0))
-                 (match_dup 2)))
-   (set (match_dup 0)
-       (compare:CC (match_dup 3)
-                   (const_int 0)))]
-  "")
-
-(define_insn ""
-  [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
-       (compare:CC
-        (plus:DI (gt:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
-                        (const_int 0))
-                 (match_operand:DI 2 "gpc_reg_operand" "r,r"))
-        (const_int 0)))
-   (clobber (match_scratch:DI 3 "=&r,&r"))]
-  "TARGET_64BIT"
-  "@
-   addc %3,%1,%1\;subfe %3,%1,%3\;addze. %3,%2
-   #"
-  [(set_attr "type" "compare")
-   (set_attr "length" "12,16")])
-
-(define_split
-  [(set (match_operand:CC 0 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC
-        (plus:DI (gt:DI (match_operand:DI 1 "gpc_reg_operand" "")
-                        (const_int 0))
-                 (match_operand:DI 2 "gpc_reg_operand" ""))
-        (const_int 0)))
-   (clobber (match_scratch:DI 3 ""))]
-  "TARGET_64BIT && reload_completed"
-  [(set (match_dup 3)
-       (plus:DI (gt:DI (match_dup 1) (const_int 0))
-                (match_dup 2)))
-   (set (match_dup 0)
-       (compare:CC (match_dup 3)
-                   (const_int 0)))]
-  "")
-
-(define_insn ""
-  [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
-       (compare:CC
-        (plus:SI (gt:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
-                        (const_int 0))
-                 (match_operand:SI 2 "gpc_reg_operand" "r,r"))
-        (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "=&r,&r")
-       (plus:SI (gt:SI (match_dup 1) (const_int 0)) (match_dup 2)))]
-  "TARGET_32BIT"
-  "@
-   addc %0,%1,%1\;subfe %0,%1,%0\;addze. %0,%2
-   #"
-  [(set_attr "type" "compare")
-   (set_attr "length" "12,16")])
-
-(define_split
-  [(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "")
-       (compare:CC
-        (plus:SI (gt:SI (match_operand:SI 1 "gpc_reg_operand" "")
-                        (const_int 0))
-                 (match_operand:SI 2 "gpc_reg_operand" ""))
-        (const_int 0)))
-   (set (match_operand:SI 0 "gpc_reg_operand" "")
-       (plus:SI (gt:SI (match_dup 1) (const_int 0)) (match_dup 2)))]
-  "TARGET_32BIT && reload_completed"
-  [(set (match_dup 0)
-       (plus:SI (gt:SI (match_dup 1) (const_int 0)) (match_dup 2)))
-   (set (match_dup 3)
-       (compare:CC (match_dup 0)
-                   (const_int 0)))]
-  "")
-
-(define_insn ""
-  [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
-       (compare:CC
-        (plus:DI (gt:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
-                        (const_int 0))
-                 (match_operand:DI 2 "gpc_reg_operand" "r,r"))
-        (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "=&r,&r")
-       (plus:DI (gt:DI (match_dup 1) (const_int 0)) (match_dup 2)))]
-  "TARGET_64BIT"
-  "@
-   addc %0,%1,%1\;subfe %0,%1,%0\;addze. %0,%2
-   #"
-  [(set_attr "type" "compare")
-   (set_attr "length" "12,16")])
-
-(define_split
-  [(set (match_operand:CC 3 "cc_reg_not_micro_cr0_operand" "")
-       (compare:CC
-        (plus:DI (gt:DI (match_operand:DI 1 "gpc_reg_operand" "")
-                        (const_int 0))
-                 (match_operand:DI 2 "gpc_reg_operand" ""))
-        (const_int 0)))
-   (set (match_operand:DI 0 "gpc_reg_operand" "")
-       (plus:DI (gt:DI (match_dup 1) (const_int 0)) (match_dup 2)))]
-  "TARGET_64BIT && reload_completed"
-  [(set (match_dup 0)
-       (plus:DI (gt:DI (match_dup 1) (const_int 0)) (match_dup 2)))
-   (set (match_dup 3)
-       (compare:CC (match_dup 0)
-                   (const_int 0)))]
-  "")
-
-(define_insn_and_split "*gtu<mode>"
-  [(set (match_operand:P 0 "gpc_reg_operand" "=r")
-       (gtu:P (match_operand:P 1 "gpc_reg_operand" "r")
-              (match_operand:P 2 "reg_or_short_operand" "rI")))]
-  ""
-  "#"
-  ""
-  [(set (match_dup 0) (neg:P (gtu:P (match_dup 1) (match_dup 2))))
-   (set (match_dup 0) (neg:P (match_dup 0)))]
-  "")
-
-(define_insn_and_split "*gtu<mode>_compare"
-  [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
-       (compare:CC
-        (gtu:P (match_operand:P 1 "gpc_reg_operand" "r,r")
-                (match_operand:P 2 "reg_or_short_operand" "rI,rI"))
-        (const_int 0)))
-   (set (match_operand:P 0 "gpc_reg_operand" "=r,r")
-       (gtu:P (match_dup 1) (match_dup 2)))]
-  ""
-  "#"
-  ""
-  [(set (match_dup 0) (neg:P (gtu:P (match_dup 1) (match_dup 2))))
-   (parallel [(set (match_dup 3)
-                  (compare:CC (neg:P (match_dup 0)) (const_int 0)))
-             (set (match_dup 0) (neg:P (match_dup 0)))])]
-  "")
-
-(define_insn_and_split "*plus_gtu<mode>"
-  [(set (match_operand:P 0 "gpc_reg_operand" "=&r")
-        (plus:P (gtu:P (match_operand:P 1 "gpc_reg_operand" "r")
-                      (match_operand:P 2 "reg_or_short_operand" "rI"))
-               (match_operand:P 3 "gpc_reg_operand" "r")))]
-  ""
-  "#"
-  "&& !reg_overlap_mentioned_p (operands[0], operands[3])"
-  [(set (match_dup 0) (neg:P (gtu:P (match_dup 1) (match_dup 2))))
-   (set (match_dup 0) (minus:P (match_dup 3) (match_dup 0)))]
-  "")
-
-(define_insn_and_split "*plus_gtu<mode>_1"
-  [(set (match_operand:P 0 "gpc_reg_operand" "=&r")
-        (plus:P (gtu:P (match_operand:P 1 "gpc_reg_operand" "r")
-                      (match_operand:P 2 "reg_or_short_operand" "rI"))
-               (match_operand:P 3 "short_cint_operand" "I")))]
-  ""
-  "#"
-  "&& !reg_overlap_mentioned_p (operands[0], operands[3])"
-  [(set (match_dup 0) (neg:P (gtu:P (match_dup 1) (match_dup 2))))
-   (parallel [(set (match_dup 0) (minus:P (match_dup 3) (match_dup 0)))
-             (clobber (reg:P CA_REGNO))])]
-  "")
-
-(define_insn_and_split "*plus_gtu<mode>_compare"
-  [(set (match_operand:CC 4 "cc_reg_operand" "=x,x,?y,?y")
-       (compare:CC
-        (plus:P (gtu:P (match_operand:P 1 "gpc_reg_operand" "r,r,r,r")
-                       (match_operand:P 2 "reg_or_short_operand" "I,r,I,r"))
-                (match_operand:P 3 "gpc_reg_operand" "r,r,r,r"))
-        (const_int 0)))
-   (set (match_operand:P 0 "gpc_reg_operand" "=&r,&r,&r,&r")
-       (plus:P (gtu:P (match_dup 1) (match_dup 2)) (match_dup 3)))]
-  ""
-  "#"
-  "&& !reg_overlap_mentioned_p (operands[0], operands[3])"
-  [(set (match_dup 0) (neg:P (gtu:P (match_dup 1) (match_dup 2))))
-   (parallel [(set (match_dup 4)
-                  (compare:CC (minus:P (match_dup 3) (match_dup 0))
-                              (const_int 0)))
-             (set (match_dup 0) (minus:P (match_dup 3) (match_dup 0)))])]
-  "")
-
-(define_insn "*neg_gtu<mode>"
-  [(set (match_operand:P 0 "gpc_reg_operand" "=r")
-       (neg:P (gtu:P (match_operand:P 1 "gpc_reg_operand" "r")
-                     (match_operand:P 2 "reg_or_short_operand" "rI"))))]
-  ""
-  "subf%I2c %0,%1,%2\;subfe %0,%0,%0"
-  [(set_attr "type" "two")
-   (set_attr "length" "8")])
+  "#"
+  ""
+  [(parallel [(set (match_dup 5)
+                  (neg:P (match_dup 4)))
+             (set (reg:P CA_REGNO)
+                  (eq:P (match_dup 4)
+                        (const_int 0)))])
+   (parallel [(set (match_dup 0)
+                  (plus:P (plus:P (match_dup 3)
+                                  (reg:P CA_REGNO))
+                          (const_int -1)))
+             (clobber (reg:P CA_REGNO))])]
+{
+  operands[4] = rs6000_emit_eqne (<MODE>mode,
+                                 operands[1], operands[2], operands[4]);
 
+  if (GET_CODE (operands[5]) == SCRATCH)
+    operands[5] = gen_reg_rtx (<MODE>mode);
+}
+  [(set (attr "length")
+       (if_then_else (match_test "operands[2] == const0_rtx")
+                     (const_string "8")
+                     (const_string "12")))])
 \f
 ;; Define both directions of branch and return.  If we need a reload
 ;; register, we'd rather use CR0 since it is much easier to copy a