[08/29,arm] Introduce arm_carry_operation
diff mbox series

Message ID 20191018194900.34795-9-Richard.Earnshaw@arm.com
State New
Headers show
Series
  • Rewrite DImode arithmetic support
Related show

Commit Message

Richard Earnshaw (lists) Oct. 18, 2019, 7:48 p.m. UTC
An earlier patch introduced arm_borrow_operation, this one introduces
the carry variant, which is the same except that the logic of the
carry-setting is inverted.  Having done this we can now match more
cases where the carry flag is propagated from comparisons with
different modes without having to define even more patterns.  A few
small changes to the expand patterns are required to directly create
the carry representation.

The iterators LTUGEU is no-longer needed and removed, as is the code
attribute 'cnb'.

Finally, we fix a long-standing bug which was probably inert before:
in Thumb2 a shift with ADC can only be by an immediate amount;
register-specified shifts are not permitted.

	* config/arm/predicates.md (arm_carry_operation): New special
	predicate.
	* config/arm/iterators.md (LTUGEU): Delete iterator.
	(cnb): Delete code attribute.
	(optab): Delete ltu and geu elements.
	* config/arm/arm.md (addsi3_carryin): Renamed from
	addsi3_carryin_<optab>.  Remove iterator and use arm_carry_operand.
	(add0si3_carryin): Similarly, but from add0si3_carryin_<optab>.
	(addsi3_carryin_alt2): Similarly, but from addsi3_carryin_alt2_<optab>.
	(addsi3_carryin_clobercc): Similarly.
	(addsi3_carryin_shift): Similarly.  Do not allow register shifts in
	Thumb2 state.
---
 gcc/config/arm/arm.md        | 36 ++++++++++++++++++++----------------
 gcc/config/arm/iterators.md  | 11 +----------
 gcc/config/arm/predicates.md | 21 +++++++++++++++++++++
 3 files changed, 42 insertions(+), 26 deletions(-)

Patch
diff mbox series

diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index f597a277c17..f53dbc27207 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -471,10 +471,12 @@  (define_expand "adddi3"
 	    hi_op2 = force_reg (SImode, hi_op2);
 
 	  emit_insn (gen_addsi3_compareC (lo_dest, lo_op1, lo_op2));
+	  rtx carry = gen_rtx_LTU (SImode, gen_rtx_REG (CC_Cmode, CC_REGNUM),
+				   const0_rtx);
 	  if (hi_op2 == const0_rtx)
-	    emit_insn (gen_add0si3_carryin_ltu (hi_dest, hi_op1));
+	    emit_insn (gen_add0si3_carryin (hi_dest, hi_op1, carry));
 	  else
-	    emit_insn (gen_addsi3_carryin_ltu (hi_dest, hi_op1, hi_op2));
+	    emit_insn (gen_addsi3_carryin (hi_dest, hi_op1, hi_op2, carry));
 	}
 
       if (lo_result != lo_dest)
@@ -858,11 +860,11 @@  (define_insn "*compare_addsi2_op1"
    (set_attr "type" "alus_imm,alus_sreg,alus_imm,alus_imm,alus_sreg")]
  )
 
