Commit 2e30cb83 by Richard Earnshaw Committed by Richard Earnshaw

[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
parent b747c183
2019-10-22 Richard Earnshaw <rearnsha@arm.com> 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. * config/arm/predicates.md (arm_borrow_operation): Handle CC_ADCmode.
2019-10-22 Richard Biener <rguenther@suse.de> 2019-10-22 Richard Biener <rguenther@suse.de>
...@@ -10107,6 +10107,13 @@ arm_rtx_costs_internal (rtx x, enum rtx_code code, enum rtx_code outer_code, ...@@ -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); *cost += rtx_cost (XEXP (op0, 0), mode, MINUS, 0, speed_p);
return true; 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); shift_op = shifter_op_p (op0, &shift_by_reg);
if (shift_op == NULL) if (shift_op == NULL)
......
...@@ -1649,6 +1649,19 @@ ...@@ -1649,6 +1649,19 @@
(set_attr "type" "adc_reg,adc_imm,alu_shift_imm")] (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" (define_insn "cmpsi3_carryin_<CC_EXTEND>out"
[(set (reg:<CC_EXTEND> CC_REGNUM) [(set (reg:<CC_EXTEND> CC_REGNUM)
(compare:<CC_EXTEND> (compare:<CC_EXTEND>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment