diff options
author | Richard Earnshaw <rearnsha@arm.com> | 2019-10-18 19:02:35 +0000 |
---|---|---|
committer | Richard Earnshaw <rearnsha@gcc.gnu.org> | 2019-10-18 19:02:35 +0000 |
commit | 1e271beeec163b124eb424c0c9918b045e289c06 (patch) | |
tree | e7d468a16e2a7534dd19d7c78a76febb470813d0 /gcc | |
parent | bc8dd50fe4cddc779349ef79f55e9e623c3c215f (diff) | |
download | gcc-1e271beeec163b124eb424c0c9918b045e289c06.zip gcc-1e271beeec163b124eb424c0c9918b045e289c06.tar.gz gcc-1e271beeec163b124eb424c0c9918b045e289c06.tar.bz2 |
[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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 15 | ||||
-rw-r--r-- | gcc/config/arm/arm.md | 36 | ||||
-rw-r--r-- | gcc/config/arm/iterators.md | 11 | ||||
-rw-r--r-- | gcc/config/arm/predicates.md | 21 |
4 files changed, 57 insertions, 26 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0051bbb..e4f10c6 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,20 @@ 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. (zextendsidi_negsi, negdi_extendsidi): Delete insn_and_split. diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md index f597a27..f53dbc2 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -471,10 +471,12 @@ 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 @@ (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 @@ ) ;; 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 @@ (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 @@ (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 8c9f712..77e1645 100644 --- a/gcc/config/arm/iterators.md +++ b/gcc/config/arm/iterators.md @@ -219,11 +219,6 @@ ;; 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_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 e6766a9..ed7495b 100644 --- a/gcc/config/arm/predicates.md +++ b/gcc/config/arm/predicates.md @@ -356,6 +356,27 @@ (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 |