diff options
author | Richard Earnshaw <rearnsha@arm.com> | 2019-10-22 13:19:15 +0000 |
---|---|---|
committer | Richard Earnshaw <rearnsha@gcc.gnu.org> | 2019-10-22 13:19:15 +0000 |
commit | 2e30cb8395130982b8b28a4eb42814f4da1fb6d2 (patch) | |
tree | bc2e47c87c976dfbcb205370a614fe10b10bc2b8 /gcc | |
parent | b747c183714a5d68da8037d8b705a8bc67f11bac (diff) | |
download | gcc-2e30cb8395130982b8b28a4eb42814f4da1fb6d2.zip gcc-2e30cb8395130982b8b28a4eb42814f4da1fb6d2.tar.gz gcc-2e30cb8395130982b8b28a4eb42814f4da1fb6d2.tar.bz2 |
[arm] Match subtraction from carry_operation
On Arm we have both carry and borrow operations, but borrow is
essentially '~carry'. Of course, with boolean logic ~carry is also
1-carry.
GCC transforms
(1 - X - LTU (cc, 0))
into
(GEU (cc, 0) - X)
Now the former matches a real insn in Arm state, using the RSC
instruction with #1 as the immediate, but we currently do not
recognize the canonicalized form. Nevertheless, given the above
logic, this turns out to be quite straight forward as the original
expression matches arm_borrow_operation and the revised form can be
used with arm_carry_operation. Since we match this new pattern we
also update rtx_costs to handle it.
* config/arm/arm.md (rsbsi_carryin_reg): New pattern.
* config/arm/arm.c (arm_rtx_costs_internal, case MINUS): Handle
subtraction from a carry operation.
From-SVN: r277290
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/config/arm/arm.c | 7 | ||||
-rw-r--r-- | gcc/config/arm/arm.md | 13 |
3 files changed, 26 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e80bb17..b1a3367 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,11 @@ 2019-10-22 Richard Earnshaw <rearnsha@arm.com> + * config/arm/arm.md (rsbsi_carryin_reg): New pattern. + * config/arm/arm.c (arm_rtx_costs_internal, case MINUS): Handle + subtraction from a carry operation. + +2019-10-22 Richard Earnshaw <rearnsha@arm.com> + * config/arm/predicates.md (arm_borrow_operation): Handle CC_ADCmode. 2019-10-22 Richard Biener <rguenther@suse.de> diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 5491ad0..5c2c48f 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -10107,6 +10107,13 @@ arm_rtx_costs_internal (rtx x, enum rtx_code code, enum rtx_code outer_code, *cost += rtx_cost (XEXP (op0, 0), mode, MINUS, 0, speed_p); return true; } + /* (Carry_op - reg) can be done as RSC Rd, Rn, #1 on Arm. + Note we do mean ~borrow here. */ + else if (TARGET_ARM && arm_carry_operation (op0, SImode)) + { + *cost += rtx_cost (op1, mode, code, 1, speed_p); + return true; + } shift_op = shifter_op_p (op0, &shift_by_reg); if (shift_op == NULL) diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md index 039fdd0..ae77cc3 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -1649,6 +1649,19 @@ (set_attr "type" "adc_reg,adc_imm,alu_shift_imm")] ) +;; Special canonicalization of the above when operand1 == (const_int 1): +;; in this case the 'borrow' needs to treated like subtracting from the carry. +(define_insn "rsbsi_carryin_reg" + [(set (match_operand:SI 0 "s_register_operand" "=r") + (minus:SI (match_operand:SI 1 "arm_carry_operation" "") + (match_operand:SI 2 "s_register_operand" "r")))] + "TARGET_ARM" + "rsc%?\\t%0, %2, #1" + [(set_attr "conds" "use") + (set_attr "predicable" "yes") + (set_attr "type" "adc_imm")] +) + (define_insn "cmpsi3_carryin_<CC_EXTEND>out" [(set (reg:<CC_EXTEND> CC_REGNUM) (compare:<CC_EXTEND> |