public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH 03/10] rs6000: Do not use addic in the ctr* splitters
  2014-12-08 14:18 [PATCH 00/10] rs6000: Carry bit improvements Segher Boessenkool
  2014-12-08 14:18 ` [PATCH 02/10] rs6000: Remove addic alternative from various lo_sum patterns Segher Boessenkool
  2014-12-08 14:18 ` [PATCH 01/10] rs6000: Clobber XER[CA] in all user asm statements Segher Boessenkool
@ 2014-12-08 14:18 ` Segher Boessenkool
  2014-12-08 14:28   ` David Edelsohn
  2014-12-08 14:47 ` [PATCH 09/10] rs6000: Remove the (now unused) insn type "compare" Segher Boessenkool
                   ` (6 subsequent siblings)
  9 siblings, 1 reply; 33+ messages in thread
From: Segher Boessenkool @ 2014-12-08 14:18 UTC (permalink / raw)
  To: gcc-patches; +Cc: dje.gcc, Segher Boessenkool

These splitters are only used when for some reason we generated a bdnz
loop but we cannot actually use one (CTR is already used for something
else, for example).  This shouldn't happen often, so making the split
sequence one insn longer isn't a big deal.


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

gcc/
	PR target/64180
	* config/rs6000/rs6000.md (*ctr<mode>_internal1, *ctr<mode>_internal2,
	*ctr<mode>_internal5, *ctr<mode>_internal6): Change "r" alternatives
	to "b".  Increase length.
	(splitters for these): Split to cmp+addi instead of addic.

---
 gcc/config/rs6000/rs6000.md | 42 ++++++++++++++++++++----------------------
 1 file changed, 20 insertions(+), 22 deletions(-)

diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index abf20c3..6f4bafb 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -13496,7 +13496,7 @@ (define_expand "ctr<mode>"
 
 (define_insn "*ctr<mode>_internal1"
   [(set (pc)
-	(if_then_else (ne (match_operand:P 1 "register_operand" "c,*r,*r,*r")
+	(if_then_else (ne (match_operand:P 1 "register_operand" "c,*b,*b,*b")
 			  (const_int 1))
 		      (label_ref (match_operand 0 "" ""))
 		      (pc)))
@@ -13516,11 +13516,11 @@ (define_insn "*ctr<mode>_internal1"
     return \"bdz $+8\;b %l0\";
 }"
   [(set_attr "type" "branch")
-   (set_attr "length" "*,12,16,16")])
+   (set_attr "length" "*,16,20,20")])
 
 (define_insn "*ctr<mode>_internal2"
   [(set (pc)
-	(if_then_else (ne (match_operand:P 1 "register_operand" "c,*r,*r,*r")
+	(if_then_else (ne (match_operand:P 1 "register_operand" "c,*b,*b,*b")
 			  (const_int 1))
 		      (pc)
 		      (label_ref (match_operand 0 "" ""))))
@@ -13540,13 +13540,13 @@ (define_insn "*ctr<mode>_internal2"
     return \"bdnz $+8\;b %l0\";
 }"
   [(set_attr "type" "branch")
-   (set_attr "length" "*,12,16,16")])
+   (set_attr "length" "*,16,20,20")])
 
 ;; Similar but use EQ
 
 (define_insn "*ctr<mode>_internal5"
   [(set (pc)
-	(if_then_else (eq (match_operand:P 1 "register_operand" "c,*r,*r,*r")
+	(if_then_else (eq (match_operand:P 1 "register_operand" "c,*b,*b,*b")
 			  (const_int 1))
 		      (label_ref (match_operand 0 "" ""))
 		      (pc)))
@@ -13566,11 +13566,11 @@ (define_insn "*ctr<mode>_internal5"
     return \"bdnz $+8\;b %l0\";
 }"
   [(set_attr "type" "branch")
-   (set_attr "length" "*,12,16,16")])
+   (set_attr "length" "*,16,20,20")])
 
 (define_insn "*ctr<mode>_internal6"
   [(set (pc)
-	(if_then_else (eq (match_operand:P 1 "register_operand" "c,*r,*r,*r")
+	(if_then_else (eq (match_operand:P 1 "register_operand" "c,*b,*b,*b")
 			  (const_int 1))
 		      (pc)
 		      (label_ref (match_operand 0 "" ""))))
@@ -13590,7 +13590,7 @@ (define_insn "*ctr<mode>_internal6"
     return \"bdz $+8\;b %l0\";
 }"
   [(set_attr "type" "branch")
-   (set_attr "length" "*,12,16,16")])
+   (set_attr "length" "*,16,20,20")])
 
 ;; Now the splitters if we could not allocate the CTR register
 
@@ -13606,13 +13606,12 @@ (define_split
    (clobber (match_scratch:CC 3 ""))
    (clobber (match_scratch:P 4 ""))]
   "reload_completed"
-  [(parallel [(set (match_dup 3)
-		   (compare:CC (plus:P (match_dup 1)
-					(const_int -1))
-			       (const_int 0)))
-	      (set (match_dup 0)
-		   (plus:P (match_dup 1)
-			    (const_int -1)))])
+  [(set (match_dup 3)
+	(compare:CC (match_dup 1)
+		    (const_int 1)))
+   (set (match_dup 0)
+	(plus:P (match_dup 1)
+		(const_int -1)))
    (set (pc) (if_then_else (match_dup 7)
 			   (match_dup 5)
 			   (match_dup 6)))]
@@ -13632,13 +13631,12 @@ (define_split
    (clobber (match_scratch:CC 3 ""))
    (clobber (match_scratch:P 4 ""))]
   "reload_completed && ! gpc_reg_operand (operands[0], SImode)"
-  [(parallel [(set (match_dup 3)
-		   (compare:CC (plus:P (match_dup 1)
-					(const_int -1))
-			       (const_int 0)))
-	      (set (match_dup 4)
-		   (plus:P (match_dup 1)
-			    (const_int -1)))])
+  [(set (match_dup 3)
+	(compare:CC (match_dup 1)
+		    (const_int 1)))
+   (set (match_dup 4)
+	(plus:P (match_dup 1)
+		(const_int -1)))
    (set (match_dup 0)
 	(match_dup 4))
    (set (pc) (if_then_else (match_dup 7)
-- 
1.8.1.4

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH 00/10] rs6000: Carry bit improvements
@ 2014-12-08 14:18 Segher Boessenkool
  2014-12-08 14:18 ` [PATCH 02/10] rs6000: Remove addic alternative from various lo_sum patterns Segher Boessenkool
                   ` (9 more replies)
  0 siblings, 10 replies; 33+ messages in thread
From: Segher Boessenkool @ 2014-12-08 14:18 UTC (permalink / raw)
  To: gcc-patches; +Cc: dje.gcc, Segher Boessenkool

This series makes the PowerPC port deal with the {add,subf}{c,ic,e,ze,me}
instructions directly, not as bigger primitives (which used to be emitted as
multiple machine instructions).

It does this by expanding multi-precision add/sub/neg as well as the unsigned
wordlength sCOND to separate machine insns, which are then simplified where
possible by the combine pass and friends.  For eq/ne this series splits after
combine.

This is PR target/64180.

All patches bootstrapped and tested on powerpc64-linux, runtestflags
-m32,-m64,-m32/-mpowerpc64,-m64/-mlra; also a lot of tiny tests that
I'll submit separately.

Comments?  Is this okay for mainline?


Segher


Segher Boessenkool (10):
  rs6000: Clobber XER[CA] in all user asm statements
  rs6000: Remove addic alternative from various lo_sum patterns
  rs6000: Do not use addic in the ctr* splitters
  rs6000: Remove addic from the normal add pattern
  rs6000: Merge and split add and addic
  rs6000: New add/subf carry insns
  rs6000: The big carry insns addition
  rs6000: compare->two for rld*;rld*.
  rs6000: Remove the (now unused) insn type "compare"
  rs6000: Get rid of the weird decimal thing in add

 gcc/config/rs6000/40x.md          |    2 +-
 gcc/config/rs6000/440.md          |    2 +-
 gcc/config/rs6000/476.md          |    2 +-
 gcc/config/rs6000/601.md          |    2 +-
 gcc/config/rs6000/603.md          |    2 +-
 gcc/config/rs6000/6xx.md          |    2 +-
 gcc/config/rs6000/7450.md         |    2 +-
 gcc/config/rs6000/7xx.md          |    2 +-
 gcc/config/rs6000/8540.md         |    2 +-
 gcc/config/rs6000/cell.md         |   10 +-
 gcc/config/rs6000/darwin.md       |   16 +-
 gcc/config/rs6000/e300c2c3.md     |    2 +-
 gcc/config/rs6000/e500mc.md       |    2 +-
 gcc/config/rs6000/e500mc64.md     |    2 +-
 gcc/config/rs6000/e5500.md        |    2 +-
 gcc/config/rs6000/e6500.md        |    2 +-
 gcc/config/rs6000/mpc.md          |    2 +-
 gcc/config/rs6000/power4.md       |    5 +-
 gcc/config/rs6000/power5.md       |    5 +-
 gcc/config/rs6000/power6.md       |    5 +-
 gcc/config/rs6000/power7.md       |    5 +-
 gcc/config/rs6000/power8.md       |    8 +-
 gcc/config/rs6000/predicates.md   |   14 +
 gcc/config/rs6000/rs6000-protos.h |    1 +
 gcc/config/rs6000/rs6000.c        |   49 +-
 gcc/config/rs6000/rs6000.md       | 1909 ++++++++++++-------------------------
 gcc/config/rs6000/rs64.md         |    2 +-
 gcc/config/rs6000/spe.md          |   18 +-
 28 files changed, 733 insertions(+), 1344 deletions(-)

-- 
1.8.1.4

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH 02/10] rs6000: Remove addic alternative from various lo_sum patterns
  2014-12-08 14:18 [PATCH 00/10] rs6000: Carry bit improvements Segher Boessenkool
@ 2014-12-08 14:18 ` Segher Boessenkool
  2014-12-08 14:27   ` David Edelsohn
  2014-12-08 14:18 ` [PATCH 01/10] rs6000: Clobber XER[CA] in all user asm statements Segher Boessenkool
                   ` (8 subsequent siblings)
  9 siblings, 1 reply; 33+ messages in thread
From: Segher Boessenkool @ 2014-12-08 14:18 UTC (permalink / raw)
  To: gcc-patches; +Cc: dje.gcc, Segher Boessenkool

This means we do not allow GPR0 as base address of those anymore.  The
alternative is to not allow the carry bit to be live over any lo_sum,
which is more expensive.


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

gcc/
	PR target/64180
	* config/rs6000/darwin.md (macho_low_si): Remove "r" alternative.
	(macho_low_di): Ditto.
	* config/rs6000/rs6000.md (*largetoc_low): Ditto.
	(tocref<mode>): Ditto.
	(elf_low): Ditto.
	* config/rs6000/spe.md (mov_si<mode>_e500_subreg0_elf_low_be): Ditto.
	(mov_si<mode>_e500_subreg0_elf_low_le): Ditto.
	(mov_si<mode>_e500_subreg4_elf_low_be): Ditto.  Reformat condition.
	(mov_si<mode>_e500_subreg4_elf_low_le): Ditto.

---
 gcc/config/rs6000/darwin.md | 16 ++++++----------
 gcc/config/rs6000/rs6000.md | 18 +++++++-----------
 gcc/config/rs6000/spe.md    | 18 +++++++++---------
 3 files changed, 22 insertions(+), 30 deletions(-)

diff --git a/gcc/config/rs6000/darwin.md b/gcc/config/rs6000/darwin.md
index 8b816b7..764f847 100644
--- a/gcc/config/rs6000/darwin.md
+++ b/gcc/config/rs6000/darwin.md
@@ -213,22 +213,18 @@ (define_expand "macho_low"
 })
 
 (define_insn "macho_low_si"
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
-	(lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b,!*r")
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+	(lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b")
 		   (match_operand 2 "" "")))]
    "TARGET_MACHO && ! TARGET_64BIT"
-   "@
-    la %0,lo16(%2)(%1)
-    addic %0,%1,lo16(%2)")
+   "la %0,lo16(%2)(%1)")
 
 (define_insn "macho_low_di"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
-	(lo_sum:DI (match_operand:DI 1 "gpc_reg_operand" "b,!*r")
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+	(lo_sum:DI (match_operand:DI 1 "gpc_reg_operand" "b")
 		   (match_operand 2 "" "")))]
    "TARGET_MACHO && TARGET_64BIT"
-   "@
-    la %0,lo16(%2)(%1)
-    addic %0,%1,lo16(%2)")
+   "la %0,lo16(%2)(%1)")
 
 (define_split
   [(set (mem:V4SI (plus:DI (match_operand:DI 0 "gpc_reg_operand" "")
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index f3b5aae..abf20c3 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -10712,13 +10712,11 @@ (define_insn "*largetoc_high_plus_aix<mode>"
    "addis %0,%1+%3@u(%2)")
 
 (define_insn "*largetoc_low"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
-        (lo_sum:DI (match_operand:DI 1 "gpc_reg_operand" "b,!*r")
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+        (lo_sum:DI (match_operand:DI 1 "gpc_reg_operand" "b")
 	           (match_operand:DI 2 "" "")))]
    "TARGET_ELF && TARGET_CMODEL != CMODEL_SMALL"
-   "@
-    addi %0,%1,%2@l
-    addic %0,%1,%2@l")
+   "addi %0,%1,%2@l")
 
 (define_insn "*largetoc_low_aix<mode>"
   [(set (match_operand:P 0 "gpc_reg_operand" "=r")
@@ -10728,7 +10726,7 @@ (define_insn "*largetoc_low_aix<mode>"
    "la %0,%2@l(%1)")
 
 (define_insn_and_split "*tocref<mode>"
-  [(set (match_operand:P 0 "gpc_reg_operand" "=b*r")
+  [(set (match_operand:P 0 "gpc_reg_operand" "=b")
 	(match_operand:P 1 "small_toc_ref" "R"))]
    "TARGET_TOC"
    "la %0,%a1"
@@ -10747,13 +10745,11 @@ (define_insn "elf_high"
   "lis %0,%1@ha")
 
 (define_insn "elf_low"
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
-	(lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b,!*r")
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+	(lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b")
 		   (match_operand 2 "" "")))]
    "TARGET_ELF && ! TARGET_64BIT"
-   "@
-    la %0,%2@l(%1)
-    addic %0,%1,%K2")
+   "la %0,%2@l(%1)")
 \f
 ;; Call and call_value insns
 (define_expand "call"
diff --git a/gcc/config/rs6000/spe.md b/gcc/config/rs6000/spe.md
index 8eec7b7..07c293c 100644
--- a/gcc/config/rs6000/spe.md
+++ b/gcc/config/rs6000/spe.md
@@ -2519,7 +2519,7 @@ (define_insn "*mov_si<mode>_e500_subreg0_le"
 
 (define_insn_and_split "*mov_si<mode>_e500_subreg0_elf_low_be"
   [(set (subreg:SI (match_operand:SPE64TF 0 "register_operand" "+r") 0)
-	(lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "r")
+	(lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b")
 		   (match_operand 2 "" "")))]
   "WORDS_BIG_ENDIAN
    && (((TARGET_E500_DOUBLE && (<MODE>mode == DFmode || <MODE>mode == TFmode))
@@ -2538,13 +2538,13 @@ (define_insn_and_split "*mov_si<mode>_e500_subreg0_elf_low_be"
 
 (define_insn "*mov_si<mode>_e500_subreg0_elf_low_le"
   [(set (subreg:SI (match_operand:SPE64TF 0 "register_operand" "+r") 0)
-	(lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "r")
+	(lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b")
 		   (match_operand 2 "" "")))]
   "!WORDS_BIG_ENDIAN
    && (((TARGET_E500_DOUBLE && (<MODE>mode == DFmode || <MODE>mode == TFmode))
 	|| (TARGET_SPE && <MODE>mode != DFmode && <MODE>mode != TFmode))
        && TARGET_ELF && !TARGET_64BIT)"
-  "addic %0,%1,%K2")
+  "addi %0,%1,%K2")
 
 ;; ??? Could use evstwwe for memory stores in some cases, depending on
 ;; the offset.
@@ -2592,17 +2592,17 @@ (define_insn "mov_si<mode>_e500_subreg4_le"
 
 (define_insn "*mov_si<mode>_e500_subreg4_elf_low_be"
   [(set (subreg:SI (match_operand:SPE64TF 0 "register_operand" "+r") 4)
-	(lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "r")
+	(lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b")
 		   (match_operand 2 "" "")))]
   "WORDS_BIG_ENDIAN
-   && (((TARGET_E500_DOUBLE && (<MODE>mode == DFmode || <MODE>mode == TFmode))
-	|| (TARGET_SPE && <MODE>mode != DFmode && <MODE>mode != TFmode))
-       && TARGET_ELF && !TARGET_64BIT)"
-  "addic %0,%1,%K2")
+   && ((TARGET_E500_DOUBLE && (<MODE>mode == DFmode || <MODE>mode == TFmode))
+       || (TARGET_SPE && <MODE>mode != DFmode && <MODE>mode != TFmode))
+   && TARGET_ELF && !TARGET_64BIT"
+  "addi %0,%1,%K2")
 
 (define_insn_and_split "*mov_si<mode>_e500_subreg4_elf_low_le"
   [(set (subreg:SI (match_operand:SPE64TF 0 "register_operand" "+r") 4)
-	(lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "r")
+	(lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b")
 		   (match_operand 2 "" "")))]
   "!WORDS_BIG_ENDIAN
    && (((TARGET_E500_DOUBLE && (<MODE>mode == DFmode || <MODE>mode == TFmode))
-- 
1.8.1.4

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH 01/10] rs6000: Clobber XER[CA] in all user asm statements
  2014-12-08 14:18 [PATCH 00/10] rs6000: Carry bit improvements Segher Boessenkool
  2014-12-08 14:18 ` [PATCH 02/10] rs6000: Remove addic alternative from various lo_sum patterns Segher Boessenkool
@ 2014-12-08 14:18 ` Segher Boessenkool
  2014-12-08 14:25   ` David Edelsohn
  2015-01-19  8:41   ` Hans-Peter Nilsson
  2014-12-08 14:18 ` [PATCH 03/10] rs6000: Do not use addic in the ctr* splitters Segher Boessenkool
                   ` (7 subsequent siblings)
  9 siblings, 2 replies; 33+ messages in thread
From: Segher Boessenkool @ 2014-12-08 14:18 UTC (permalink / raw)
  To: gcc-patches; +Cc: dje.gcc, Segher Boessenkool

A lot of old user code clobbers the carry bit without telling the compiler
about it.  This used to just work, because the compiler never used the bit
outside of a single RTL instruction.  But that will change.  Let's clobber
the carry bit in every asm; this isn't very expensive.


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

gcc/
	PR target/64180
	* config/rs6000/rs6000.c (TARGET_MD_ASM_CLOBBERS): Define.
	(rs6000_md_asm_clobbers): New function.

---
 gcc/config/rs6000/rs6000.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index cdb9de9..e58fc81 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -1556,6 +1556,9 @@ static const struct attribute_spec rs6000_attribute_table[] =
 #undef TARGET_ASM_LOOP_ALIGN_MAX_SKIP
 #define TARGET_ASM_LOOP_ALIGN_MAX_SKIP rs6000_loop_align_max_skip
 
+#undef TARGET_MD_ASM_CLOBBERS
+#define TARGET_MD_ASM_CLOBBERS rs6000_md_asm_clobbers
+
 #undef TARGET_OPTION_OVERRIDE
 #define TARGET_OPTION_OVERRIDE rs6000_option_override
 
@@ -3146,6 +3149,19 @@ rs6000_builtin_mask_calculate (void)
 	  | ((TARGET_LONG_DOUBLE_128)	    ? RS6000_BTM_LDBL128 : 0));
 }
 
+/* Implement TARGET_MD_ASM_CLOBBERS.  All asm statements are considered
+   to clobber the XER[CA] bit because clobbering that bit without telling
+   the compiler worked just fine with versions of GCC before GCC 5, and
+   breaking a lot of older code in ways that are hard to track down is
+   not such a great idea.  */
+
+static tree
+rs6000_md_asm_clobbers (tree, tree, tree clobbers)
+{
+  tree s = build_string (strlen (reg_names[CA_REGNO]), reg_names[CA_REGNO]);
+  return tree_cons (NULL_TREE, s, clobbers);
+}
+
 /* Override command line options.  Mostly we process the processor type and
    sometimes adjust other TARGET_ options.  */
 
-- 
1.8.1.4

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH 01/10] rs6000: Clobber XER[CA] in all user asm statements
  2014-12-08 14:18 ` [PATCH 01/10] rs6000: Clobber XER[CA] in all user asm statements Segher Boessenkool
@ 2014-12-08 14:25   ` David Edelsohn
  2014-12-09 21:48     ` Richard Henderson
  2015-01-19  8:41   ` Hans-Peter Nilsson
  1 sibling, 1 reply; 33+ messages in thread
From: David Edelsohn @ 2014-12-08 14:25 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: GCC Patches

On Mon, Dec 8, 2014 at 9:18 AM, Segher Boessenkool
<segher@kernel.crashing.org> wrote:
> A lot of old user code clobbers the carry bit without telling the compiler
> about it.  This used to just work, because the compiler never used the bit
> outside of a single RTL instruction.  But that will change.  Let's clobber
> the carry bit in every asm; this isn't very expensive.
>
>
> 2014-12-08  Segher Boessenkool  <segher@kernel.crashing.org>
>
> gcc/
>         PR target/64180
>         * config/rs6000/rs6000.c (TARGET_MD_ASM_CLOBBERS): Define.
>         (rs6000_md_asm_clobbers): New function.

Okay.  I don't know of another option that preserves backward
compatibility.  If RTH looks at this series of patches, he may have a
better suggestion.

Thanks, David

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH 02/10] rs6000: Remove addic alternative from various lo_sum patterns
  2014-12-08 14:18 ` [PATCH 02/10] rs6000: Remove addic alternative from various lo_sum patterns Segher Boessenkool
@ 2014-12-08 14:27   ` David Edelsohn
  0 siblings, 0 replies; 33+ messages in thread
From: David Edelsohn @ 2014-12-08 14:27 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: GCC Patches

On Mon, Dec 8, 2014 at 9:18 AM, Segher Boessenkool
<segher@kernel.crashing.org> wrote:
> This means we do not allow GPR0 as base address of those anymore.  The
> alternative is to not allow the carry bit to be live over any lo_sum,
> which is more expensive.
>
>
> 2014-12-08  Segher Boessenkool  <segher@kernel.crashing.org>
>
> gcc/
>         PR target/64180
>         * config/rs6000/darwin.md (macho_low_si): Remove "r" alternative.
>         (macho_low_di): Ditto.
>         * config/rs6000/rs6000.md (*largetoc_low): Ditto.
>         (tocref<mode>): Ditto.
>         (elf_low): Ditto.
>         * config/rs6000/spe.md (mov_si<mode>_e500_subreg0_elf_low_be): Ditto.
>         (mov_si<mode>_e500_subreg0_elf_low_le): Ditto.
>         (mov_si<mode>_e500_subreg4_elf_low_be): Ditto.  Reformat condition.
>         (mov_si<mode>_e500_subreg4_elf_low_le): Ditto.

Okay.

Thanks, David

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH 03/10] rs6000: Do not use addic in the ctr* splitters
  2014-12-08 14:18 ` [PATCH 03/10] rs6000: Do not use addic in the ctr* splitters Segher Boessenkool
@ 2014-12-08 14:28   ` David Edelsohn
  0 siblings, 0 replies; 33+ messages in thread
From: David Edelsohn @ 2014-12-08 14:28 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: GCC Patches

On Mon, Dec 8, 2014 at 9:18 AM, Segher Boessenkool
<segher@kernel.crashing.org> wrote:
> These splitters are only used when for some reason we generated a bdnz
> loop but we cannot actually use one (CTR is already used for something
> else, for example).  This shouldn't happen often, so making the split
> sequence one insn longer isn't a big deal.
>
>
> 2014-12-08  Segher Boessenkool  <segher@kernel.crashing.org>
>
> gcc/
>         PR target/64180
>         * config/rs6000/rs6000.md (*ctr<mode>_internal1, *ctr<mode>_internal2,
>         *ctr<mode>_internal5, *ctr<mode>_internal6): Change "r" alternatives
>         to "b".  Increase length.
>         (splitters for these): Split to cmp+addi instead of addic.

Okay.

Thanks, David

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH 04/10] rs6000: Remove addic from the normal add pattern
  2014-12-08 14:47 ` [PATCH 04/10] rs6000: Remove addic from the normal add pattern Segher Boessenkool
@ 2014-12-08 14:44   ` David Edelsohn
  2014-12-08 15:01     ` Segher Boessenkool
  0 siblings, 1 reply; 33+ messages in thread
From: David Edelsohn @ 2014-12-08 14:44 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: GCC Patches

On Mon, Dec 8, 2014 at 9:18 AM, Segher Boessenkool
<segher@kernel.crashing.org> wrote:
> This means we can no longer add GPR0+imm.  Register allocation will have
> to use a different register.
>
>
> 2014-12-08  Segher Boessenkool  <segher@kernel.crashing.org>
>
> gcc/
>         PR target/64180
>         * config/rs6000/rs6000.md (*add<mode>3_internal1): Remove addic
>         alternative.
>
> ---
>  gcc/config/rs6000/rs6000.md | 9 +++------
>  1 file changed, 3 insertions(+), 6 deletions(-)
>
> diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
> index 6f4bafb..1647f8b 100644
> --- a/gcc/config/rs6000/rs6000.md
> +++ b/gcc/config/rs6000/rs6000.md
> @@ -1491,17 +1491,14 @@ (define_expand "add<mode>3"
>      }
>  })
>
> -;; Discourage ai/addic because of carry but provide it in an alternative
> -;; allowing register zero as source.
>  (define_insn "*add<mode>3_internal1"
> -  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r,r,?r,r")
> -       (plus:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,b,r,b")
> -                 (match_operand:GPR 2 "add_operand" "r,I,I,L")))]
> +  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r,r,r")
> +       (plus:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,b,b")
> +                 (match_operand:GPR 2 "add_operand" "r,I,L")))]
>    "!DECIMAL_FLOAT_MODE_P (GET_MODE (operands[0])) && !DECIMAL_FLOAT_MODE_P (GET_MODE (operands[1]))"
>    "@
>     add %0,%1,%2
>     addi %0,%1,%2
> -   addic %0,%1,%2
>     addis %0,%1,%v2"
>    [(set_attr "type" "add")])
>
> --
> 1.8.1.4
>

Why are you removing the alternative instead of clobbering XER[CA]?

Thanks, David

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH 08/10] rs6000: compare->two for rld*;rld*.
  2014-12-08 14:18 [PATCH 00/10] rs6000: Carry bit improvements Segher Boessenkool
                   ` (3 preceding siblings ...)
  2014-12-08 14:47 ` [PATCH 09/10] rs6000: Remove the (now unused) insn type "compare" Segher Boessenkool
@ 2014-12-08 14:47 ` Segher Boessenkool
  2014-12-09 18:56   ` David Edelsohn
  2014-12-08 14:47 ` [PATCH 06/10] rs6000: New add/subf carry insns Segher Boessenkool
                   ` (4 subsequent siblings)
  9 siblings, 1 reply; 33+ messages in thread
From: Segher Boessenkool @ 2014-12-08 14:47 UTC (permalink / raw)
  To: gcc-patches; +Cc: dje.gcc, Segher Boessenkool

These now are the only remaining patterns that have type "compare".
And they shouldn't: "two" is a better type for them.


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

gcc/
	* config/rs6000/rs6000.md (*anddi3_2rld_dot, *anddi3_rld_dot2):
	Change type from "compare" to "two".

---
 gcc/config/rs6000/rs6000.md | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index eb15fff..d0b8bc8 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -7341,7 +7341,7 @@ (define_insn_and_split "*anddi3_2rld_dot"
 {
   build_mask64_2_operands (operands[2], &operands[4]);
 }
-  [(set_attr "type" "compare")
+  [(set_attr "type" "two")
    (set_attr "dot" "yes")
    (set_attr "length" "8,12")])
 
@@ -7374,7 +7374,7 @@ (define_insn_and_split "*anddi3_2rld_dot2"
 {
   build_mask64_2_operands (operands[2], &operands[4]);
 }
-  [(set_attr "type" "compare")
+  [(set_attr "type" "two")
    (set_attr "dot" "yes")
    (set_attr "length" "8,12")])
 \f
-- 
1.8.1.4

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH 10/10] rs6000: Get rid of the weird decimal thing in add
  2014-12-08 14:18 [PATCH 00/10] rs6000: Carry bit improvements Segher Boessenkool
                   ` (8 preceding siblings ...)
  2014-12-08 14:47 ` [PATCH 07/10] rs6000: The big carry insns addition Segher Boessenkool
@ 2014-12-08 14:47 ` Segher Boessenkool
  2014-12-09 18:57   ` David Edelsohn
  9 siblings, 1 reply; 33+ messages in thread
From: Segher Boessenkool @ 2014-12-08 14:47 UTC (permalink / raw)
  To: gcc-patches; +Cc: dje.gcc, Segher Boessenkool

Peter tells me it was an artifact of old versions of the DFP code.  The
condition can never be false; delete it.


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

gcc/
	* config/rs6000/rs6000.md (*add<mode>3): Remove condition.

---
 gcc/config/rs6000/rs6000.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index a544e57..6724819 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -1506,7 +1506,7 @@ (define_insn "*add<mode>3"
   [(set (match_operand:GPR 0 "gpc_reg_operand" "=r,r,r")
 	(plus:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,b,b")
 		  (match_operand:GPR 2 "add_operand" "r,I,L")))]
-  "!DECIMAL_FLOAT_MODE_P (GET_MODE (operands[0])) && !DECIMAL_FLOAT_MODE_P (GET_MODE (operands[1]))"
+  ""
   "@
    add %0,%1,%2
    addi %0,%1,%2
-- 
1.8.1.4

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH 06/10] rs6000: New add/subf carry insns
  2014-12-08 14:18 [PATCH 00/10] rs6000: Carry bit improvements Segher Boessenkool
                   ` (4 preceding siblings ...)
  2014-12-08 14:47 ` [PATCH 08/10] rs6000: compare->two for rld*;rld* Segher Boessenkool
@ 2014-12-08 14:47 ` Segher Boessenkool
  2014-12-08 15:41   ` David Edelsohn
  2014-12-08 14:47 ` [PATCH 05/10] rs6000: Merge and split add and addic Segher Boessenkool
                   ` (3 subsequent siblings)
  9 siblings, 1 reply; 33+ messages in thread
From: Segher Boessenkool @ 2014-12-08 14:47 UTC (permalink / raw)
  To: gcc-patches; +Cc: dje.gcc, Segher Boessenkool

This implements addc, addic, adde, addze, addme, subfc, subfic, subfe,
subfze, subfme.  Some of those in multiple forms: canonical RTL for the
"immediate" insns has four forms; subfX has a special form for subtracting
a register from itself.

All these new insns get type "add" for now.


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

gcc/
	PR target/64180
	* config/rs6000/predicates.md (adde_operand): New.
	* config/rs6000/rs6000.md (add<mode>3_carry): New.
	(add<mode>3_imm_carry_pos): New.
	(add<mode>3_imm_carry_0): New.
	(add<mode>3_imm_carry_m1): New.
	(add<mode>3_imm_carry_neg): New.
	(add<mode>3_carry_in): New.
	(add<mode>3_carry_in_0): New.
	(add<mode>3_carry_in_m1): New.
	(subf<mode>3_carry): New.
	(subf<mode>3_imm_carry_0): New.
	(subf<mode>3_imm_carry_m1): New.
	(subf<mode>3_carry_in): New.
	(subf<mode>3_carry_in_0): New.
	(subf<mode>3_carry_in_m1): New.
	(subf<mode>3_carry_in_xx): New.

---
 gcc/config/rs6000/predicates.md |   6 ++
 gcc/config/rs6000/rs6000.md     | 162 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 168 insertions(+)

diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md
index ea230a5..a19cb2f 100644
--- a/gcc/config/rs6000/predicates.md
+++ b/gcc/config/rs6000/predicates.md
@@ -788,6 +788,12 @@ (define_predicate "add_operand"
 		 || satisfies_constraint_L (op)")
     (match_operand 0 "gpc_reg_operand")))
 
+;; Return 1 if the operand is either a non-special register, or 0, or -1.
+(define_predicate "adde_operand"
+  (if_then_else (match_code "const_int")
+    (match_test "INTVAL (op) == 0 || INTVAL (op) == -1")
+    (match_operand 0 "gpc_reg_operand")))
+
 ;; Return 1 if OP is a constant but not a valid add_operand.
 (define_predicate "non_add_cint_operand"
   (and (match_code "const_int")
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index dcdb7c1..e23fadb 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -1634,6 +1634,96 @@ (define_split
     FAIL;
 })
 
+
+(define_insn "add<mode>3_carry"
+  [(set (match_operand:P 0 "gpc_reg_operand" "=r")
+	(plus:P (match_operand:P 1 "gpc_reg_operand" "r")
+		(match_operand:P 2 "reg_or_short_operand" "rI")))
+   (set (reg:P CA_REGNO)
+	(ltu:P (plus:P (match_dup 1)
+		       (match_dup 2))
+	       (match_dup 1)))]
+  ""
+  "add%I2c %0,%1,%2"
+  [(set_attr "type" "add")])
+
+(define_insn "*add<mode>3_imm_carry_pos"
+  [(set (match_operand:P 0 "gpc_reg_operand" "=r")
+	(plus:P (match_operand:P 1 "gpc_reg_operand" "r")
+		(match_operand:P 2 "short_cint_operand" "n")))
+   (set (reg:P CA_REGNO)
+	(geu:P (match_dup 1)
+	       (match_operand:P 3 "const_int_operand" "n")))]
+  "INTVAL (operands[2]) > 0
+   && INTVAL (operands[2]) + INTVAL (operands[3]) == 0"
+  "addic %0,%1,%2"
+  [(set_attr "type" "add")])
+
+(define_insn "*add<mode>3_imm_carry_0"
+  [(set (match_operand:P 0 "gpc_reg_operand" "=r")
+	(match_operand:P 1 "gpc_reg_operand" "r"))
+   (set (reg:P CA_REGNO)
+	(const_int 0))]
+  ""
+  "addic %0,%1,0"
+  [(set_attr "type" "add")])
+
+(define_insn "*add<mode>3_imm_carry_m1"
+  [(set (match_operand:P 0 "gpc_reg_operand" "=r")
+	(plus:P (match_operand:P 1 "gpc_reg_operand" "r")
+		(const_int -1)))
+   (set (reg:P CA_REGNO)
+	(ne:P (match_dup 1)
+	      (const_int 0)))]
+  ""
+  "addic %0,%1,-1"
+  [(set_attr "type" "add")])
+
+(define_insn "*add<mode>3_imm_carry_neg"
+  [(set (match_operand:P 0 "gpc_reg_operand" "=r")
+	(plus:P (match_operand:P 1 "gpc_reg_operand" "r")
+		(match_operand:P 2 "short_cint_operand" "n")))
+   (set (reg:P CA_REGNO)
+	(gtu:P (match_dup 1)
+	       (match_operand:P 3 "const_int_operand" "n")))]
+  "INTVAL (operands[2]) < 0
+   && INTVAL (operands[2]) + INTVAL (operands[3]) == -1"
+  "addic %0,%1,%2"
+  [(set_attr "type" "add")])
+
+
+(define_insn "add<mode>3_carry_in"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
+	(plus:GPR (plus:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r")
+			    (match_operand:GPR 2 "adde_operand" "r,n"))
+		  (reg:GPR CA_REGNO)))
+   (clobber (reg:GPR CA_REGNO))]
+  ""
+  "@
+   adde %0,%1,%2
+   add%G2e %0,%1"
+  [(set_attr "type" "add")])
+
+(define_insn "add<mode>3_carry_in_0"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
+	(plus:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r")
+		  (reg:GPR CA_REGNO)))
+   (clobber (reg:GPR CA_REGNO))]
+  ""
+  "addze %0,%1"
+  [(set_attr "type" "add")])
+
+(define_insn "add<mode>3_carry_in_m1"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
+	(plus:GPR (plus:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r")
+			    (reg:GPR CA_REGNO))
+		  (const_int -1)))
+   (clobber (reg:GPR CA_REGNO))]
+  ""
+  "addme %0,%1"
+  [(set_attr "type" "add")])
+
+
 (define_expand "one_cmpl<mode>2"
   [(set (match_operand:SDI 0 "gpc_reg_operand" "")
 	(not:SDI (match_operand:SDI 1 "gpc_reg_operand" "")))]
@@ -1772,6 +1862,78 @@ (define_insn "subf<mode>3_imm"
   [(set_attr "type" "add")])
 
 
+(define_insn "subf<mode>3_carry"
+  [(set (match_operand:P 0 "gpc_reg_operand" "=r")
+	(minus:P (match_operand:P 2 "reg_or_short_operand" "rI")
+		 (match_operand:P 1 "gpc_reg_operand" "r")))
+   (set (reg:P CA_REGNO)
+	(leu:P (match_dup 1)
+	       (match_dup 2)))]
+  ""
+  "subf%I2c %0,%1,%2"
+  [(set_attr "type" "add")])
+
+(define_insn "*subf<mode>3_imm_carry_0"
+  [(set (match_operand:P 0 "gpc_reg_operand" "=r")
+	(neg:P (match_operand:P 1 "gpc_reg_operand" "r")))
+   (set (reg:P CA_REGNO)
+	(eq:P (match_dup 1)
+	      (const_int 0)))]
+  ""
+  "subfic %0,%1,0"
+  [(set_attr "type" "add")])
+
+(define_insn "*subf<mode>3_imm_carry_m1"
+  [(set (match_operand:P 0 "gpc_reg_operand" "=r")
+	(not:P (match_operand:P 1 "gpc_reg_operand" "r")))
+   (set (reg:P CA_REGNO)
+	(const_int 1))]
+  ""
+  "subfic %0,%1,-1"
+  [(set_attr "type" "add")])
+
+
+(define_insn "subf<mode>3_carry_in"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
+	(plus:GPR (plus:GPR (not:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r"))
+			    (reg:GPR CA_REGNO))
+		  (match_operand:GPR 2 "adde_operand" "r,n")))
+   (clobber (reg:GPR CA_REGNO))]
+  ""
+  "@
+   subfe %0,%1,%2
+   subf%G2e %0,%1"
+  [(set_attr "type" "add")])
+
+(define_insn "*subf<mode>3_carry_in_0"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+	(plus:GPR (not:GPR (match_operand:GPR 1 "gpc_reg_operand" "r"))
+		  (reg:GPR CA_REGNO)))
+   (clobber (reg:GPR CA_REGNO))]
+  ""
+  "subfze %0,%1"
+  [(set_attr "type" "add")])
+
+(define_insn "*subf<mode>3_carry_in_m1"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+	(plus:GPR (plus:GPR (not:GPR (match_operand:GPR 1 "gpc_reg_operand" "r"))
+			    (reg:GPR CA_REGNO))
+		  (const_int -1)))
+   (clobber (reg:GPR CA_REGNO))]
+  ""
+  "subfme %0,%1"
+  [(set_attr "type" "add")])
+
+(define_insn "subf<mode>3_carry_in_xx"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+	(plus:GPR (reg:GPR CA_REGNO)
+		  (const_int -1)))
+   (clobber (reg:GPR CA_REGNO))]
+  ""
+  "subfe %0,%0,%0"
+  [(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" "")))]
-- 
1.8.1.4

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH 04/10] rs6000: Remove addic from the normal add pattern
  2014-12-08 14:18 [PATCH 00/10] rs6000: Carry bit improvements Segher Boessenkool
                   ` (6 preceding siblings ...)
  2014-12-08 14:47 ` [PATCH 05/10] rs6000: Merge and split add and addic Segher Boessenkool
@ 2014-12-08 14:47 ` Segher Boessenkool
  2014-12-08 14:44   ` David Edelsohn
  2014-12-08 14:47 ` [PATCH 07/10] rs6000: The big carry insns addition Segher Boessenkool
  2014-12-08 14:47 ` [PATCH 10/10] rs6000: Get rid of the weird decimal thing in add Segher Boessenkool
  9 siblings, 1 reply; 33+ messages in thread
From: Segher Boessenkool @ 2014-12-08 14:47 UTC (permalink / raw)
  To: gcc-patches; +Cc: dje.gcc, Segher Boessenkool

This means we can no longer add GPR0+imm.  Register allocation will have
to use a different register.


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

gcc/
	PR target/64180
	* config/rs6000/rs6000.md (*add<mode>3_internal1): Remove addic
	alternative.

---
 gcc/config/rs6000/rs6000.md | 9 +++------
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index 6f4bafb..1647f8b 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -1491,17 +1491,14 @@ (define_expand "add<mode>3"
     }
 })
 
-;; Discourage ai/addic because of carry but provide it in an alternative
-;; allowing register zero as source.
 (define_insn "*add<mode>3_internal1"
-  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r,r,?r,r")
-	(plus:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,b,r,b")
-		  (match_operand:GPR 2 "add_operand" "r,I,I,L")))]
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r,r,r")
+	(plus:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,b,b")
+		  (match_operand:GPR 2 "add_operand" "r,I,L")))]
   "!DECIMAL_FLOAT_MODE_P (GET_MODE (operands[0])) && !DECIMAL_FLOAT_MODE_P (GET_MODE (operands[1]))"
   "@
    add %0,%1,%2
    addi %0,%1,%2
-   addic %0,%1,%2
    addis %0,%1,%v2"
   [(set_attr "type" "add")])
 
-- 
1.8.1.4

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH 05/10] rs6000: Merge and split add and addic
  2014-12-08 14:18 [PATCH 00/10] rs6000: Carry bit improvements Segher Boessenkool
                   ` (5 preceding siblings ...)
  2014-12-08 14:47 ` [PATCH 06/10] rs6000: New add/subf carry insns Segher Boessenkool
@ 2014-12-08 14:47 ` Segher Boessenkool
  2014-12-08 15:31   ` David Edelsohn
  2014-12-08 14:47 ` [PATCH 04/10] rs6000: Remove addic from the normal add pattern Segher Boessenkool
                   ` (2 subsequent siblings)
  9 siblings, 1 reply; 33+ messages in thread
From: Segher Boessenkool @ 2014-12-08 14:47 UTC (permalink / raw)
  To: gcc-patches; +Cc: dje.gcc, Segher Boessenkool

This splits the addic patterns from the add/addi patterns, and merges the
insns and splitters.
Also change type "compare" to "add" for "addic." (the dot form).


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

gcc/
	PR target/64180
	* config/rs6000/rs6000.md (*add<mode>3_internal1): Rename to
	"*add<mode>3".
	(*add<mode>3_internal2, *add<mode>3_internal3, and (their splitters):
	Delete.
	(*add<mode>3_dot, *add<mode>3_dot2): New.
	(*add<mode>3_imm_dot, *add<mode>3_imm_dot2): New.

---
 gcc/config/rs6000/rs6000.md | 119 +++++++++++++++++++++++++++-----------------
 1 file changed, 74 insertions(+), 45 deletions(-)

diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index 1647f8b..dcdb7c1 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -1491,7 +1491,7 @@ (define_expand "add<mode>3"
     }
 })
 
-(define_insn "*add<mode>3_internal1"
+(define_insn "*add<mode>3"
   [(set (match_operand:GPR 0 "gpc_reg_operand" "=r,r,r")
 	(plus:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,b,b")
 		  (match_operand:GPR 2 "add_operand" "r,I,L")))]
@@ -1510,70 +1510,99 @@ (define_insn "addsi3_high"
   "addis %0,%1,ha16(%2)"
   [(set_attr "type" "add")])
 
-(define_insn "*add<mode>3_internal2"
-  [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y")
-	(compare:CC (plus:P (match_operand:P 1 "gpc_reg_operand" "%r,r,r,r")
-			    (match_operand:P 2 "reg_or_short_operand" "r,I,r,I"))
+(define_insn_and_split "*add<mode>3_dot"
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
+	(compare:CC (plus:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r")
+			      (match_operand:GPR 2 "gpc_reg_operand" "r,r"))
 		    (const_int 0)))
-   (clobber (match_scratch:P 3 "=r,r,r,r"))]
-  ""
+   (clobber (match_scratch:GPR 0 "=r,r"))]
+  "<MODE>mode == Pmode"
   "@
-   add. %3,%1,%2
-   addic. %3,%1,%2
-   #
+   add. %0,%1,%2
    #"
-  [(set_attr "type" "add,compare,compare,compare")
+  "&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
+  [(set (match_dup 0)
+	(plus:GPR (match_dup 1)
+		 (match_dup 2)))
+   (set (match_dup 3)
+	(compare:CC (match_dup 0)
+		    (const_int 0)))]
+  ""
+  [(set_attr "type" "add")
    (set_attr "dot" "yes")
-   (set_attr "length" "4,4,8,8")])
+   (set_attr "length" "4,8")])
 
-(define_split
-  [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
-	(compare:CC (plus:GPR (match_operand:GPR 1 "gpc_reg_operand" "")
-			      (match_operand:GPR 2 "reg_or_short_operand" ""))
+(define_insn_and_split "*add<mode>3_dot2"
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
+	(compare:CC (plus:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r")
+			      (match_operand:GPR 2 "gpc_reg_operand" "r,r"))
 		    (const_int 0)))
-   (clobber (match_scratch:GPR 3 ""))]
-  "reload_completed"
-  [(set (match_dup 3)
+   (set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
 	(plus:GPR (match_dup 1)
-		 (match_dup 2)))
-   (set (match_dup 0)
-	(compare:CC (match_dup 3)
+		  (match_dup 2)))]
+  "<MODE>mode == Pmode"
+  "@
+   add. %0,%1,%2
+   #"
+  "&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
+  [(set (match_dup 0)
+	(plus:GPR (match_dup 1)
+		  (match_dup 2)))
+   (set (match_dup 3)
+	(compare:CC (match_dup 0)
 		    (const_int 0)))]
-  "")
+  ""
+  [(set_attr "type" "add")
+   (set_attr "dot" "yes")
+   (set_attr "length" "4,8")])
 
-(define_insn "*add<mode>3_internal3"
-  [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,?y,?y")
-	(compare:CC (plus:P (match_operand:P 1 "gpc_reg_operand" "%r,r,r,r")
-			    (match_operand:P 2 "reg_or_short_operand" "r,I,r,I"))
+(define_insn_and_split "*add<mode>3_imm_dot"
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
+	(compare:CC (plus:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,r")
+			      (match_operand:GPR 2 "short_cint_operand" "I,I"))
 		    (const_int 0)))
-   (set (match_operand:P 0 "gpc_reg_operand" "=r,r,r,r")
-	(plus:P (match_dup 1)
-		(match_dup 2)))]
-  ""
+   (clobber (match_scratch:GPR 0 "=r,r"))
+   (clobber (reg:GPR CA_REGNO))]
+  "<MODE>mode == Pmode"
   "@
-   add. %0,%1,%2
    addic. %0,%1,%2
-   #
    #"
-  [(set_attr "type" "add,compare,compare,compare")
+  "&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
+  [(set (match_dup 0)
+	(plus:GPR (match_dup 1)
+		  (match_dup 2)))
+   (set (match_dup 3)
+	(compare:CC (match_dup 0)
+		    (const_int 0)))]
+  ""
+  [(set_attr "type" "add")
    (set_attr "dot" "yes")
-   (set_attr "length" "4,4,8,8")])
+   (set_attr "length" "4,8")])
 
-(define_split
-  [(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "")
-	(compare:CC (plus:P (match_operand:P 1 "gpc_reg_operand" "")
-			    (match_operand:P 2 "reg_or_short_operand" ""))
+(define_insn_and_split "*add<mode>3_imm_dot2"
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
+	(compare:CC (plus:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,r")
+			      (match_operand:GPR 2 "short_cint_operand" "I,I"))
 		    (const_int 0)))
-   (set (match_operand:P 0 "gpc_reg_operand" "")
-	(plus:P (match_dup 1) (match_dup 2)))]
-  "reload_completed"
+   (set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
+	(plus:GPR (match_dup 1)
+		  (match_dup 2)))
+   (clobber (reg:GPR CA_REGNO))]
+  "<MODE>mode == Pmode"
+  "@
+   addic. %0,%1,%2
+   #"
+  "&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
   [(set (match_dup 0)
-	(plus:P (match_dup 1)
-		(match_dup 2)))
+	(plus:GPR (match_dup 1)
+		  (match_dup 2)))
    (set (match_dup 3)
 	(compare:CC (match_dup 0)
 		    (const_int 0)))]
-  "")
+  ""
+  [(set_attr "type" "add")
+   (set_attr "dot" "yes")
+   (set_attr "length" "4,8")])
 
 ;; Split an add that we can't do in one insn into two insns, each of which
 ;; does one 16-bit part.  This is used by combine.  Note that the low-order
-- 
1.8.1.4

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH 09/10] rs6000: Remove the (now unused) insn type "compare"
  2014-12-08 14:18 [PATCH 00/10] rs6000: Carry bit improvements Segher Boessenkool
                   ` (2 preceding siblings ...)
  2014-12-08 14:18 ` [PATCH 03/10] rs6000: Do not use addic in the ctr* splitters Segher Boessenkool
@ 2014-12-08 14:47 ` Segher Boessenkool
  2014-12-09 18:57   ` David Edelsohn
  2014-12-08 14:47 ` [PATCH 08/10] rs6000: compare->two for rld*;rld* Segher Boessenkool
                   ` (5 subsequent siblings)
  9 siblings, 1 reply; 33+ messages in thread
From: Segher Boessenkool @ 2014-12-08 14:47 UTC (permalink / raw)
  To: gcc-patches; +Cc: dje.gcc, Segher Boessenkool


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

gcc/
	* config/rs6000/40x.md (ppc403-compare): Remove "compare".
	config/rs6000/440.md (ppc440-compare): Remove "compare".
	config/rs6000/476.md (ppc476-compare): Remove "compare".
	config/rs6000/601.md (ppc601-compare): Remove "compare".
	config/rs6000/603.md (ppc603-compare): Remove "compare".
	config/rs6000/6xx.md (ppc604-compare): Remove "compare".
	config/rs6000/7450.md (ppc7450-compare): Remove "compare".
	config/rs6000/7xx.md (ppc750-compare): Remove "compare".
	config/rs6000/8540.md (ppc8540_su): Remove "compare".
	config/rs6000/cell.md (cell-fast-cmp, cell-cmp-microcoded): Remove
	"compare".
	config/rs6000/e300c2c3.md (ppce300c3_cmp): Remove "compare".
	config/rs6000/e500mc.md (e500mc_su): Remove "compare".
	config/rs6000/e500mc64.md (e500mc64_su2): Remove "compare".
	config/rs6000/e5500.md (e5500_sfx2): Remove "compare".
	config/rs6000/e6500.md (e6500_sfx2): Remove "compare".
	config/rs6000/mpc.md (mpccore-compare): Remove "compare".
	config/rs6000/power4.md (power4-compare): Remove "compare".
	config/rs6000/power5.md (power5-compare): Remove "compare".
	config/rs6000/power6.md (power6-compare): Remove "compare".
	config/rs6000/power7.md (power7-compare): Remove "compare".
	config/rs6000/power8.md (power8-compare): Remove "compare".  Update
	comment.
	config/rs6000/rs6000.c (rs6000_adjust_cost) <TYPE_COMPARE>: Remove
	(three times).
	(is_cracked_insn): Remove TYPE_COMPARE case.
	(insn_must_be_first_in_group) <TYPE_COMPARE>: Remove (twice).
	config/rs6000/rs6000.md (type): Remove "compare".
	(cell_micro): Remove "compare".
	config/rs6000/rs64.md (rs64a-compare): Remove "compare".

---
 gcc/config/rs6000/40x.md      |  2 +-
 gcc/config/rs6000/440.md      |  2 +-
 gcc/config/rs6000/476.md      |  2 +-
 gcc/config/rs6000/601.md      |  2 +-
 gcc/config/rs6000/603.md      |  2 +-
 gcc/config/rs6000/6xx.md      |  2 +-
 gcc/config/rs6000/7450.md     |  2 +-
 gcc/config/rs6000/7xx.md      |  2 +-
 gcc/config/rs6000/8540.md     |  2 +-
 gcc/config/rs6000/cell.md     | 10 ++++------
 gcc/config/rs6000/e300c2c3.md |  2 +-
 gcc/config/rs6000/e500mc.md   |  2 +-
 gcc/config/rs6000/e500mc64.md |  2 +-
 gcc/config/rs6000/e5500.md    |  2 +-
 gcc/config/rs6000/e6500.md    |  2 +-
 gcc/config/rs6000/mpc.md      |  2 +-
 gcc/config/rs6000/power4.md   |  5 ++---
 gcc/config/rs6000/power5.md   |  5 ++---
 gcc/config/rs6000/power6.md   |  5 ++---
 gcc/config/rs6000/power7.md   |  5 ++---
 gcc/config/rs6000/power8.md   |  8 +++-----
 gcc/config/rs6000/rs6000.c    |  6 ------
 gcc/config/rs6000/rs6000.md   |  4 +---
 gcc/config/rs6000/rs64.md     |  2 +-
 24 files changed, 32 insertions(+), 48 deletions(-)

diff --git a/gcc/config/rs6000/40x.md b/gcc/config/rs6000/40x.md
index 0903536..650fe52 100644
--- a/gcc/config/rs6000/40x.md
+++ b/gcc/config/rs6000/40x.md
@@ -53,7 +53,7 @@ (define_insn_reservation "ppc403-three" 1
   "iu_40x,iu_40x,iu_40x")
 
 (define_insn_reservation "ppc403-compare" 3
-  (and (ior (eq_attr "type" "cmp,compare")
+  (and (ior (eq_attr "type" "cmp")
 	    (and (eq_attr "type" "add,logical,shift,exts")
 		 (eq_attr "dot" "yes")))
        (eq_attr "cpu" "ppc403,ppc405"))
diff --git a/gcc/config/rs6000/440.md b/gcc/config/rs6000/440.md
index ff91fdb..b8a1d33 100644
--- a/gcc/config/rs6000/440.md
+++ b/gcc/config/rs6000/440.md
@@ -95,7 +95,7 @@ (define_insn_reservation "ppc440-branch" 1
   "ppc440_issue,ppc440_i_pipe")
 
 (define_insn_reservation "ppc440-compare" 2
-  (and (ior (eq_attr "type" "cmp,compare,cr_logical,delayed_cr,mfcr")
+  (and (ior (eq_attr "type" "cmp,cr_logical,delayed_cr,mfcr")
 	    (and (eq_attr "type" "add,logical,shift,exts")
 		 (eq_attr "dot" "yes")))
        (eq_attr "cpu" "ppc440"))
diff --git a/gcc/config/rs6000/476.md b/gcc/config/rs6000/476.md
index 9bfd6b6..cf47754 100644
--- a/gcc/config/rs6000/476.md
+++ b/gcc/config/rs6000/476.md
@@ -77,7 +77,7 @@ (define_insn_reservation "ppc476-complex-integer" 1
    ppc476_i_pipe")
 
 (define_insn_reservation "ppc476-compare" 4
-  (and (ior (eq_attr "type" "compare,mfcr,mfcrf,mtcr,mfjmpr,mtjmpr")
+  (and (ior (eq_attr "type" "mfcr,mfcrf,mtcr,mfjmpr,mtjmpr")
 	    (and (eq_attr "type" "add,logical,shift,exts")
 		 (eq_attr "dot" "yes")))
        (eq_attr "cpu" "ppc476"))
diff --git a/gcc/config/rs6000/601.md b/gcc/config/rs6000/601.md
index de51cbf..af14274 100644
--- a/gcc/config/rs6000/601.md
+++ b/gcc/config/rs6000/601.md
@@ -74,7 +74,7 @@ (define_insn_reservation "ppc601-idiv" 36
 ; compare executes on integer unit, but feeds insns which
 ; execute on the branch unit.
 (define_insn_reservation "ppc601-compare" 3
-  (and (ior (eq_attr "type" "cmp,compare")
+  (and (ior (eq_attr "type" "cmp")
 	    (and (eq_attr "type" "shift,exts")
 		 (eq_attr "dot" "yes")))
        (eq_attr "cpu" "ppc601"))
diff --git a/gcc/config/rs6000/603.md b/gcc/config/rs6000/603.md
index dc03018..a145776 100644
--- a/gcc/config/rs6000/603.md
+++ b/gcc/config/rs6000/603.md
@@ -93,7 +93,7 @@ (define_insn_reservation "ppc603-idiv" 37
   "iu_603*37")
 
 (define_insn_reservation "ppc603-compare" 3
-  (and (ior (eq_attr "type" "cmp,compare")
+  (and (ior (eq_attr "type" "cmp")
 	    (and (eq_attr "type" "add,logical,shift,exts")
 		 (eq_attr "dot" "yes")))
        (eq_attr "cpu" "ppc603"))
diff --git a/gcc/config/rs6000/6xx.md b/gcc/config/rs6000/6xx.md
index db83469..8395dbc 100644
--- a/gcc/config/rs6000/6xx.md
+++ b/gcc/config/rs6000/6xx.md
@@ -147,7 +147,7 @@ (define_insn_reservation "ppc620-ldiv" 37
   "mciu_6xx*36")
 
 (define_insn_reservation "ppc604-compare" 3
-  (and (ior (eq_attr "type" "cmp,compare")
+  (and (ior (eq_attr "type" "cmp")
 	    (and (eq_attr "type" "add,logical,shift,exts")
 		 (eq_attr "dot" "yes")))
        (eq_attr "cpu" "ppc604,ppc604e,ppc620,ppc630"))
diff --git a/gcc/config/rs6000/7450.md b/gcc/config/rs6000/7450.md
index 3679c79..f790332 100644
--- a/gcc/config/rs6000/7450.md
+++ b/gcc/config/rs6000/7450.md
@@ -108,7 +108,7 @@ (define_insn_reservation "ppc7450-idiv" 23
   "ppc7450_du,mciu_7450*23")
 
 (define_insn_reservation "ppc7450-compare" 2
-  (and (ior (eq_attr "type" "cmp,compare")
+  (and (ior (eq_attr "type" "cmp")
 	    (and (eq_attr "type" "add,logical,shift,exts")
 		 (eq_attr "dot" "yes")))
        (eq_attr "cpu" "ppc7450"))
diff --git a/gcc/config/rs6000/7xx.md b/gcc/config/rs6000/7xx.md
index b27fe35..21461f0 100644
--- a/gcc/config/rs6000/7xx.md
+++ b/gcc/config/rs6000/7xx.md
@@ -101,7 +101,7 @@ (define_insn_reservation "ppc750-idiv" 19
   "ppc750_du,iu1_7xx*19")
 
 (define_insn_reservation "ppc750-compare" 2
-  (and (ior (eq_attr "type" "cmp,compare")
+  (and (ior (eq_attr "type" "cmp")
 	    (and (eq_attr "type" "add,logical,shift,exts")
 		 (eq_attr "dot" "yes")))
        (eq_attr "cpu" "ppc750,ppc7400"))
diff --git a/gcc/config/rs6000/8540.md b/gcc/config/rs6000/8540.md
index 90a3d27..1487a41 100644
--- a/gcc/config/rs6000/8540.md
+++ b/gcc/config/rs6000/8540.md
@@ -84,7 +84,7 @@ (define_reservation "ppc8540_su_stage0"
 
 ;; Simple SU insns
 (define_insn_reservation "ppc8540_su" 1
-  (and (eq_attr "type" "integer,add,logical,insert,cmp,compare,\
+  (and (eq_attr "type" "integer,add,logical,insert,cmp,\
                         shift,trap,cntlz,exts,isel")
        (eq_attr "cpu" "ppc8540,ppc8548"))
   "ppc8540_decode,ppc8540_issue+ppc8540_su_stage0+ppc8540_retire")
diff --git a/gcc/config/rs6000/cell.md b/gcc/config/rs6000/cell.md
index f1ce352..8479bb7 100644
--- a/gcc/config/rs6000/cell.md
+++ b/gcc/config/rs6000/cell.md
@@ -201,17 +201,15 @@ (define_insn_reservation "cell-cmp" 1
 
 ;; add, addo, sub, subo, alter cr0, rldcli, rlwinm 
 (define_insn_reservation "cell-fast-cmp" 2
-  (and (ior (eq_attr "type" "compare")
-	    (and (eq_attr "type" "add,logical,shift,exts")
-		 (eq_attr "dot" "yes")))
+  (and (eq_attr "type" "add,logical,shift,exts")
+       (eq_attr "dot" "yes")
        (eq_attr "cpu" "cell")
        (eq_attr "cell_micro" "not"))
   "slot01,fxu_cell")
 
 (define_insn_reservation "cell-cmp-microcoded" 9
-  (and (ior (eq_attr "type" "compare")
-	    (and (eq_attr "type" "add,logical,shift,exts")
-		 (eq_attr "dot" "yes")))
+  (and (eq_attr "type" "add,logical,shift,exts")
+       (eq_attr "dot" "yes")
        (eq_attr "cpu" "cell")
        (eq_attr "cell_micro" "always"))
   "slot0+slot1,fxu_cell,fxu_cell*7")
diff --git a/gcc/config/rs6000/e300c2c3.md b/gcc/config/rs6000/e300c2c3.md
index 276b9e9..5f73323 100644
--- a/gcc/config/rs6000/e300c2c3.md
+++ b/gcc/config/rs6000/e300c2c3.md
@@ -83,7 +83,7 @@ (define_reservation "ppce300c3_iu_stage0"
 
 ;; Compares can be executed either one of the IU or SRU
 (define_insn_reservation "ppce300c3_cmp" 1
-  (and (ior (eq_attr "type" "cmp,compare")
+  (and (ior (eq_attr "type" "cmp")
 	    (and (eq_attr "type" "add,logical,shift,exts")
 		 (eq_attr "dot" "yes")))
        (ior (eq_attr "cpu" "ppce300c2") (eq_attr "cpu" "ppce300c3")))
diff --git a/gcc/config/rs6000/e500mc.md b/gcc/config/rs6000/e500mc.md
index 2af7eb4..85bc7cd 100644
--- a/gcc/config/rs6000/e500mc.md
+++ b/gcc/config/rs6000/e500mc.md
@@ -70,7 +70,7 @@ (define_reservation "e500mc_su_stage0"
 
 ;; Simple SU insns.
 (define_insn_reservation "e500mc_su" 1
-  (and (eq_attr "type" "integer,add,logical,insert,cmp,compare,\
+  (and (eq_attr "type" "integer,add,logical,insert,cmp,\
                         shift,trap,cntlz,exts,isel")
        (eq_attr "cpu" "ppce500mc"))
   "e500mc_decode,e500mc_issue+e500mc_su_stage0+e500mc_retire")
diff --git a/gcc/config/rs6000/e500mc64.md b/gcc/config/rs6000/e500mc64.md
index dc3eb6a..059992f 100644
--- a/gcc/config/rs6000/e500mc64.md
+++ b/gcc/config/rs6000/e500mc64.md
@@ -79,7 +79,7 @@ (define_insn_reservation "e500mc64_su" 1
   "e500mc64_decode,e500mc64_issue+e500mc64_su_stage0+e500mc64_retire")
 
 (define_insn_reservation "e500mc64_su2" 2
-  (and (ior (eq_attr "type" "cmp,compare,trap")
+  (and (ior (eq_attr "type" "cmp,trap")
 	    (and (eq_attr "type" "add,logical,exts")
 		 (eq_attr "dot" "yes"))
 	    (and (eq_attr "type" "shift")
diff --git a/gcc/config/rs6000/e5500.md b/gcc/config/rs6000/e5500.md
index 3cad8bd..b0596b6 100644
--- a/gcc/config/rs6000/e5500.md
+++ b/gcc/config/rs6000/e5500.md
@@ -65,7 +65,7 @@ (define_insn_reservation "e5500_sfx" 1
   "e5500_decode,e5500_sfx")
 
 (define_insn_reservation "e5500_sfx2" 2
-  (and (ior (eq_attr "type" "cmp,compare,trap")
+  (and (ior (eq_attr "type" "cmp,trap")
 	    (and (eq_attr "type" "add,logical,exts")
 		 (eq_attr "dot"  "yes"))
 	    (and (eq_attr "type" "shift")
diff --git a/gcc/config/rs6000/e6500.md b/gcc/config/rs6000/e6500.md
index 9d4b483..6fe062a 100644
--- a/gcc/config/rs6000/e6500.md
+++ b/gcc/config/rs6000/e6500.md
@@ -69,7 +69,7 @@ (define_insn_reservation "e6500_sfx" 1
   "e6500_decode,e6500_sfx")
 
 (define_insn_reservation "e6500_sfx2" 2
-  (and (ior (eq_attr "type" "cmp,compare,trap")
+  (and (ior (eq_attr "type" "cmp,trap")
 	    (and (eq_attr "type" "add,logical,exts")
 		 (eq_attr "dot"  "yes"))
 	    (and (eq_attr "type" "shift")
diff --git a/gcc/config/rs6000/mpc.md b/gcc/config/rs6000/mpc.md
index 9ac611a..b1d4cf76 100644
--- a/gcc/config/rs6000/mpc.md
+++ b/gcc/config/rs6000/mpc.md
@@ -69,7 +69,7 @@ (define_insn_reservation "mpccore-idiv" 6
   "mciu_mpc*6")
 
 (define_insn_reservation "mpccore-compare" 3
-  (and (ior (eq_attr "type" "cmp,compare")
+  (and (ior (eq_attr "type" "cmp")
 	    (and (eq_attr "type" "add,logical,shift,exts")
 		 (eq_attr "dot" "yes")))
        (eq_attr "cpu" "mpccore"))
diff --git a/gcc/config/rs6000/power4.md b/gcc/config/rs6000/power4.md
index a436ec7..0c838bb 100644
--- a/gcc/config/rs6000/power4.md
+++ b/gcc/config/rs6000/power4.md
@@ -257,9 +257,8 @@ (define_insn_reservation "power4-cmp" 3
   "iq_power4")
 
 (define_insn_reservation "power4-compare" 2
-  (and (ior (eq_attr "type" "compare")
-	    (and (eq_attr "type" "shift,exts")
-		 (eq_attr "dot" "yes")))
+  (and (eq_attr "type" "shift,exts")
+       (eq_attr "dot" "yes")
        (eq_attr "cpu" "power4"))
   "(du1_power4+du2_power4|du2_power4+du3_power4|du3_power4+du4_power4),\
    ((iu1_power4,iu2_power4)\
diff --git a/gcc/config/rs6000/power5.md b/gcc/config/rs6000/power5.md
index 530c255..24fde7d 100644
--- a/gcc/config/rs6000/power5.md
+++ b/gcc/config/rs6000/power5.md
@@ -210,9 +210,8 @@ (define_insn_reservation "power5-cmp" 3
   "iq_power5")
 
 (define_insn_reservation "power5-compare" 2
-  (and (ior (eq_attr "type" "compare")
-	    (and (eq_attr "type" "shift,exts")
-		 (eq_attr "dot" "yes")))
+  (and (eq_attr "type" "shift,exts")
+       (eq_attr "dot" "yes")
        (eq_attr "cpu" "power5"))
   "du1_power5+du2_power5,iu1_power5,iu2_power5")
 
diff --git a/gcc/config/rs6000/power6.md b/gcc/config/rs6000/power6.md
index 695f642..60dd1de 100644
--- a/gcc/config/rs6000/power6.md
+++ b/gcc/config/rs6000/power6.md
@@ -334,9 +334,8 @@ (define_insn_reservation "power6-cmp" 1
   "FXU_power6")
 
 (define_insn_reservation "power6-compare" 1
-  (and (ior (eq_attr "type" "compare")
-            (and (eq_attr "type" "exts")
-                 (eq_attr "dot" "yes")))
+  (and (eq_attr "type" "exts")
+       (eq_attr "dot" "yes")
        (eq_attr "cpu" "power6"))
   "FXU_power6")
 
diff --git a/gcc/config/rs6000/power7.md b/gcc/config/rs6000/power7.md
index 8be2879..fa1e80f 100644
--- a/gcc/config/rs6000/power7.md
+++ b/gcc/config/rs6000/power7.md
@@ -203,9 +203,8 @@ (define_insn_reservation "power7-cmp" 1
   "DU_power7,FXU_power7")
 
 (define_insn_reservation "power7-compare" 2
-  (and (ior (eq_attr "type" "compare")
-	    (and (eq_attr "type" "shift,exts")
-		 (eq_attr "dot" "yes")))
+  (and (eq_attr "type" "shift,exts")
+       (eq_attr "dot" "yes")
        (eq_attr "cpu" "power7"))
   "DU2F_power7,FXU_power7,FXU_power7")
 
diff --git a/gcc/config/rs6000/power8.md b/gcc/config/rs6000/power8.md
index 4b03ac2..a9b523d 100644
--- a/gcc/config/rs6000/power8.md
+++ b/gcc/config/rs6000/power8.md
@@ -212,12 +212,10 @@ (define_insn_reservation "power8-fast-compare" 2
        (eq_attr "cpu" "power8"))
   "DU_any_power8,FXU_power8")
 
-; compare : rldicl./exts./etc
-; shift with dot : rlwinm./slwi./rlwnm./slw./etc
+; exts/shift with dot : rldicl./exts./rlwinm./slwi./rlwnm./slw./etc
 (define_insn_reservation "power8-compare" 2
-  (and (ior (eq_attr "type" "compare")
-	    (and (eq_attr "type" "shift,exts")
-		 (eq_attr "dot" "yes")))
+  (and (eq_attr "type" "shift,exts")
+       (eq_attr "dot" "yes")
        (eq_attr "cpu" "power8"))
   "DU_cracked_power8,FXU_power8,FXU_power8")
 
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index f60f4d7..1738f46 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -26696,7 +26696,6 @@ rs6000_adjust_cost (rtx_insn *insn, rtx link, rtx_insn *dep_insn, int cost)
               switch (get_attr_type (dep_insn))
                 {
                 case TYPE_CMP:
-                case TYPE_COMPARE:
                 case TYPE_FPCOMPARE:
                 case TYPE_CR_LOGICAL:
                 case TYPE_DELAYED_CR:
@@ -26753,7 +26752,6 @@ rs6000_adjust_cost (rtx_insn *insn, rtx link, rtx_insn *dep_insn, int cost)
                   case TYPE_INTEGER:
                   case TYPE_ADD:
                   case TYPE_LOGICAL:
-                  case TYPE_COMPARE:
                   case TYPE_EXTS:
                   case TYPE_INSERT:
                     {
@@ -26817,7 +26815,6 @@ rs6000_adjust_cost (rtx_insn *insn, rtx link, rtx_insn *dep_insn, int cost)
                   case TYPE_INTEGER:
                   case TYPE_ADD:
                   case TYPE_LOGICAL:
-                  case TYPE_COMPARE:
                   case TYPE_EXTS:
                   case TYPE_INSERT:
                     {
@@ -26993,7 +26990,6 @@ is_cracked_insn (rtx_insn *insn)
 	  || ((type == TYPE_FPLOAD || type == TYPE_FPSTORE)
 	      && get_attr_update (insn) == UPDATE_YES)
 	  || type == TYPE_DELAYED_CR
-	  || type == TYPE_COMPARE
 	  || (type == TYPE_EXTS
 	      && get_attr_dot (insn) == DOT_YES)
 	  || (type == TYPE_SHIFT
@@ -27875,7 +27871,6 @@ insn_must_be_first_in_group (rtx_insn *insn)
         case TYPE_MFCRF:
         case TYPE_MTCR:
         case TYPE_DIV:
-        case TYPE_COMPARE:
         case TYPE_ISYNC:
         case TYPE_LOAD_L:
         case TYPE_STORE_C:
@@ -27916,7 +27911,6 @@ insn_must_be_first_in_group (rtx_insn *insn)
         case TYPE_MFCR:
         case TYPE_MFCRF:
         case TYPE_MTCR:
-        case TYPE_COMPARE:
         case TYPE_SYNC:
         case TYPE_ISYNC:
         case TYPE_LOAD_L:
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index d0b8bc8..a544e57 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -168,7 +168,6 @@ (define_attr "type"
    load,store,fpload,fpstore,vecload,vecstore,
    cmp,
    branch,jmpreg,mfjmpr,mtjmpr,trap,isync,sync,load_l,store_c,
-   compare,
    cr_logical,delayed_cr,mfcr,mfcrf,mtcr,
    fpcompare,fp,fpsimple,dmul,sdiv,ddiv,ssqrt,dsqrt,
    brinc,
@@ -254,8 +253,7 @@ (define_attr "cpu"
 ;; If this instruction is microcoded on the CELL processor
 ; The default for load extended, the recorded instructions and rotate/shifts by a variable is always microcoded
 (define_attr "cell_micro" "not,conditional,always"
-  (if_then_else (ior (eq_attr "type" "compare")
-		     (and (eq_attr "type" "shift,exts,mul")
+  (if_then_else (ior (and (eq_attr "type" "shift,exts,mul")
 			  (eq_attr "dot" "yes"))
 		     (and (eq_attr "type" "load")
 			  (eq_attr "sign_extend" "yes"))
diff --git a/gcc/config/rs6000/rs64.md b/gcc/config/rs6000/rs64.md
index 8925f38..3023890 100644
--- a/gcc/config/rs6000/rs64.md
+++ b/gcc/config/rs6000/rs64.md
@@ -99,7 +99,7 @@ (define_insn_reservation "rs64a-ldiv" 66
   "mciu_rs64*66")
 
 (define_insn_reservation "rs64a-compare" 3
-  (and (ior (eq_attr "type" "cmp,compare")
+  (and (ior (eq_attr "type" "cmp")
 	    (and (eq_attr "type" "add,logical,shift,exts")
 		 (eq_attr "dot" "yes")))
        (eq_attr "cpu" "rs64a"))
-- 
1.8.1.4

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH 07/10] rs6000: The big carry insns addition
  2014-12-08 14:18 [PATCH 00/10] rs6000: Carry bit improvements Segher Boessenkool
                   ` (7 preceding siblings ...)
  2014-12-08 14:47 ` [PATCH 04/10] rs6000: Remove addic from the normal add pattern Segher Boessenkool
@ 2014-12-08 14:47 ` Segher Boessenkool
  2014-12-09 18:56   ` David Edelsohn
  2014-12-08 14:47 ` [PATCH 10/10] rs6000: Get rid of the weird decimal thing in add Segher Boessenkool
  9 siblings, 1 reply; 33+ messages in thread
From: Segher Boessenkool @ 2014-12-08 14:47 UTC (permalink / raw)
  To: gcc-patches; +Cc: dje.gcc, Segher Boessenkool

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")))])
 \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
-- 
1.8.1.4

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH 04/10] rs6000: Remove addic from the normal add pattern
  2014-12-08 14:44   ` David Edelsohn
@ 2014-12-08 15:01     ` Segher Boessenkool
  2014-12-08 15:10       ` David Edelsohn
  2014-12-09 17:12       ` Segher Boessenkool
  0 siblings, 2 replies; 33+ messages in thread
From: Segher Boessenkool @ 2014-12-08 15:01 UTC (permalink / raw)
  To: David Edelsohn; +Cc: GCC Patches

On Mon, Dec 08, 2014 at 09:44:44AM -0500, David Edelsohn wrote:
> > -;; Discourage ai/addic because of carry but provide it in an alternative
> > -;; allowing register zero as source.
> >  (define_insn "*add<mode>3_internal1"
> > -  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r,r,?r,r")
> > -       (plus:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,b,r,b")
> > -                 (match_operand:GPR 2 "add_operand" "r,I,I,L")))]
> > +  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r,r,r")
> > +       (plus:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,b,b")
> > +                 (match_operand:GPR 2 "add_operand" "r,I,L")))]
> >    "!DECIMAL_FLOAT_MODE_P (GET_MODE (operands[0])) && !DECIMAL_FLOAT_MODE_P (GET_MODE (operands[1]))"
> >    "@
> >     add %0,%1,%2
> >     addi %0,%1,%2
> > -   addic %0,%1,%2
> >     addis %0,%1,%v2"
> >    [(set_attr "type" "add")])
> 
> Why are you removing the alternative instead of clobbering XER[CA]?

I should have mentioned, sorry.

We don't want to clobber CA on *every* add, and reload can generate more
adds out of thin air.  And CA is a fixed register.

There may be a better way to do this, but I don't know it.


Segher

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH 04/10] rs6000: Remove addic from the normal add pattern
  2014-12-08 15:01     ` Segher Boessenkool
@ 2014-12-08 15:10       ` David Edelsohn
  2014-12-09 16:25         ` Eric Botcazou
  2014-12-09 17:12       ` Segher Boessenkool
  1 sibling, 1 reply; 33+ messages in thread
From: David Edelsohn @ 2014-12-08 15:10 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: GCC Patches

On Mon, Dec 8, 2014 at 10:01 AM, Segher Boessenkool
<segher@kernel.crashing.org> wrote:
> On Mon, Dec 08, 2014 at 09:44:44AM -0500, David Edelsohn wrote:
>> > -;; Discourage ai/addic because of carry but provide it in an alternative
>> > -;; allowing register zero as source.
>> >  (define_insn "*add<mode>3_internal1"
>> > -  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r,r,?r,r")
>> > -       (plus:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,b,r,b")
>> > -                 (match_operand:GPR 2 "add_operand" "r,I,I,L")))]
>> > +  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r,r,r")
>> > +       (plus:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,b,b")
>> > +                 (match_operand:GPR 2 "add_operand" "r,I,L")))]
>> >    "!DECIMAL_FLOAT_MODE_P (GET_MODE (operands[0])) && !DECIMAL_FLOAT_MODE_P (GET_MODE (operands[1]))"
>> >    "@
>> >     add %0,%1,%2
>> >     addi %0,%1,%2
>> > -   addic %0,%1,%2
>> >     addis %0,%1,%v2"
>> >    [(set_attr "type" "add")])
>>
>> Why are you removing the alternative instead of clobbering XER[CA]?
>
> I should have mentioned, sorry.
>
> We don't want to clobber CA on *every* add, and reload can generate more
> adds out of thin air.  And CA is a fixed register.
>
> There may be a better way to do this, but I don't know it.

Okay.

It's unfortunate that GCC does not have separate patterns for a safe
ADD used by reload.

Thanks, David

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH 05/10] rs6000: Merge and split add and addic
  2014-12-08 14:47 ` [PATCH 05/10] rs6000: Merge and split add and addic Segher Boessenkool
@ 2014-12-08 15:31   ` David Edelsohn
  0 siblings, 0 replies; 33+ messages in thread
From: David Edelsohn @ 2014-12-08 15:31 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: GCC Patches

On Mon, Dec 8, 2014 at 9:18 AM, Segher Boessenkool
<segher@kernel.crashing.org> wrote:
> This splits the addic patterns from the add/addi patterns, and merges the
> insns and splitters.
> Also change type "compare" to "add" for "addic." (the dot form).
>
>
> 2014-12-08  Segher Boessenkool  <segher@kernel.crashing.org>
>
> gcc/
>         PR target/64180
>         * config/rs6000/rs6000.md (*add<mode>3_internal1): Rename to
>         "*add<mode>3".
>         (*add<mode>3_internal2, *add<mode>3_internal3, and (their splitters):
>         Delete.
>         (*add<mode>3_dot, *add<mode>3_dot2): New.
>         (*add<mode>3_imm_dot, *add<mode>3_imm_dot2): New.

Okay.

Thanks, David

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH 06/10] rs6000: New add/subf carry insns
  2014-12-08 14:47 ` [PATCH 06/10] rs6000: New add/subf carry insns Segher Boessenkool
@ 2014-12-08 15:41   ` David Edelsohn
  2014-12-08 15:53     ` David Edelsohn
  0 siblings, 1 reply; 33+ messages in thread
From: David Edelsohn @ 2014-12-08 15:41 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: GCC Patches

On Mon, Dec 8, 2014 at 9:18 AM, Segher Boessenkool
<segher@kernel.crashing.org> wrote:
> This implements addc, addic, adde, addze, addme, subfc, subfic, subfe,
> subfze, subfme.  Some of those in multiple forms: canonical RTL for the
> "immediate" insns has four forms; subfX has a special form for subtracting
> a register from itself.
>
> All these new insns get type "add" for now.
>
>
> 2014-12-08  Segher Boessenkool  <segher@kernel.crashing.org>
>
> gcc/
>         PR target/64180
>         * config/rs6000/predicates.md (adde_operand): New.
>         * config/rs6000/rs6000.md (add<mode>3_carry): New.
>         (add<mode>3_imm_carry_pos): New.
>         (add<mode>3_imm_carry_0): New.
>         (add<mode>3_imm_carry_m1): New.
>         (add<mode>3_imm_carry_neg): New.
>         (add<mode>3_carry_in): New.
>         (add<mode>3_carry_in_0): New.
>         (add<mode>3_carry_in_m1): New.
>         (subf<mode>3_carry): New.
>         (subf<mode>3_imm_carry_0): New.
>         (subf<mode>3_imm_carry_m1): New.
>         (subf<mode>3_carry_in): New.
>         (subf<mode>3_carry_in_0): New.
>         (subf<mode>3_carry_in_m1): New.
>         (subf<mode>3_carry_in_xx): New.

Okay.

Thanks, David

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH 06/10] rs6000: New add/subf carry insns
  2014-12-08 15:41   ` David Edelsohn
@ 2014-12-08 15:53     ` David Edelsohn
  2014-12-10 14:00       ` Segher Boessenkool
  0 siblings, 1 reply; 33+ messages in thread
From: David Edelsohn @ 2014-12-08 15:53 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: GCC Patches

On Mon, Dec 8, 2014 at 10:41 AM, David Edelsohn <dje.gcc@gmail.com> wrote:
> On Mon, Dec 8, 2014 at 9:18 AM, Segher Boessenkool
> <segher@kernel.crashing.org> wrote:
>> This implements addc, addic, adde, addze, addme, subfc, subfic, subfe,
>> subfze, subfme.  Some of those in multiple forms: canonical RTL for the
>> "immediate" insns has four forms; subfX has a special form for subtracting
>> a register from itself.
>>
>> All these new insns get type "add" for now.
>>
>>
>> 2014-12-08  Segher Boessenkool  <segher@kernel.crashing.org>
>>
>> gcc/
>>         PR target/64180
>>         * config/rs6000/predicates.md (adde_operand): New.
>>         * config/rs6000/rs6000.md (add<mode>3_carry): New.
>>         (add<mode>3_imm_carry_pos): New.
>>         (add<mode>3_imm_carry_0): New.
>>         (add<mode>3_imm_carry_m1): New.
>>         (add<mode>3_imm_carry_neg): New.
>>         (add<mode>3_carry_in): New.
>>         (add<mode>3_carry_in_0): New.
>>         (add<mode>3_carry_in_m1): New.
>>         (subf<mode>3_carry): New.
>>         (subf<mode>3_imm_carry_0): New.
>>         (subf<mode>3_imm_carry_m1): New.
>>         (subf<mode>3_carry_in): New.
>>         (subf<mode>3_carry_in_0): New.
>>         (subf<mode>3_carry_in_m1): New.
>>         (subf<mode>3_carry_in_xx): New.
>
> Okay.
>
> Thanks, David

As we both noticed, there are a few problems with this patch, so I'll
wait for a revised version.

Thanks, David

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH 04/10] rs6000: Remove addic from the normal add pattern
  2014-12-08 15:10       ` David Edelsohn
@ 2014-12-09 16:25         ` Eric Botcazou
  2014-12-09 16:48           ` David Edelsohn
  0 siblings, 1 reply; 33+ messages in thread
From: Eric Botcazou @ 2014-12-09 16:25 UTC (permalink / raw)
  To: David Edelsohn; +Cc: gcc-patches, Segher Boessenkool

> It's unfortunate that GCC does not have separate patterns for a safe
> ADD used by reload.

It does, the addptrM3 pattern, but it works only with LRA at the moment.

-- 
Eric Botcazou

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH 04/10] rs6000: Remove addic from the normal add pattern
  2014-12-09 16:25         ` Eric Botcazou
@ 2014-12-09 16:48           ` David Edelsohn
  2014-12-09 17:01             ` Segher Boessenkool
  0 siblings, 1 reply; 33+ messages in thread
From: David Edelsohn @ 2014-12-09 16:48 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: GCC Patches, Segher Boessenkool

On Tue, Dec 9, 2014 at 11:24 AM, Eric Botcazou <ebotcazou@adacore.com> wrote:
>> It's unfortunate that GCC does not have separate patterns for a safe
>> ADD used by reload.
>
> It does, the addptrM3 pattern, but it works only with LRA at the moment.

Hi, Eric

Segher and I previously discussed addptrM3, but I thought that it was
restricted in a different way.

We definitely will have to define addptrM3 and restore addM3 when
rs6000 switches to LRA.

Thanks, David

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH 04/10] rs6000: Remove addic from the normal add pattern
  2014-12-09 16:48           ` David Edelsohn
@ 2014-12-09 17:01             ` Segher Boessenkool
  0 siblings, 0 replies; 33+ messages in thread
From: Segher Boessenkool @ 2014-12-09 17:01 UTC (permalink / raw)
  To: David Edelsohn; +Cc: Eric Botcazou, GCC Patches

On Tue, Dec 09, 2014 at 11:48:44AM -0500, David Edelsohn wrote:
> We definitely will have to define addptrM3 and restore addM3 when
> rs6000 switches to LRA.

Can LRA deal with adding a clobber of a hard register?  How would
you express that in the patterns, anyway?


Segher

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH 04/10] rs6000: Remove addic from the normal add pattern
  2014-12-08 15:01     ` Segher Boessenkool
  2014-12-08 15:10       ` David Edelsohn
@ 2014-12-09 17:12       ` Segher Boessenkool
  1 sibling, 0 replies; 33+ messages in thread
From: Segher Boessenkool @ 2014-12-09 17:12 UTC (permalink / raw)
  To: David Edelsohn; +Cc: GCC Patches

On Mon, Dec 08, 2014 at 09:01:39AM -0600, Segher Boessenkool wrote:
> > Why are you removing the alternative instead of clobbering XER[CA]?
> 
> I should have mentioned, sorry.
> 
> We don't want to clobber CA on *every* add, and reload can generate more
> adds out of thin air.  And CA is a fixed register.
> 
> There may be a better way to do this, but I don't know it.

Some numbers...

I checked how often the compiler used to allocate GPR0 here.  I looked
at cc1 of 4.7.2, 12MB text size.  It happened zero times (it already was
"?r" to discourage the RA / reload from using that alternative).

There are 143962 addi insns in there.


Segher

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH 08/10] rs6000: compare->two for rld*;rld*.
  2014-12-08 14:47 ` [PATCH 08/10] rs6000: compare->two for rld*;rld* Segher Boessenkool
@ 2014-12-09 18:56   ` David Edelsohn
  0 siblings, 0 replies; 33+ messages in thread
From: David Edelsohn @ 2014-12-09 18:56 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: GCC Patches

On Mon, Dec 8, 2014 at 9:18 AM, Segher Boessenkool
<segher@kernel.crashing.org> wrote:
> These now are the only remaining patterns that have type "compare".
> And they shouldn't: "two" is a better type for them.
>
>
> 2014-12-08  Segher Boessenkool  <segher@kernel.crashing.org>
>
> gcc/
>         * config/rs6000/rs6000.md (*anddi3_2rld_dot, *anddi3_rld_dot2):
>         Change type from "compare" to "two".

Okay.

Thanks, David

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH 07/10] rs6000: The big carry insns addition
  2014-12-08 14:47 ` [PATCH 07/10] rs6000: The big carry insns addition Segher Boessenkool
@ 2014-12-09 18:56   ` David Edelsohn
  0 siblings, 0 replies; 33+ messages in thread
From: David Edelsohn @ 2014-12-09 18:56 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: GCC Patches

On Mon, Dec 8, 2014 at 9:18 AM, Segher Boessenkool
<segher@kernel.crashing.org> wrote:
> 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.

Okay.

Thanks, David

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH 10/10] rs6000: Get rid of the weird decimal thing in add
  2014-12-08 14:47 ` [PATCH 10/10] rs6000: Get rid of the weird decimal thing in add Segher Boessenkool
@ 2014-12-09 18:57   ` David Edelsohn
  0 siblings, 0 replies; 33+ messages in thread
From: David Edelsohn @ 2014-12-09 18:57 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: GCC Patches

On Mon, Dec 8, 2014 at 9:18 AM, Segher Boessenkool
<segher@kernel.crashing.org> wrote:
> Peter tells me it was an artifact of old versions of the DFP code.  The
> condition can never be false; delete it.
>
>
> 2014-12-08  Segher Boessenkool  <segher@kernel.crashing.org>
>
> gcc/
>         * config/rs6000/rs6000.md (*add<mode>3): Remove condition.

Okay.

Thanks, David

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH 09/10] rs6000: Remove the (now unused) insn type "compare"
  2014-12-08 14:47 ` [PATCH 09/10] rs6000: Remove the (now unused) insn type "compare" Segher Boessenkool
@ 2014-12-09 18:57   ` David Edelsohn
  0 siblings, 0 replies; 33+ messages in thread
From: David Edelsohn @ 2014-12-09 18:57 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: GCC Patches

On Mon, Dec 8, 2014 at 9:18 AM, Segher Boessenkool
<segher@kernel.crashing.org> wrote:
>
> 2014-12-08  Segher Boessenkool  <segher@kernel.crashing.org>
>
> gcc/
>         * config/rs6000/40x.md (ppc403-compare): Remove "compare".
>         config/rs6000/440.md (ppc440-compare): Remove "compare".
>         config/rs6000/476.md (ppc476-compare): Remove "compare".
>         config/rs6000/601.md (ppc601-compare): Remove "compare".
>         config/rs6000/603.md (ppc603-compare): Remove "compare".
>         config/rs6000/6xx.md (ppc604-compare): Remove "compare".
>         config/rs6000/7450.md (ppc7450-compare): Remove "compare".
>         config/rs6000/7xx.md (ppc750-compare): Remove "compare".
>         config/rs6000/8540.md (ppc8540_su): Remove "compare".
>         config/rs6000/cell.md (cell-fast-cmp, cell-cmp-microcoded): Remove
>         "compare".
>         config/rs6000/e300c2c3.md (ppce300c3_cmp): Remove "compare".
>         config/rs6000/e500mc.md (e500mc_su): Remove "compare".
>         config/rs6000/e500mc64.md (e500mc64_su2): Remove "compare".
>         config/rs6000/e5500.md (e5500_sfx2): Remove "compare".
>         config/rs6000/e6500.md (e6500_sfx2): Remove "compare".
>         config/rs6000/mpc.md (mpccore-compare): Remove "compare".
>         config/rs6000/power4.md (power4-compare): Remove "compare".
>         config/rs6000/power5.md (power5-compare): Remove "compare".
>         config/rs6000/power6.md (power6-compare): Remove "compare".
>         config/rs6000/power7.md (power7-compare): Remove "compare".
>         config/rs6000/power8.md (power8-compare): Remove "compare".  Update
>         comment.
>         config/rs6000/rs6000.c (rs6000_adjust_cost) <TYPE_COMPARE>: Remove
>         (three times).
>         (is_cracked_insn): Remove TYPE_COMPARE case.
>         (insn_must_be_first_in_group) <TYPE_COMPARE>: Remove (twice).
>         config/rs6000/rs6000.md (type): Remove "compare".
>         (cell_micro): Remove "compare".
>         config/rs6000/rs64.md (rs64a-compare): Remove "compare".

Okay.

Thanks, David

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH 01/10] rs6000: Clobber XER[CA] in all user asm statements
  2014-12-08 14:25   ` David Edelsohn
@ 2014-12-09 21:48     ` Richard Henderson
  0 siblings, 0 replies; 33+ messages in thread
From: Richard Henderson @ 2014-12-09 21:48 UTC (permalink / raw)
  To: David Edelsohn, Segher Boessenkool; +Cc: GCC Patches

On 12/08/2014 06:25 AM, David Edelsohn wrote:
> Okay.  I don't know of another option that preserves backward
> compatibility.  If RTH looks at this series of patches, he may have a
> better suggestion.

No, this looks like what I'd do.

Indeed, I added this hook back when the i386 port gained direct
support for the flags register, so it's exactly what I did.  ;-)


r~

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH 06/10] rs6000: New add/subf carry insns
  2014-12-08 15:53     ` David Edelsohn
@ 2014-12-10 14:00       ` Segher Boessenkool
  2014-12-10 14:39         ` David Edelsohn
  0 siblings, 1 reply; 33+ messages in thread
From: Segher Boessenkool @ 2014-12-10 14:00 UTC (permalink / raw)
  To: David Edelsohn; +Cc: GCC Patches

On Mon, Dec 08, 2014 at 10:53:21AM -0500, David Edelsohn wrote:
> As we both noticed, there are a few problems with this patch, so I'll
> wait for a revised version.

Here it is.  It took a bit longer because of a latent problem in combine
(ugh!) that caused mysterious failures in guality (double ugh).

For the carry_in patterns I now have an expander that expands to the
_0 and _m1 cases directly.

Okay for mainline?

Cheers,


Segher



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

gcc/
	PR target/64180
	* config/rs6000/predicates.md (adde_operand): New.
	* config/rs6000/rs6000.md (add<mode>3_carry): New.
	(*add<mode>3_imm_carry_pos): New.
	(*add<mode>3_imm_carry_0): New.
	(*add<mode>3_imm_carry_m1): New.
	(*add<mode>3_imm_carry_neg): New.
	(add<mode>3_carry_in): New.
	(*add<mode>3_carry_in): New.
	(add<mode>3_carry_in_0): New.
	(add<mode>3_carry_in_m1): New.
	(subf<mode>3_carry): New.
	(*subf<mode>3_imm_carry_0): New.
	(*subf<mode>3_imm_carry_m1): New.
	(subf<mode>3_carry_in): New.
	(*subf<mode>3_carry_in): New.
	(subf<mode>3_carry_in_0): New.
	(subf<mode>3_carry_in_m1): New.
	(subf<mode>3_carry_in_xx): New.

---
 gcc/config/rs6000/predicates.md |   6 ++
 gcc/config/rs6000/rs6000.md     | 200 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 206 insertions(+)

diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md
index ea230a5..a19cb2f 100644
--- a/gcc/config/rs6000/predicates.md
+++ b/gcc/config/rs6000/predicates.md
@@ -788,6 +788,12 @@ (define_predicate "add_operand"
 		 || satisfies_constraint_L (op)")
     (match_operand 0 "gpc_reg_operand")))
 
