diff mbox

[06/10] rs6000: New add/subf carry insns

Message ID 72cecd52901018524525d156113b1be658917f6b.1418024189.git.segher@kernel.crashing.org
State New
Headers show

Commit Message

Segher Boessenkool Dec. 8, 2014, 2:18 p.m. UTC
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(+)

Comments

David Edelsohn Dec. 8, 2014, 3:41 p.m. UTC | #1
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
David Edelsohn Dec. 8, 2014, 3:53 p.m. UTC | #2
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
diff mbox

Patch

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