[arm] Introduce arm_carry_operation

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
This commit is contained in:
Richard Earnshaw 2019-10-18 19:02:35 +00:00 committed by Richard Earnshaw
parent bc8dd50fe4
commit 1e271beeec
4 changed files with 57 additions and 26 deletions

View 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> 2019-10-18 Richard Earnshaw <rearnsha@arm.com>
* config/arm/arm.md (arm_subdi3): Delete insn. * config/arm/arm.md (arm_subdi3): Delete insn.

View File

@ -471,10 +471,12 @@
hi_op2 = force_reg (SImode, hi_op2); hi_op2 = force_reg (SImode, hi_op2);
emit_insn (gen_addsi3_compareC (lo_dest, lo_op1, lo_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) 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 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) if (lo_result != lo_dest)
@ -858,11 +860,11 @@
(set_attr "type" "alus_imm,alus_sreg,alus_imm,alus_imm,alus_sreg")] (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") [(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") (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%l,r,r")
(match_operand:SI 2 "arm_not_operand" "0,rI,K")) (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" "TARGET_32BIT"
"@ "@
adc%?\\t%0, %1, %2 adc%?\\t%0, %1, %2
@ -877,9 +879,9 @@
) )
;; Canonicalization of the above when the immediate is zero. ;; 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") [(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")))] (match_operand:SI 1 "arm_not_operand" "r")))]
"TARGET_32BIT" "TARGET_32BIT"
"adc%?\\t%0, %1, #0" "adc%?\\t%0, %1, #0"
@ -889,9 +891,9 @@
(set_attr "type" "adc_imm")] (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") [(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 1 "s_register_operand" "%l,r,r"))
(match_operand:SI 2 "arm_not_operand" "l,rI,K")))] (match_operand:SI 2 "arm_not_operand" "l,rI,K")))]
"TARGET_32BIT" "TARGET_32BIT"
@ -907,28 +909,30 @@
(set_attr "type" "adc_reg,adc_reg,adc_imm")] (set_attr "type" "adc_reg,adc_reg,adc_imm")]
) )
(define_insn "*addsi3_carryin_shift_<optab>" (define_insn "*addsi3_carryin_shift"
[(set (match_operand:SI 0 "s_register_operand" "=r") [(set (match_operand:SI 0 "s_register_operand" "=r,r")
(plus:SI (plus:SI (plus:SI (plus:SI
(match_operator:SI 2 "shift_operator" (match_operator:SI 2 "shift_operator"
[(match_operand:SI 3 "s_register_operand" "r") [(match_operand:SI 3 "s_register_operand" "r,r")
(match_operand:SI 4 "reg_or_int_operand" "rM")]) (match_operand:SI 4 "shift_amount_operand" "M,r")])
(LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))) (match_operand:SI 5 "arm_carry_operation" ""))
(match_operand:SI 1 "s_register_operand" "r")))] (match_operand:SI 1 "s_register_operand" "r,r")))]
"TARGET_32BIT" "TARGET_32BIT"
"adc%?\\t%0, %1, %3%S2" "adc%?\\t%0, %1, %3%S2"
[(set_attr "conds" "use") [(set_attr "conds" "use")
(set_attr "arch" "32,a")
(set_attr "shift" "3")
(set_attr "predicable" "yes") (set_attr "predicable" "yes")
(set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "") (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
(const_string "alu_shift_imm") (const_string "alu_shift_imm")
(const_string "alu_shift_reg")))] (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") [(set (match_operand:SI 0 "s_register_operand" "=r")
(plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%r") (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%r")
(match_operand:SI 2 "arm_rhs_operand" "rI")) (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))] (clobber (reg:CC CC_REGNUM))]
"TARGET_32BIT" "TARGET_32BIT"
"adcs%?\\t%0, %1, %2" "adcs%?\\t%0, %1, %2"

View File

@ -219,11 +219,6 @@
;; Code iterators ;; 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 ;; The signed gt, ge comparisons
(define_code_iterator GTGE [gt ge]) (define_code_iterator GTGE [gt ge])
@ -809,13 +804,9 @@
(define_code_attr VQH_sign [(plus "i") (smin "s") (smax "s") (umin "u") (define_code_attr VQH_sign [(plus "i") (smin "s") (smax "s") (umin "u")
(umax "u")]) (umax "u")])
(define_code_attr cnb [(ltu "CC_C") (geu "CC")])
;; Map rtl operator codes to optab names ;; Map rtl operator codes to optab names
(define_code_attr optab (define_code_attr optab
[(ltu "ltu") [(and "and")
(geu "geu")
(and "and")
(ior "ior") (ior "ior")
(xor "xor")]) (xor "xor")])

View File

@ -356,6 +356,27 @@
(define_special_predicate "lt_ge_comparison_operator" (define_special_predicate "lt_ge_comparison_operator"
(match_code "lt,ge")) (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 ;; 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 ;; 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 ;; a carry operation, since the logic of SBC uses "not borrow" in it's