diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/config/arm/aarch-common-protos.h | 1 | ||||
-rw-r--r-- | gcc/config/arm/aarch-common.c | 2 | ||||
-rw-r--r-- | gcc/config/arm/arm.c | 46 |
4 files changed, 54 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 797636a..e128ec3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2013-11-19 Kyrylo Tkachov <kyrylo.tkachov@arm.com> + + * config/arm/arm.c (arm_new_rtx_costs): + Handle narrow mode add-shifts properly. + * config/arm/arm-common.c (arm_rtx_shift_left_p): Remove static. + * config/arm/arm-common-protos.h (arm_rtx_shift_left_p): + Declare extern. + 2013-11-19 James Greenhalgh <james.greenhalgh@arm.com> * config/arm/arm.md (zero_extend<mode>di2): Add type attribute. diff --git a/gcc/config/arm/aarch-common-protos.h b/gcc/config/arm/aarch-common-protos.h index 841f544..c3652a7 100644 --- a/gcc/config/arm/aarch-common-protos.h +++ b/gcc/config/arm/aarch-common-protos.h @@ -31,6 +31,7 @@ extern int arm_no_early_alu_shift_dep (rtx, rtx); extern int arm_no_early_alu_shift_value_dep (rtx, rtx); extern int arm_no_early_mul_dep (rtx, rtx); extern int arm_no_early_store_addr_dep (rtx, rtx); +extern bool arm_rtx_shift_left_p (rtx); /* RTX cost table definitions. These are used when tuning for speed rather than for size and should reflect the _additional_ cost over the cost diff --git a/gcc/config/arm/aarch-common.c b/gcc/config/arm/aarch-common.c index 201e581..a46e675 100644 --- a/gcc/config/arm/aarch-common.c +++ b/gcc/config/arm/aarch-common.c @@ -40,7 +40,7 @@ typedef struct /* Return TRUE if X is either an arithmetic shift left, or is a multiplication by a power of two. */ -static bool +bool arm_rtx_shift_left_p (rtx x) { enum rtx_code code = GET_CODE (x); diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 2d5f867..3cd53b0 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -8766,6 +8766,30 @@ arm_unspec_cost (rtx x, enum rtx_code /* outer_code */, bool speed_p, int *cost) call (one insn for -Os) and then one for processing the result. */ #define LIBCALL_COST(N) COSTS_N_INSNS (N + (speed_p ? 18 : 2)) +#define HANDLE_NARROW_SHIFT_ARITH(OP, IDX) \ + do \ + { \ + shift_op = shifter_op_p (XEXP (x, IDX), &shift_reg); \ + if (shift_op != NULL \ + && arm_rtx_shift_left_p (XEXP (x, IDX))) \ + { \ + if (shift_reg) \ + { \ + if (speed_p) \ + *cost += extra_cost->alu.arith_shift_reg; \ + *cost += rtx_cost (shift_reg, ASHIFT, 1, speed_p); \ + } \ + else if (speed_p) \ + *cost += extra_cost->alu.arith_shift; \ + \ + *cost += (rtx_cost (shift_op, ASHIFT, 0, speed_p) \ + + rtx_cost (XEXP (x, 1 - IDX), \ + OP, 1, speed_p)); \ + return true; \ + } \ + } \ + while (0); + /* RTX costs. Make an estimate of the cost of executing the operation X, which is contained with an operation with code OUTER_CODE. SPEED_P indicates whether the cost desired is the performance cost, @@ -9122,6 +9146,15 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code, if (GET_MODE_CLASS (mode) == MODE_INT && GET_MODE_SIZE (mode) < 4) { + rtx shift_op, shift_reg; + shift_reg = NULL; + + /* We check both sides of the MINUS for shifter operands since, + unlike PLUS, it's not commutative. */ + + HANDLE_NARROW_SHIFT_ARITH (MINUS, 0) + HANDLE_NARROW_SHIFT_ARITH (MINUS, 1) + /* Slightly disparage, as we might need to widen the result. */ *cost = 1 + COSTS_N_INSNS (1); if (speed_p) @@ -9221,11 +9254,18 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code, return false; } + /* Narrow modes can be synthesized in SImode, but the range + of useful sub-operations is limited. Check for shift operations + on one of the operands. Only left shifts can be used in the + narrow modes. */ if (GET_MODE_CLASS (mode) == MODE_INT && GET_MODE_SIZE (mode) < 4) { - /* Narrow modes can be synthesized in SImode, but the range - of useful sub-operations is limited. */ + rtx shift_op, shift_reg; + shift_reg = NULL; + + HANDLE_NARROW_SHIFT_ARITH (PLUS, 0) + if (CONST_INT_P (XEXP (x, 1))) { int insns = arm_gen_constant (PLUS, SImode, NULL_RTX, @@ -10344,6 +10384,8 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code, } } +#undef HANDLE_NARROW_SHIFT_ARITH + /* RTX costs when optimizing for size. */ static bool arm_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED, |