rs6000: insn_cost
authorSegher Boessenkool <segher@kernel.crashing.org>
Wed, 11 Oct 2017 00:11:23 +0000 (02:11 +0200)
committerSegher Boessenkool <segher@gcc.gnu.org>
Wed, 11 Oct 2017 00:11:23 +0000 (02:11 +0200)
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
gcc/config/rs6000/rs6000.c
gcc/config/rs6000/rs6000.md

index d2d89e329997be2ab444cec890050704b5bd2427..e42eb5062eae21dbe6db3175d82a7f97194f8d54 100644 (file)
@@ -1,3 +1,9 @@
+2017-10-10  Segher Boessenkool  <segher@kernel.crashing.org>
+
+       * 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  <jakub@redhat.com>
            H.J. Lu  <hongjiu.lu@intel.com>
 
index 12ddd970be52af48633f0fe1218253a35b1ae7ab..8b014e75fae553489bd9d2ce0edf0985e24374a4 100644 (file)
@@ -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
index 97a75a2291ce2ef00ae78f06de3248411b3293f2..6efc1134fc48c73d58a5eea372058e06e1ec5498 100644 (file)
 ;; 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"))