+;; Return 1 if the operand is either a non-special register, or 0, or -1.
+(define_predicate "adde_operand"
+  (if_then_else (match_code "const_int")
+    (match_test "INTVAL (op) == 0 || INTVAL (op) == -1")
+    (match_operand 0 "gpc_reg_operand")))
+
 ;; Return 1 if OP is a constant but not a valid add_operand.
 (define_predicate "non_add_cint_operand"
   (and (match_code "const_int")
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index dcdb7c1..63ca3c2 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -1634,6 +1634,115 @@ (define_split
     FAIL;
 })
 
+
+(define_insn "add<mode>3_carry"
+  [(set (match_operand:P 0 "gpc_reg_operand" "=r")
+	(plus:P (match_operand:P 1 "gpc_reg_operand" "r")
+		(match_operand:P 2 "reg_or_short_operand" "rI")))
+   (set (reg:P CA_REGNO)
+	(ltu:P (plus:P (match_dup 1)
+		       (match_dup 2))
+	       (match_dup 1)))]
+  ""
+  "add%I2c %0,%1,%2"
+  [(set_attr "type" "add")])
+
+(define_insn "*add<mode>3_imm_carry_pos"
+  [(set (match_operand:P 0 "gpc_reg_operand" "=r")
+	(plus:P (match_operand:P 1 "gpc_reg_operand" "r")
+		(match_operand:P 2 "short_cint_operand" "n")))
+   (set (reg:P CA_REGNO)
+	(geu:P (match_dup 1)
+	       (match_operand:P 3 "const_int_operand" "n")))]
+  "INTVAL (operands[2]) > 0
+   && INTVAL (operands[2]) + INTVAL (operands[3]) == 0"
+  "addic %0,%1,%2"
+  [(set_attr "type" "add")])
+
+(define_insn "*add<mode>3_imm_carry_0"
+  [(set (match_operand:P 0 "gpc_reg_operand" "=r")
+	(match_operand:P 1 "gpc_reg_operand" "r"))
+   (set (reg:P CA_REGNO)
+	(const_int 0))]
+  ""
+  "addic %0,%1,0"
+  [(set_attr "type" "add")])
+
+(define_insn "*add<mode>3_imm_carry_m1"
+  [(set (match_operand:P 0 "gpc_reg_operand" "=r")
+	(plus:P (match_operand:P 1 "gpc_reg_operand" "r")
+		(const_int -1)))
+   (set (reg:P CA_REGNO)
+	(ne:P (match_dup 1)
+	      (const_int 0)))]
+  ""
+  "addic %0,%1,-1"
+  [(set_attr "type" "add")])
+
+(define_insn "*add<mode>3_imm_carry_neg"
+  [(set (match_operand:P 0 "gpc_reg_operand" "=r")
+	(plus:P (match_operand:P 1 "gpc_reg_operand" "r")
+		(match_operand:P 2 "short_cint_operand" "n")))
+   (set (reg:P CA_REGNO)
+	(gtu:P (match_dup 1)
+	       (match_operand:P 3 "const_int_operand" "n")))]
+  "INTVAL (operands[2]) < 0
+   && INTVAL (operands[2]) + INTVAL (operands[3]) == -1"
+  "addic %0,%1,%2"
+  [(set_attr "type" "add")])
+
+
+(define_expand "add<mode>3_carry_in"
+  [(parallel [
+     (set (match_operand:GPR 0 "gpc_reg_operand")
+	  (plus:GPR (plus:GPR (match_operand:GPR 1 "gpc_reg_operand")
+			      (match_operand:GPR 2 "adde_operand"))
+		    (reg:GPR CA_REGNO)))
+     (clobber (reg:GPR CA_REGNO))])]
+  ""
+{
+  if (operands[2] == const0_rtx)
+    {
+      emit_insn (gen_add<mode>3_carry_in_0 (operands[0], operands[1]));
+      DONE;
+    }
+  if (operands[2] == constm1_rtx)
+    {
+      emit_insn (gen_add<mode>3_carry_in_m1 (operands[0], operands[1]));
+      DONE;
+    }
+})
+
+(define_insn "*add<mode>3_carry_in"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+	(plus:GPR (plus:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")
+			    (match_operand:GPR 2 "gpc_reg_operand" "r"))
+		  (reg:GPR CA_REGNO)))
+   (clobber (reg:GPR CA_REGNO))]
+  ""
+  "adde %0,%1,%2"
+  [(set_attr "type" "add")])
+
+(define_insn "add<mode>3_carry_in_0"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+	(plus:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")
+		  (reg:GPR CA_REGNO)))
+   (clobber (reg:GPR CA_REGNO))]
+  ""
+  "addze %0,%1"
+  [(set_attr "type" "add")])
+
+(define_insn "add<mode>3_carry_in_m1"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+	(plus:GPR (plus:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")
+			    (reg:GPR CA_REGNO))
+		  (const_int -1)))
+   (clobber (reg:GPR CA_REGNO))]
+  ""
+  "addme %0,%1"
+  [(set_attr "type" "add")])
+
+
 (define_expand "one_cmpl<mode>2"
   [(set (match_operand:SDI 0 "gpc_reg_operand" "")
 	(not:SDI (match_operand:SDI 1 "gpc_reg_operand" "")))]
@@ -1772,6 +1881,97 @@ (define_insn "subf<mode>3_imm"
   [(set_attr "type" "add")])
 
 
+(define_insn "subf<mode>3_carry"
+  [(set (match_operand:P 0 "gpc_reg_operand" "=r")
+	(minus:P (match_operand:P 2 "reg_or_short_operand" "rI")
+		 (match_operand:P 1 "gpc_reg_operand" "r")))
+   (set (reg:P CA_REGNO)
+	(leu:P (match_dup 1)
+	       (match_dup 2)))]
+  ""
+  "subf%I2c %0,%1,%2"
+  [(set_attr "type" "add")])
+
+(define_insn "*subf<mode>3_imm_carry_0"
+  [(set (match_operand:P 0 "gpc_reg_operand" "=r")
+	(neg:P (match_operand:P 1 "gpc_reg_operand" "r")))
+   (set (reg:P CA_REGNO)
+	(eq:P (match_dup 1)
+	      (const_int 0)))]
+  ""
+  "subfic %0,%1,0"
+  [(set_attr "type" "add")])
+
+(define_insn "*subf<mode>3_imm_carry_m1"
+  [(set (match_operand:P 0 "gpc_reg_operand" "=r")
+	(not:P (match_operand:P 1 "gpc_reg_operand" "r")))
+   (set (reg:P CA_REGNO)
+	(const_int 1))]
+  ""
+  "subfic %0,%1,-1"
+  [(set_attr "type" "add")])
+
+
+(define_expand "subf<mode>3_carry_in"
+  [(parallel [
+     (set (match_operand:GPR 0 "gpc_reg_operand")
+	  (plus:GPR (plus:GPR (not:GPR (match_operand:GPR 1 "gpc_reg_operand"))
+			      (reg:GPR CA_REGNO))
+		    (match_operand:GPR 2 "adde_operand")))
+     (clobber (reg:GPR CA_REGNO))])]
+  ""
+{
+  if (operands[2] == const0_rtx)
+    {
+      emit_insn (gen_subf<mode>3_carry_in_0 (operands[0], operands[1]));
+      DONE;
+    }
+  if (operands[2] == constm1_rtx)
+    {
+      emit_insn (gen_subf<mode>3_carry_in_m1 (operands[0], operands[1]));
+      DONE;
+    }
+})
+
+(define_insn "*subf<mode>3_carry_in"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+	(plus:GPR (plus:GPR (not:GPR (match_operand:GPR 1 "gpc_reg_operand" "r"))
+			    (reg:GPR CA_REGNO))
+		  (match_operand:GPR 2 "gpc_reg_operand" "r")))
+   (clobber (reg:GPR CA_REGNO))]
+  ""
+  "subfe %0,%1,%2"
+  [(set_attr "type" "add")])
+
+(define_insn "subf<mode>3_carry_in_0"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+	(plus:GPR (not:GPR (match_operand:GPR 1 "gpc_reg_operand" "r"))
+		  (reg:GPR CA_REGNO)))
+   (clobber (reg:GPR CA_REGNO))]
+  ""
+  "subfze %0,%1"
+  [(set_attr "type" "add")])
+
+(define_insn "subf<mode>3_carry_in_m1"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+	(plus:GPR (minus:GPR (reg:GPR CA_REGNO)
+			     (match_operand:GPR 1 "gpc_reg_operand" "r"))
+		  (const_int -2)))
+   (clobber (reg:GPR CA_REGNO))]
+  ""
+  "subfme %0,%1"
+  [(set_attr "type" "add")])
+
+(define_insn "subf<mode>3_carry_in_xx"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+	(plus:GPR (reg:GPR CA_REGNO)
+		  (const_int -1)))
+   (clobber (reg:GPR CA_REGNO))]
+  ""
+  "subfe %0,%0,%0"
+  [(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" "")))]
-- 
1.8.1.4

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH 06/10] rs6000: New add/subf carry insns
  2014-12-10 14:00       ` Segher Boessenkool
@ 2014-12-10 14:39         ` David Edelsohn
  0 siblings, 0 replies; 33+ messages in thread
From: David Edelsohn @ 2014-12-10 14:39 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: GCC Patches

On Wed, Dec 10, 2014 at 9:00 AM, Segher Boessenkool
<segher@kernel.crashing.org> wrote:
> On Mon, Dec 08, 2014 at 10:53:21AM -0500, David Edelsohn wrote:
>> As we both noticed, there are a few problems with this patch, so I'll
>> wait for a revised version.
>
> Here it is.  It took a bit longer because of a latent problem in combine
> (ugh!) that caused mysterious failures in guality (double ugh).
>
> For the carry_in patterns I now have an expander that expands to the
> _0 and _m1 cases directly.
>
> Okay for mainline?
>
> Cheers,
>
>
> Segher
>
>
>
> 2014-12-10  Segher Boessenkool  <segher@kernel.crashing.org>
>
> gcc/
>         PR target/64180
>         * config/rs6000/predicates.md (adde_operand): New.
>         * config/rs6000/rs6000.md (add<mode>3_carry): New.
>         (*add<mode>3_imm_carry_pos): New.
>         (*add<mode>3_imm_carry_0): New.
>         (*add<mode>3_imm_carry_m1): New.
>         (*add<mode>3_imm_carry_neg): New.
>         (add<mode>3_carry_in): New.
>         (*add<mode>3_carry_in): New.

Please name this *add<mode>3_carry_in_internal

>         (add<mode>3_carry_in_0): New.
>         (add<mode>3_carry_in_m1): New.
>         (subf<mode>3_carry): New.
>         (*subf<mode>3_imm_carry_0): New.
>         (*subf<mode>3_imm_carry_m1): New.
>         (subf<mode>3_carry_in): New.
>         (*subf<mode>3_carry_in): New.

Please name this *subf<mode>3_carry_in_internal

>         (subf<mode>3_carry_in_0): New.
>         (subf<mode>3_carry_in_m1): New.
>         (subf<mode>3_carry_in_xx): New.

Okay with those changes.

Thanks for all of the great improvements!

- David

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH 01/10] rs6000: Clobber XER[CA] in all user asm statements
  2014-12-08 14:18 ` [PATCH 01/10] rs6000: Clobber XER[CA] in all user asm statements Segher Boessenkool
  2014-12-08 14:25   ` David Edelsohn
