aboutsummaryrefslogtreecommitdiff
path: root/gcc/config
diff options
context:
space:
mode:
authorRichard Earnshaw <rearnsha@arm.com>2019-10-18 19:02:50 +0000
committerRichard Earnshaw <rearnsha@gcc.gnu.org>2019-10-18 19:02:50 +0000
commitbbead5babc046279d886b059e68e613b0185b2ff (patch)
tree124a99d80876a893377cb89eb847f09c6eca55f6 /gcc/config
parent0a67306e3cc2adfe0ef2fe313a86f57141ab57b2 (diff)
downloadgcc-bbead5babc046279d886b059e68e613b0185b2ff.zip
gcc-bbead5babc046279d886b059e68e613b0185b2ff.tar.gz
gcc-bbead5babc046279d886b059e68e613b0185b2ff.tar.bz2
[arm] Correct cost calculations involving borrow for subtracts.
The rtx_cost calculations when a borrow operation was being performed were not being calculated correctly. The borrow is free as part of the subtract-with-carry instructions. This patch recognizes the various idioms that can describe this and returns the correct costs. * config/arm/arm.c (arm_rtx_costs_internal, case MINUS): Handle borrow operations. From-SVN: r277173
Diffstat (limited to 'gcc/config')
-rw-r--r--gcc/config/arm/arm.c49
1 files changed, 42 insertions, 7 deletions
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 820a41f..fd74222 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -10049,15 +10049,46 @@ arm_rtx_costs_internal (rtx x, enum rtx_code code, enum rtx_code outer_code,
rtx shift_by_reg = NULL;
rtx shift_op;
rtx non_shift_op;
+ rtx op0 = XEXP (x, 0);
+ rtx op1 = XEXP (x, 1);
- shift_op = shifter_op_p (XEXP (x, 0), &shift_by_reg);
+ /* Factor out any borrow operation. There's more than one way
+ of expressing this; try to recognize them all. */
+ if (GET_CODE (op0) == MINUS)
+ {
+ if (arm_borrow_operation (op1, SImode))
+ {
+ op1 = XEXP (op0, 1);
+ op0 = XEXP (op0, 0);
+ }
+ else if (arm_borrow_operation (XEXP (op0, 1), SImode))
+ op0 = XEXP (op0, 0);
+ }
+ else if (GET_CODE (op1) == PLUS
+ && arm_borrow_operation (XEXP (op1, 0), SImode))
+ op1 = XEXP (op1, 0);
+ else if (GET_CODE (op0) == NEG
+ && arm_borrow_operation (op1, SImode))
+ {
+ /* Negate with carry-in. For Thumb2 this is done with
+ SBC R, X, X lsl #1 (ie X - 2X - C) as Thumb lacks the
+ RSC instruction that exists in Arm mode. */
+ if (speed_p)
+ *cost += (TARGET_THUMB2
+ ? extra_cost->alu.arith_shift
+ : extra_cost->alu.arith);
+ *cost += rtx_cost (XEXP (op0, 0), mode, MINUS, 0, speed_p);
+ return true;
+ }
+
+ shift_op = shifter_op_p (op0, &shift_by_reg);
if (shift_op == NULL)
{
- shift_op = shifter_op_p (XEXP (x, 1), &shift_by_reg);
- non_shift_op = XEXP (x, 0);
+ shift_op = shifter_op_p (op1, &shift_by_reg);
+ non_shift_op = op0;
}
else
- non_shift_op = XEXP (x, 1);
+ non_shift_op = op1;
if (shift_op != NULL)
{
@@ -10087,10 +10118,10 @@ arm_rtx_costs_internal (rtx x, enum rtx_code code, enum rtx_code outer_code,
return true;
}
- if (CONST_INT_P (XEXP (x, 0)))
+ if (CONST_INT_P (op0))
{
int insns = arm_gen_constant (MINUS, SImode, NULL_RTX,
- INTVAL (XEXP (x, 0)), NULL_RTX,
+ INTVAL (op0), NULL_RTX,
NULL_RTX, 1, 0);
*cost = COSTS_N_INSNS (insns);
if (speed_p)
@@ -10101,7 +10132,11 @@ arm_rtx_costs_internal (rtx x, enum rtx_code code, enum rtx_code outer_code,
else if (speed_p)
*cost += extra_cost->alu.arith;
- return false;
+ /* Don't recurse as we don't want to cost any borrow that
+ we've stripped. */
+ *cost += rtx_cost (op0, mode, MINUS, 0, speed_p);
+ *cost += rtx_cost (op1, mode, MINUS, 1, speed_p);
+ return true;
}
if (GET_MODE_CLASS (mode) == MODE_INT