-(define_insn "addsi3_carryin_<optab>"
+(define_insn "addsi3_carryin"
   [(set (match_operand:SI 0 "s_register_operand" "=l,r,r")
         (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%l,r,r")
                           (match_operand:SI 2 "arm_not_operand" "0,rI,K"))
-                 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
+                 (match_operand:SI 3 "arm_carry_operation" "")))]
   "TARGET_32BIT"
   "@
    adc%?\\t%0, %1, %2
@@ -877,9 +879,9 @@  (define_insn "addsi3_carryin_<optab>"
 )
 
 ;; Canonicalization of the above when the immediate is zero.
-(define_insn "add0si3_carryin_<optab>"
+(define_insn "add0si3_carryin"
   [(set (match_operand:SI 0 "s_register_operand" "=r")
-	(plus:SI (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))
+	(plus:SI (match_operand:SI 2 "arm_carry_operation" "")
 		 (match_operand:SI 1 "arm_not_operand" "r")))]
   "TARGET_32BIT"
   "adc%?\\t%0, %1, #0"
@@ -889,9 +891,9 @@  (define_insn "add0si3_carryin_<optab>"
    (set_attr "type" "adc_imm")]
 )
 
-(define_insn "*addsi3_carryin_alt2_<optab>"
+(define_insn "*addsi3_carryin_alt2"
   [(set (match_operand:SI 0 "s_register_operand" "=l,r,r")
-        (plus:SI (plus:SI (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))
+        (plus:SI (plus:SI (match_operand:SI 3 "arm_carry_operation" "")
                           (match_operand:SI 1 "s_register_operand" "%l,r,r"))
                  (match_operand:SI 2 "arm_not_operand" "l,rI,K")))]
   "TARGET_32BIT"
@@ -907,28 +909,30 @@  (define_insn "*addsi3_carryin_alt2_<optab>"
    (set_attr "type" "adc_reg,adc_reg,adc_imm")]
 )
 
-(define_insn "*addsi3_carryin_shift_<optab>"
-  [(set (match_operand:SI 0 "s_register_operand" "=r")
+(define_insn "*addsi3_carryin_shift"
+  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
 	(plus:SI (plus:SI
 		  (match_operator:SI 2 "shift_operator"
-		    [(match_operand:SI 3 "s_register_operand" "r")
-		     (match_operand:SI 4 "reg_or_int_operand" "rM")])
-		  (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0)))
-		 (match_operand:SI 1 "s_register_operand" "r")))]
+		    [(match_operand:SI 3 "s_register_operand" "r,r")
+		     (match_operand:SI 4 "shift_amount_operand" "M,r")])
+		  (match_operand:SI 5 "arm_carry_operation" ""))
+		 (match_operand:SI 1 "s_register_operand" "r,r")))]
   "TARGET_32BIT"
   "adc%?\\t%0, %1, %3%S2"
   [(set_attr "conds" "use")
+   (set_attr "arch" "32,a")
+   (set_attr "shift" "3")
    (set_attr "predicable" "yes")
    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
 		      (const_string "alu_shift_imm")
 		      (const_string "alu_shift_reg")))]
 )
 
-(define_insn "*addsi3_carryin_clobercc_<optab>"
+(define_insn "*addsi3_carryin_clobercc"
   [(set (match_operand:SI 0 "s_register_operand" "=r")
 	(plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%r")
 			  (match_operand:SI 2 "arm_rhs_operand" "rI"))
-		 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))
+		 (match_operand:SI 3 "arm_carry_operation" "")))
    (clobber (reg:CC CC_REGNUM))]
    "TARGET_32BIT"
    "adcs%?\\t%0, %1, %2"
diff --git a/gcc/config/arm/iterators.md b/gcc/config/arm/iterators.md
index 8c9f7121951..77e1645083f 100644
--- a/gcc/config/arm/iterators.md
+++ b/gcc/config/arm/iterators.md
@@ -219,11 +219,6 @@  (define_mode_iterator VPF [V8QI V16QI V2SF V4SF])
 ;; Code iterators
 ;;----------------------------------------------------------------------------
 
-;; A list of condition codes used in compare instructions where
-;; the carry flag from the addition is used instead of doing the
-;; compare a second time.
-(define_code_iterator LTUGEU [ltu geu])
-
 ;; The signed gt, ge comparisons
 (define_code_iterator GTGE [gt ge])
 
@@ -809,13 +804,9 @@  (define_code_attr VQH_type [(plus "add") (smin "minmax") (smax "minmax")
 (define_code_attr VQH_sign [(plus "i") (smin "s") (smax "s") (umin "u")
                 (umax "u")])
 
-(define_code_attr cnb [(ltu "CC_C") (geu "CC")])
-
 ;; Map rtl operator codes to optab names
 (define_code_attr optab
- [(ltu "ltu")
-  (geu "geu")
-  (and "and")
+ [(and "and")
   (ior "ior")
   (xor "xor")])
 
diff --git a/gcc/config/arm/predicates.md b/gcc/config/arm/predicates.md
index e6766a97fc4..ed7495b69fc 100644
--- a/gcc/config/arm/predicates.md
+++ b/gcc/config/arm/predicates.md
@@ -356,6 +356,27 @@  (define_predicate "arm_comparison_operator_mode"
 (define_special_predicate "lt_ge_comparison_operator"
   (match_code "lt,ge"))
 
+(define_special_predicate "arm_carry_operation"
+  (match_code "geu,ltu")
+  {
+    if (XEXP (op, 1) != const0_rtx)
+      return false;
+
+    rtx op0 = XEXP (op, 0);
+
+    if (!REG_P (op0) || REGNO (op0) != CC_REGNUM)
+      return false;
+
+    machine_mode ccmode = GET_MODE (op0);
+    if (ccmode == CC_Cmode)
+      return GET_CODE (op) == LTU;
+    else if (ccmode == CCmode || ccmode == CC_RSBmode)
+      return GET_CODE (op) == GEU;
+
+    return false;
+  }
+)
+
 ;; Match a "borrow" operation for use with SBC.  The precise code will
 ;; depend on the form of the comparison.  This is generally the inverse of
 ;; a carry operation, since the logic of SBC uses "not borrow" in it's