diff mbox series

[arm] Match subtraction from carry_operation

Message ID 2894905c-7b63-2d66-aceb-d37eadbd20f2@arm.com
State New
Headers show
Series [arm] Match subtraction from carry_operation | expand

Commit Message

Richard Earnshaw (lists) Oct. 22, 2019, 1:21 p.m. UTC
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.

Committed to trunk.

R.
diff mbox series

Patch

diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 5491ad0fb43..5c2c48f4253 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 039fdd02479..ae77cc377f6 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -1649,6 +1649,19 @@  (define_insn "subsi3_carryin"
    (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>