@ 2015-01-19  8:41   ` Hans-Peter Nilsson
  2015-01-19 15:13     ` Segher Boessenkool
  1 sibling, 1 reply; 33+ messages in thread
From: Hans-Peter Nilsson @ 2015-01-19  8:41 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: gcc-patches, dje.gcc

On Mon, 8 Dec 2014, Segher Boessenkool wrote:

> A lot of old user code clobbers the carry bit without telling the compiler
> about it.  This used to just work, because the compiler never used the bit
> outside of a single RTL instruction.  But that will change.  Let's clobber
> the carry bit in every asm; this isn't very expensive.

There's also the option of clobbering it only if it's not
explicitly mentioned in the asm, say with a singleton
regclass, see cris_md_asm_clobbers.

brgds, H-P

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH 01/10] rs6000: Clobber XER[CA] in all user asm statements
  2015-01-19  8:41   ` Hans-Peter Nilsson
@ 2015-01-19 15:13     ` Segher Boessenkool
  0 siblings, 0 replies; 33+ messages in thread
From: Segher Boessenkool @ 2015-01-19 15:13 UTC (permalink / raw)
  To: Hans-Peter Nilsson; +Cc: gcc-patches, dje.gcc

On Mon, Jan 19, 2015 at 01:53:06AM -0500, Hans-Peter Nilsson wrote:
> On Mon, 8 Dec 2014, Segher Boessenkool wrote:
> 
> > A lot of old user code clobbers the carry bit without telling the compiler
> > about it.  This used to just work, because the compiler never used the bit
> > outside of a single RTL instruction.  But that will change.  Let's clobber
> > the carry bit in every asm; this isn't very expensive.
> 
> There's also the option of clobbering it only if it's not
> explicitly mentioned in the asm, say with a singleton
> regclass, see cris_md_asm_clobbers.

