From 7548c1be3a1ed1b10f5752a41d8efa3a3dfe01ac Mon Sep 17 00:00:00 2001 From: Wei Guozhi Date: Thu, 8 Apr 2010 09:27:44 +0000 Subject: [PATCH] re PR target/41653 (not optimal result for multiplication with constant when -Os is specified) PR target/41653 * config/arm/arm.c (thumb1_size_rtx_costs): New function. (arm_size_rtx_costs): Call the new function when optimized for size. From-SVN: r158110 --- gcc/ChangeLog | 6 ++ gcc/config/arm/arm.c | 127 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 131 insertions(+), 2 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7e08006de17..94860fafabb 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2010-04-08 Wei Guozhi + + PR target/41653 + * config/arm/arm.c (thumb1_size_rtx_costs): New function. + (arm_size_rtx_costs): Call the new function when optimized for size. + 2010-04-08 Jakub Jelinek PR debug/43670 diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 84dd8fa972b..242ead5f027 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -6884,6 +6884,130 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int* total, bool speed) } } +/* Estimates the size cost of thumb1 instructions. + For now most of the code is copied from thumb1_rtx_costs. We need more + fine grain tuning when we have more related test cases. */ +static inline int +thumb1_size_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer) +{ + enum machine_mode mode = GET_MODE (x); + + switch (code) + { + case ASHIFT: + case ASHIFTRT: + case LSHIFTRT: + case ROTATERT: + case PLUS: + case MINUS: + case COMPARE: + case NEG: + case NOT: + return COSTS_N_INSNS (1); + + case MULT: + if (GET_CODE (XEXP (x, 1)) == CONST_INT) + { + /* Thumb1 mul instruction can't operate on const. We must Load it + into a register first. */ + int const_size = thumb1_size_rtx_costs (XEXP (x, 1), CONST_INT, SET); + return COSTS_N_INSNS (1) + const_size; + } + return COSTS_N_INSNS (1); + + case SET: + return (COSTS_N_INSNS (1) + + 4 * ((GET_CODE (SET_SRC (x)) == MEM) + + GET_CODE (SET_DEST (x)) == MEM)); + + case CONST_INT: + if (outer == SET) + { + if ((unsigned HOST_WIDE_INT) INTVAL (x) < 256) + return 0; + if (thumb_shiftable_const (INTVAL (x))) + return COSTS_N_INSNS (2); + return COSTS_N_INSNS (3); + } + else if ((outer == PLUS || outer == COMPARE) + && INTVAL (x) < 256 && INTVAL (x) > -256) + return 0; + else if ((outer == IOR || outer == XOR || outer == AND) + && INTVAL (x) < 256 && INTVAL (x) >= -256) + return COSTS_N_INSNS (1); + else if (outer == AND) + { + int i; + /* This duplicates the tests in the andsi3 expander. */ + for (i = 9; i <= 31; i++) + if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (x) + || (((HOST_WIDE_INT) 1) << i) - 1 == ~INTVAL (x)) + return COSTS_N_INSNS (2); + } + else if (outer == ASHIFT || outer == ASHIFTRT + || outer == LSHIFTRT) + return 0; + return COSTS_N_INSNS (2); + + case CONST: + case CONST_DOUBLE: + case LABEL_REF: + case SYMBOL_REF: + return COSTS_N_INSNS (3); + + case UDIV: + case UMOD: + case DIV: + case MOD: + return 100; + + case TRUNCATE: + return 99; + + case AND: + case XOR: + case IOR: + /* XXX guess. */ + return 8; + + case MEM: + /* XXX another guess. */ + /* Memory costs quite a lot for the first word, but subsequent words + load at the equivalent of a single insn each. */ + return (10 + 4 * ((GET_MODE_SIZE (mode) - 1) / UNITS_PER_WORD) + + ((GET_CODE (x) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (x)) + ? 4 : 0)); + + case IF_THEN_ELSE: + /* XXX a guess. */ + if (GET_CODE (XEXP (x, 1)) == PC || GET_CODE (XEXP (x, 2)) == PC) + return 14; + return 2; + + case ZERO_EXTEND: + /* XXX still guessing. */ + switch (GET_MODE (XEXP (x, 0))) + { + case QImode: + return (1 + (mode == DImode ? 4 : 0) + + (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0)); + + case HImode: + return (4 + (mode == DImode ? 4 : 0) + + (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0)); + + case SImode: + return (1 + (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0)); + + default: + return 99; + } + + default: + return 99; + } +} + /* RTX costs when optimizing for size. */ static bool arm_size_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code, @@ -6892,8 +7016,7 @@ arm_size_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code, enum machine_mode mode = GET_MODE (x); if (TARGET_THUMB1) { - /* XXX TBD. For now, use the standard costs. */ - *total = thumb1_rtx_costs (x, code, outer_code); + *total = thumb1_size_rtx_costs (x, code, outer_code); return true; } -- 2.30.2