rs6000: insn_cost

Message ID a2f23369b6a05314e62ae93f98b8d8537621f1bd.1507678499.git.segher@kernel.crashing.org
State New
Headers show
Series
  • rs6000: insn_cost
Related show

Commit Message

Segher Boessenkool Oct. 10, 2017, 11:57 p.m.
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.

Tested on powerpc64-linux {-m32,-m64}; committing to trunk.


Segher


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.

---
 gcc/config/rs6000/rs6000.c  | 84 +++++++++++++++++++++++++++++++++++++++++++++
 gcc/config/rs6000/rs6000.md |  4 +++
 2 files changed, 88 insertions(+)

Patch

diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index f98ef93..744533b 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
@@ -34932,6 +34934,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 b10a999..2e1daf4 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -193,6 +193,10 @@  (define_attr "type"
 ;; 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"))