diff options
author | James Greenhalgh <james.greenhalgh@arm.com> | 2014-05-16 08:47:59 +0000 |
---|---|---|
committer | James Greenhalgh <jgreenhalgh@gcc.gnu.org> | 2014-05-16 08:47:59 +0000 |
commit | 9dfc162c47a8485b032af6af78e3790940a9d210 (patch) | |
tree | 64c86e2439dc7e841cbd6bc1e4bc11b7604381e5 /gcc | |
parent | 0ee859b53ba2af19f58f9e58ab38da1a8a16b5d6 (diff) | |
download | gcc-9dfc162c47a8485b032af6af78e3790940a9d210.zip gcc-9dfc162c47a8485b032af6af78e3790940a9d210.tar.gz gcc-9dfc162c47a8485b032af6af78e3790940a9d210.tar.bz2 |
[AArch64 costs 4/18] Better estimate cost of building a constant
gcc/
* config/aarch64/aarch64.c (aarch64_build_constant): Conditionally
emit instructions, return number of instructions which would
be emitted.
(aarch64_add_constant): Update call to aarch64_build_constant.
(aarch64_output_mi_thunk): Likewise.
(aarch64_rtx_costs): Estimate cost of a CONST_INT, cost
a CONST_DOUBLE.
Co-Authored-By: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
From-SVN: r210496
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/config/aarch64/aarch64.c | 96 |
2 files changed, 95 insertions, 12 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index c624538..41a39a2 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,4 +1,15 @@ 2014-05-16 James Greenhalgh <james.greenhalgh@arm.com> + Philipp Tomsich <philipp.tomsich@theobroma-systems.com> + + * config/aarch64/aarch64.c (aarch64_build_constant): Conditionally + emit instructions, return number of instructions which would + be emitted. + (aarch64_add_constant): Update call to aarch64_build_constant. + (aarch64_output_mi_thunk): Likewise. + (aarch64_rtx_costs): Estimate cost of a CONST_INT, cost + a CONST_DOUBLE. + +2014-05-16 James Greenhalgh <james.greenhalgh@arm.com> * config/aarch64/aarch64.c (aarch64_rtx_costs_wrapper): New. (TARGET_RTX_COSTS): Call it. diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index da693b4..b3e6f5c 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -2547,12 +2547,22 @@ aarch64_final_eh_return_addr (void) - 2 * UNITS_PER_WORD)); } -/* Output code to build up a constant in a register. */ -static void -aarch64_build_constant (int regnum, HOST_WIDE_INT val) +/* Possibly output code to build up a constant in a register. For + the benefit of the costs infrastructure, returns the number of + instructions which would be emitted. GENERATE inhibits or + enables code generation. */ + +static int +aarch64_build_constant (int regnum, HOST_WIDE_INT val, bool generate) { + int insns = 0; + if (aarch64_bitmask_imm (val, DImode)) - emit_move_insn (gen_rtx_REG (Pmode, regnum), GEN_INT (val)); + { + if (generate) + emit_move_insn (gen_rtx_REG (Pmode, regnum), GEN_INT (val)); + insns = 1; + } else { int i; @@ -2583,15 +2593,19 @@ aarch64_build_constant (int regnum, HOST_WIDE_INT val) the same. */ if (ncount < zcount) { - emit_move_insn (gen_rtx_REG (Pmode, regnum), - GEN_INT (val | ~(HOST_WIDE_INT) 0xffff)); + if (generate) + emit_move_insn (gen_rtx_REG (Pmode, regnum), + GEN_INT (val | ~(HOST_WIDE_INT) 0xffff)); tval = 0xffff; + insns++; } else { - emit_move_insn (gen_rtx_REG (Pmode, regnum), - GEN_INT (val & 0xffff)); + if (generate) + emit_move_insn (gen_rtx_REG (Pmode, regnum), + GEN_INT (val & 0xffff)); tval = 0; + insns++; } val >>= 16; @@ -2599,11 +2613,17 @@ aarch64_build_constant (int regnum, HOST_WIDE_INT val) for (i = 16; i < 64; i += 16) { if ((val & 0xffff) != tval) - emit_insn (gen_insv_immdi (gen_rtx_REG (Pmode, regnum), - GEN_INT (i), GEN_INT (val & 0xffff))); + { + if (generate) + emit_insn (gen_insv_immdi (gen_rtx_REG (Pmode, regnum), + GEN_INT (i), + GEN_INT (val & 0xffff))); + insns++; + } val >>= 16; } } + return insns; } static void @@ -2618,7 +2638,7 @@ aarch64_add_constant (int regnum, int scratchreg, HOST_WIDE_INT delta) if (mdelta >= 4096 * 4096) { - aarch64_build_constant (scratchreg, delta); + (void) aarch64_build_constant (scratchreg, delta, true); emit_insn (gen_add3_insn (this_rtx, this_rtx, scratch_rtx)); } else if (mdelta > 0) @@ -2692,7 +2712,7 @@ aarch64_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED, addr = plus_constant (Pmode, temp0, vcall_offset); else { - aarch64_build_constant (IP1_REGNUM, vcall_offset); + (void) aarch64_build_constant (IP1_REGNUM, vcall_offset, true); addr = gen_rtx_PLUS (Pmode, temp0, temp1); } @@ -4705,6 +4725,7 @@ aarch64_rtx_costs (rtx x, int code, int outer ATTRIBUTE_UNUSED, rtx op0, op1; const struct cpu_cost_table *extra_cost = aarch64_tune_params->insn_extra_cost; + enum machine_mode mode = GET_MODE (x); switch (code) { @@ -4751,6 +4772,57 @@ aarch64_rtx_costs (rtx x, int code, int outer ATTRIBUTE_UNUSED, } return false; + case CONST_INT: + /* If an instruction can incorporate a constant within the + instruction, the instruction's expression avoids calling + rtx_cost() on the constant. If rtx_cost() is called on a + constant, then it is usually because the constant must be + moved into a register by one or more instructions. + + The exception is constant 0, which can be expressed + as XZR/WZR and is therefore free. The exception to this is + if we have (set (reg) (const0_rtx)) in which case we must cost + the move. However, we can catch that when we cost the SET, so + we don't need to consider that here. */ + if (x == const0_rtx) + *cost = 0; + else + { + /* To an approximation, building any other constant is + proportionally expensive to the number of instructions + required to build that constant. This is true whether we + are compiling for SPEED or otherwise. */ + *cost = COSTS_N_INSNS (aarch64_build_constant (0, + INTVAL (x), + false)); + } + return true; + + case CONST_DOUBLE: + if (speed) + { + /* mov[df,sf]_aarch64. */ + if (aarch64_float_const_representable_p (x)) + /* FMOV (scalar immediate). */ + *cost += extra_cost->fp[mode == DFmode].fpconst; + else if (!aarch64_float_const_zero_rtx_p (x)) + { + /* This will be a load from memory. */ + if (mode == DFmode) + *cost += extra_cost->ldst.loadd; + else + *cost += extra_cost->ldst.loadf; + } + else + /* Otherwise this is +0.0. We get this using MOVI d0, #0 + or MOV v0.s[0], wzr - neither of which are modeled by the + cost tables. Just use the default cost. */ + { + } + } + + return true; + case MEM: if (speed) *cost += extra_cost->ldst.load; |