From ca158af378fe7727ec100bd03b3a07a540f25d9b Mon Sep 17 00:00:00 2001 From: Segher Boessenkool Date: Wed, 11 Oct 2017 02:11:23 +0200 Subject: [PATCH] rs6000: insn_cost This adds an implementation of the insn_cost hook to rs6000. This implementations is very minimal (so far). It is mostly based on how many machine instructions are generated by an RTL insn, and it also looks at the instruction type. Floating point insns are costed as if all machine instructions it generates are floating point; the other insns are treated as if all but one are integer insns (and one is the specified type). Load instructions are treated as costing twice as much, and load locked and sync insns as three times as much (just like the original costs), and integer div and mul are handled as well. Each define_insn (etc.) can set a "cost" attribute to override this general cost. With optimization for size, the cost is set equal to the value of the "length" attribute. With this, the majority of cost differences between old and new are where the old was wrong. Also, benchmarks show a slight win (if anything). Some refinements are obviously needed. * config/rs6000/rs6000.c (TARGET_INSN_COST): New. (rs6000_insn_cost): New function. * config/rs6000/rs6000.md (cost): New attribute. From-SVN: r253624 --- gcc/ChangeLog | 6 +++ gcc/config/rs6000/rs6000.c | 84 +++++++++++++++++++++++++++++++++++++ gcc/config/rs6000/rs6000.md | 4 ++ 3 files changed, 94 insertions(+) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d2d89e32999..e42eb5062ea 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2017-10-10 Segher Boessenkool + + * config/rs6000/rs6000.c (TARGET_INSN_COST): New. + (rs6000_insn_cost): New function. + * config/rs6000/rs6000.md (cost): New attribute. + 2017-10-10 Jakub Jelinek H.J. Lu diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 12ddd970be5..8b014e75fae 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -1728,6 +1728,8 @@ static const struct attribute_spec rs6000_attribute_table[] = #define TARGET_RTX_COSTS rs6000_rtx_costs #undef TARGET_ADDRESS_COST #define TARGET_ADDRESS_COST hook_int_rtx_mode_as_bool_0 +#undef TARGET_INSN_COST +#define TARGET_INSN_COST rs6000_insn_cost #undef TARGET_INIT_DWARF_REG_SIZES_EXTRA #define TARGET_INIT_DWARF_REG_SIZES_EXTRA rs6000_init_dwarf_reg_sizes_extra @@ -34936,6 +34938,88 @@ rs6000_debug_rtx_costs (rtx x, machine_mode mode, int outer_code, return ret; } +static int +rs6000_insn_cost (rtx_insn *insn, bool speed) +{ + if (recog_memoized (insn) < 0) + return 0; + + if (!speed) + return get_attr_length (insn); + + int cost = get_attr_cost (insn); + if (cost > 0) + return cost; + + int n = get_attr_length (insn) / 4; + enum attr_type type = get_attr_type (insn); + + switch (type) + { + case TYPE_LOAD: + case TYPE_FPLOAD: + case TYPE_VECLOAD: + cost = COSTS_N_INSNS (n + 1); + break; + + case TYPE_MUL: + switch (get_attr_size (insn)) + { + case SIZE_8: + cost = COSTS_N_INSNS (n - 1) + rs6000_cost->mulsi_const9; + break; + case SIZE_16: + cost = COSTS_N_INSNS (n - 1) + rs6000_cost->mulsi_const; + break; + case SIZE_32: + cost = COSTS_N_INSNS (n - 1) + rs6000_cost->mulsi; + break; + case SIZE_64: + cost = COSTS_N_INSNS (n - 1) + rs6000_cost->muldi; + break; + default: + gcc_unreachable (); + } + break; + case TYPE_DIV: + switch (get_attr_size (insn)) + { + case SIZE_32: + cost = COSTS_N_INSNS (n - 1) + rs6000_cost->divsi; + break; + case SIZE_64: + cost = COSTS_N_INSNS (n - 1) + rs6000_cost->divdi; + break; + default: + gcc_unreachable (); + } + break; + + case TYPE_FP: + cost = n * rs6000_cost->fp; + break; + case TYPE_DMUL: + cost = n * rs6000_cost->dmul; + break; + case TYPE_SDIV: + cost = n * rs6000_cost->sdiv; + break; + case TYPE_DDIV: + cost = n * rs6000_cost->ddiv; + break; + + case TYPE_SYNC: + case TYPE_LOAD_L: + cost = COSTS_N_INSNS (n + 2); + break; + + default: + cost = COSTS_N_INSNS (n); + } + + return cost; +} + /* Debug form of ADDRESS_COST that is selected if -mdebug=cost. */ static int diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 97a75a2291c..6efc1134fc4 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -193,6 +193,10 @@ ;; This is used for insert, mul and others as necessary. (define_attr "size" "8,16,32,64,128" (const_string "32")) +;; What is the insn_cost for this insn? The target hook can still override +;; this. For optimizing for size the "length" attribute is used instead. +(define_attr "cost" "" (const_int 0)) + ;; Is this instruction record form ("dot", signed compare to 0, writing CR0)? ;; This is used for add, logical, shift, exts, mul. (define_attr "dot" "no,yes" (const_string "no")) -- 2.30.2