[arm] Match subtraction from carry_operation
authorRichard Earnshaw <rearnsha@arm.com>
Tue, 22 Oct 2019 13:19:15 +0000 (13:19 +0000)
committerRichard Earnshaw <rearnsha@gcc.gnu.org>
Tue, 22 Oct 2019 13:19:15 +0000 (13:19 +0000)
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

gcc/ChangeLog
gcc/config/arm/arm.c
gcc/config/arm/arm.md

index e80bb17738724b666fd79b9d219ee71e2d9ba238..b1a336796323bf337f42a60f26c021f12b490732 100644 (file)
@@ -1,3 +1,9 @@
+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.
index 5491ad0fb43e322c073d6d6dfeed5970fa9cfa73..5c2c48f4253daad429f865d798df593d6bf8856b 100644 (file)
@@ -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)
index 039fdd02479abfc4ad36bf35ce55172cdcfb9c1b..ae77cc377f62478f431b980feb7164e292d39686 100644 (file)
    (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>