It's a fixed register.  The register class we have for it complains
about inconsistent operand constraints whenever you try to use it
(since at least 4.7, and it would never have worked: the compiler
used to clobber the carry reg implicitly all over the place, so you
could never use the register class safely).

I'll remove the register class next stage1.  Thanks for bringing
it to attention.

Cheers,


Segher

^ permalink raw reply	[flat|nested] 33+ messages in thread

end of thread, other threads:[~2015-01-19 15:00 UTC | newest]

Thread overview: 33+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-12-08 14:18 [PATCH 00/10] rs6000: Carry bit improvements Segher Boessenkool
2014-12-08 14:18 ` [PATCH 02/10] rs6000: Remove addic alternative from various lo_sum patterns Segher Boessenkool
2014-12-08 14:27   ` David Edelsohn
2014-12-08 14:18 ` [PATCH 01/10] rs6000: Clobber XER[CA] in all user asm statements Segher Boessenkool
2014-12-08 14:25   ` David Edelsohn
2014-12-09 21:48     ` Richard Henderson
2015-01-19  8:41   ` Hans-Peter Nilsson
2015-01-19 15:13     ` Segher Boessenkool
2014-12-08 14:18 ` [PATCH 03/10] rs6000: Do not use addic in the ctr* splitters Segher Boessenkool
2014-12-08 14:28   ` David Edelsohn
2014-12-08 14:47 ` [PATCH 09/10] rs6000: Remove the (now unused) insn type "compare" Segher Boessenkool
2014-12-09 18:57   ` David Edelsohn
2014-12-08 14:47 ` [PATCH 08/10] rs6000: compare->two for rld*;rld* Segher Boessenkool
2014-12-09 18:56   ` David Edelsohn
2014-12-08 14:47 ` [PATCH 06/10] rs6000: New add/subf carry insns Segher Boessenkool
2014-12-08 15:41   ` David Edelsohn
2014-12-08 15:53     ` David Edelsohn
2014-12-10 14:00       ` Segher Boessenkool
2014-12-10 14:39         ` David Edelsohn
2014-12-08 14:47 ` [PATCH 05/10] rs6000: Merge and split add and addic Segher Boessenkool
2014-12-08 15:31   ` David Edelsohn
2014-12-08 14:47 ` [PATCH 04/10] rs6000: Remove addic from the normal add pattern Segher Boessenkool
2014-12-08 14:44   ` David Edelsohn
2014-12-08 15:01     ` Segher Boessenkool
2014-12-08 15:10       ` David Edelsohn
2014-12-09 16:25         ` Eric Botcazou
2014-12-09 16:48           ` David Edelsohn
2014-12-09 17:01             ` Segher Boessenkool
2014-12-09 17:12       ` Segher Boessenkool
2014-12-08 14:47 ` [PATCH 07/10] rs6000: The big carry insns addition Segher Boessenkool
2014-12-09 18:56   ` David Edelsohn
2014-12-08 14:47 ` [PATCH 10/10] rs6000: Get rid of the weird decimal thing in add Segher Boessenkool
2014-12-09 18:57   ` David Edelsohn

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).