This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH 07/10] rs6000: The big carry insns addition


Now that everything is in place for letting GCC use the carry-using and
carry-producing machine insns as separate RTL insns, switch over all
remaining patterns that clobber CA without telling the compiler.  This
are the multiple-precision add/sub/neg patterns, and the various eq/ne/
ltu/gtu/leu/geu patterns.

The eq/ne patterns are special.  The optimal machine code for those isn't
regular (like e.g. the ltu patterns are), and we want to implement a plain
eq as "cntlz[wd];sr[wd]i"; but that means that if we split those patterns
at expand time, combine will happily put them back together again.  So
expand them as eq/ne, and split later.


2014-12-08  Segher Boessenkool  <segher@kernel.crashing.org>

gcc/
	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.

---
 gcc/config/rs6000/predicates.md   |    8 +
 gcc/config/rs6000/rs6000-protos.h |    1 +
 gcc/config/rs6000/rs6000.c        |   27 +-
 gcc/config/rs6000/rs6000.md       | 1559 +++++++++----------------------------
 4 files changed, 400 insertions(+), 1195 deletions(-)

diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md
index a19cb2f..8b68f9c 100644
--- a/gcc/config/rs6000/predicates.md
+++ b/gcc/config/rs6000/predicates.md
@@ -1240,6 +1240,14 @@ (define_predicate "rs6000_cbranch_operator"
 				   (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"
diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h
index 8d27a69..eb64598 100644
--- a/gcc/config/rs6000/rs6000-protos.h
+++ b/gcc/config/rs6000/rs6000-protos.h
@@ -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[]);
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index e58fc81..f60f4d7 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -19421,6 +19421,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[])
 {
@@ -19429,12 +19450,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);
 
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index e23fadb..eb15fff 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -1463,13 +1463,26 @@ (define_expand "add<mode>3"
 		  (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]))
@@ -1790,8 +1803,26 @@ (define_expand "sub<mode>3"
 		   (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;
@@ -1934,13 +1965,7 @@ (define_insn "subf<mode>3_carry_in_xx"
   [(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")))]
   ""
@@ -6455,99 +6480,51 @@ (define_insn_and_split "*floatunsdisf2_mem"
 ;; (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
@@ -11745,40 +11722,89 @@ (define_expand "cbranch<mode>4"
   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"
@@ -11786,11 +11812,10 @@ (define_expand "cstore<mode>4"
           (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"
@@ -12262,1109 +12287,265 @@ (define_peephole
   [(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")))])
 
 ;; 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
-- 
1.8.1.4


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]