diff options
author | James Greenhalgh <james.greenhalgh@arm.com> | 2014-05-16 08:41:46 +0000 |
---|---|---|
committer | James Greenhalgh <jgreenhalgh@gcc.gnu.org> | 2014-05-16 08:41:46 +0000 |
commit | 677473677aa5d85ea967c998f73fb7f50b9eb379 (patch) | |
tree | 7c872be35c8eaa51a6269b4942c1b7399210b7e0 /gcc/config/aarch64 | |
parent | a764d66099b476db7d59829da1b86fd4a701523f (diff) | |
download | gcc-677473677aa5d85ea967c998f73fb7f50b9eb379.zip gcc-677473677aa5d85ea967c998f73fb7f50b9eb379.tar.gz gcc-677473677aa5d85ea967c998f73fb7f50b9eb379.tar.bz2 |
[AArch64 costs 1/18] Refactor aarch64_address_costs.
gcc/
* config/aarch64/aarch64-protos.h (scale_addr_mode_cost): New.
(cpu_addrcost_table): Use it.
* config/aarch64/aarch64.c (generic_addrcost_table): Initialize it.
(aarch64_address_cost): Rewrite using aarch64_classify_address,
move it.
From-SVN: r210493
Diffstat (limited to 'gcc/config/aarch64')
-rw-r--r-- | gcc/config/aarch64/aarch64-protos.h | 13 | ||||
-rw-r--r-- | gcc/config/aarch64/aarch64.c | 135 |
2 files changed, 117 insertions, 31 deletions
diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h index 7cf7d9f..a05605b 100644 --- a/gcc/config/aarch64/aarch64-protos.h +++ b/gcc/config/aarch64/aarch64-protos.h @@ -108,9 +108,22 @@ enum aarch64_symbol_type cost models and vectors for address cost calculations, register move costs and memory move costs. */ +/* Scaled addressing modes can vary cost depending on the mode of the + value to be loaded/stored. QImode values cannot use scaled + addressing modes. */ + +struct scale_addr_mode_cost +{ + const int hi; + const int si; + const int di; + const int ti; +}; + /* Additional cost for addresses. */ struct cpu_addrcost_table { + const struct scale_addr_mode_cost addr_scale_costs; const int pre_modify; const int post_modify; const int register_offset; diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index fabd6a9..a596f0d 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -171,6 +171,15 @@ __extension__ #endif static const struct cpu_addrcost_table generic_addrcost_table = { +#if HAVE_DESIGNATED_INITIALIZERS + .addr_scale_costs = +#endif + { + NAMED_PARAM (qi, 0), + NAMED_PARAM (hi, 0), + NAMED_PARAM (si, 0), + NAMED_PARAM (ti, 0), + }, NAMED_PARAM (pre_modify, 0), NAMED_PARAM (post_modify, 0), NAMED_PARAM (register_offset, 0), @@ -4550,6 +4559,101 @@ aarch64_strip_shift_or_extend (rtx x) return aarch64_strip_shift (x); } +static int +aarch64_address_cost (rtx x, + enum machine_mode mode, + addr_space_t as ATTRIBUTE_UNUSED, + bool speed) +{ + enum rtx_code c = GET_CODE (x); + const struct cpu_addrcost_table *addr_cost = aarch64_tune_params->addr_cost; + struct aarch64_address_info info; + int cost = 0; + info.shift = 0; + + if (!aarch64_classify_address (&info, x, mode, c, false)) + { + if (GET_CODE (x) == CONST || GET_CODE (x) == SYMBOL_REF) + { + /* This is a CONST or SYMBOL ref which will be split + in a different way depending on the code model in use. + Cost it through the generic infrastructure. */ + int cost_symbol_ref = rtx_cost (x, MEM, 1, speed); + /* Divide through by the cost of one instruction to + bring it to the same units as the address costs. */ + cost_symbol_ref /= COSTS_N_INSNS (1); + /* The cost is then the cost of preparing the address, + followed by an immediate (possibly 0) offset. */ + return cost_symbol_ref + addr_cost->imm_offset; + } + else + { + /* This is most likely a jump table from a case + statement. */ + return addr_cost->register_offset; + } + } + + switch (info.type) + { + case ADDRESS_LO_SUM: + case ADDRESS_SYMBOLIC: + case ADDRESS_REG_IMM: + cost += addr_cost->imm_offset; + break; + + case ADDRESS_REG_WB: + if (c == PRE_INC || c == PRE_DEC || c == PRE_MODIFY) + cost += addr_cost->pre_modify; + else if (c == POST_INC || c == POST_DEC || c == POST_MODIFY) + cost += addr_cost->post_modify; + else + gcc_unreachable (); + + break; + + case ADDRESS_REG_REG: + cost += addr_cost->register_offset; + break; + + case ADDRESS_REG_UXTW: + case ADDRESS_REG_SXTW: + cost += addr_cost->register_extend; + break; + + default: + gcc_unreachable (); + } + + + if (info.shift > 0) + { + /* For the sake of calculating the cost of the shifted register + component, we can treat same sized modes in the same way. */ + switch (GET_MODE_BITSIZE (mode)) + { + case 16: + cost += addr_cost->addr_scale_costs.hi; + break; + + case 32: + cost += addr_cost->addr_scale_costs.si; + break; + + case 64: + cost += addr_cost->addr_scale_costs.di; + break; + + /* We can't tell, or this is a 128-bit vector. */ + default: + cost += addr_cost->addr_scale_costs.ti; + break; + } + } + + return cost; +} + /* Calculate the cost of calculating X, storing it in *COST. Result is true if the total cost of the operation has now been calculated. */ static bool @@ -4887,37 +4991,6 @@ aarch64_rtx_costs (rtx x, int code, int outer ATTRIBUTE_UNUSED, } static int -aarch64_address_cost (rtx x ATTRIBUTE_UNUSED, - enum machine_mode mode ATTRIBUTE_UNUSED, - addr_space_t as ATTRIBUTE_UNUSED, bool speed ATTRIBUTE_UNUSED) -{ - enum rtx_code c = GET_CODE (x); - const struct cpu_addrcost_table *addr_cost = aarch64_tune_params->addr_cost; - - if (c == PRE_INC || c == PRE_DEC || c == PRE_MODIFY) - return addr_cost->pre_modify; - - if (c == POST_INC || c == POST_DEC || c == POST_MODIFY) - return addr_cost->post_modify; - - if (c == PLUS) - { - if (GET_CODE (XEXP (x, 1)) == CONST_INT) - return addr_cost->imm_offset; - else if (GET_CODE (XEXP (x, 0)) == MULT - || GET_CODE (XEXP (x, 0)) == ZERO_EXTEND - || GET_CODE (XEXP (x, 0)) == SIGN_EXTEND) - return addr_cost->register_extend; - - return addr_cost->register_offset; - } - else if (c == MEM || c == LABEL_REF || c == SYMBOL_REF) - return addr_cost->imm_offset; - - return 0; -} - -static int aarch64_register_move_cost (enum machine_mode mode, reg_class_t from_i, reg_class_t to_i) { |