[arm] Introduce arm_carry_operation
authorRichard Earnshaw <rearnsha@arm.com>
Fri, 18 Oct 2019 19:02:35 +0000 (19:02 +0000)
committerRichard Earnshaw <rearnsha@gcc.gnu.org>
Fri, 18 Oct 2019 19:02:35 +0000 (19:02 +0000)
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.

From-SVN: r277171

gcc/ChangeLog
gcc/config/arm/arm.md
gcc/config/arm/iterators.md
gcc/config/arm/predicates.md

index 0051bbbeb32f380843891076d0abc427e3c451ff..e4f10c6eb962cd7f0b638e3906ba1a0d5d426d9a 100644 (file)
@@ -1,3 +1,18 @@
+2019-10-18  Richard Earnshaw  <rearnsha@arm.com>
+
+       * 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.
+
 2019-10-18  Richard Earnshaw  <rearnsha@arm.com>
 
        * config/arm/arm.md (arm_subdi3): Delete insn.
index f597a277c177050d96d9f495c10aa4d207e2df02..f53dbc27207c6d6736fb72b709e046ddc7ed12d5 100644 (file)
            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)
    (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
 )
 
 ;; 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"
    (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"
    (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"
index 8c9f7121951ba319fcb6cf4c73e186f3764917c2..77e1645083fa1605bf542f8ec507b519ef37d72b 100644 (file)
 ;; 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])
 
 (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")])
 
index e6766a97fc41356fd5db556f2209cbac6bd98710..ed7495b69fc430d944ac0ced1c0341bb80e9707b 100644 (file)
 (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