aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Earnshaw <rearnsha@arm.com>2019-10-22 13:19:15 +0000
committerRichard Earnshaw <rearnsha@gcc.gnu.org>2019-10-22 13:19:15 +0000
commit2e30cb8395130982b8b28a4eb42814f4da1fb6d2 (patch)
treebc2e47c87c976dfbcb205370a614fe10b10bc2b8
parentb747c183714a5d68da8037d8b705a8bc67f11bac (diff)
downloadgcc-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
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/config/arm/arm.c7
-rw-r--r--gcc/config/arm/arm.md13
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>