From d84b9ad53fed75590c3ebc6e38bd49db3b201128 Mon Sep 17 00:00:00 2001 From: Richard Earnshaw Date: Thu, 31 Oct 2019 16:04:53 +0000 Subject: [PATCH] [arm] Pattern match insns for a + ~b + Carry On ARM, the SBC instruction is defined as Ra - Rb - ~C where C is the carry flag. But -Rb = ~Rb + 1, so this is equivalent to Ra + ~Rb + 1 - ~C which then simplifies to Ra + ~Rb + C which is essentially an add-with-carry with one operand inverted. We can define RTL patterns to match this. In thumb2 we can only match when the operands are both registers, but in Arm state we can also use RSC to match when Rn is either a constant or a shifted operand. This overall simplifies some cases of 64-bit arithmetic, for example, int64_t f (int64_t a, int64_t b) { return a + ~b; } will now compile to MVN R2, R2 ADDS R0, R0, R2 SBC R1, R1, R3 * config/arm/arm.md (add_not_cin): New insn. (add_not_shift_cin): Likewise. From-SVN: r277676 --- gcc/ChangeLog | 5 +++++ gcc/config/arm/arm.md | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5ce04fe3f3c..e520cf05403 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2019-10-31 Richard Earnshaw + + * config/arm/arm.md (add_not_cin): New insn. + (add_not_shift_cin): Likewise. + 2019-10-31 Martin Liska * ipa-icf-gimple.c (func_checker::compare_tree_ssa_label): Remove. diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md index ae77cc377f6..4f035cbfddd 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -1662,6 +1662,41 @@ (set_attr "type" "adc_imm")] ) +;; SBC performs Rn - Rm - ~C, but -Rm = ~Rm + 1 => Rn + ~Rm + 1 - ~C +;; => Rn + ~Rm + C, which is essentially ADC Rd, Rn, ~Rm +(define_insn "*add_not_cin" + [(set (match_operand:SI 0 "s_register_operand" "=r,r") + (plus:SI + (plus:SI (not:SI (match_operand:SI 1 "s_register_operand" "r,r")) + (match_operand:SI 3 "arm_carry_operation" "")) + (match_operand:SI 2 "arm_rhs_operand" "r,I")))] + "TARGET_ARM || (TARGET_THUMB2 && !CONST_INT_P (operands[2]))" + "@ + sbc%?\\t%0, %2, %1 + rsc%?\\t%0, %1, %2" + [(set_attr "conds" "use") + (set_attr "predicable" "yes") + (set_attr "arch" "*,a") + (set_attr "type" "adc_reg,adc_imm")] +) + +;; On Arm we can also use the same trick when the non-inverted operand is +;; shifted, using RSC. +(define_insn "add_not_shift_cin" + [(set (match_operand:SI 0 "s_register_operand" "=r,r") + (plus:SI + (plus:SI (match_operator:SI 3 "shift_operator" + [(match_operand:SI 1 "s_register_operand" "r,r") + (match_operand:SI 2 "shift_amount_operand" "M,r")]) + (not:SI (match_operand:SI 4 "s_register_operand" "r,r"))) + (match_operand:SI 5 "arm_carry_operation" "")))] + "TARGET_ARM" + "rsc%?\\t%0, %4, %1%S3" + [(set_attr "conds" "use") + (set_attr "predicable" "yes") + (set_attr "type" "alu_shift_imm,alu_shift_reg")] +) + (define_insn "cmpsi3_carryin_out" [(set (reg: CC_REGNUM) (compare: -- 2.30.2