Hi,

the current cost computations in rtlanal.c and maybe other places
suffer from the fact that they are hiding parts of the expressions
from the back-end, like SET_DESTs of single_set or the anatomy of
PARALELLs.

Would it be in order to have a hook like the one attached?

I am aware of that, in an ideal world, there wouldn't be more
than one hook to get rtx costs.  But well...

Whilst rtx_costs does in the majority of cases, there are cases
where hiding information leads to performance degradation,
for example when insn combine cooks up a set zero_extract.
combine.c does actually the right thing as it uses insn_rtx_costs,
but insn_rtx_cost is already a lie because it only uses SET_SRC
and digs into PARALELL without exposing the whole story.

The patch just uses a new targetm.insn_cost hook.  If the
back-end doesn't come up with something useful, the classic
functions with rtx_costs for sub-rtxes are called.

The purpose is to allow a friendly transition and not no
raise any performance degradations which would be very likely
if we just called rtx_costs with outer_code = INSN.

If a back-end finds it useful to implement this hook and need
the whole story, they can do so.  Otherwise, or if it is too
lazy to analyse a specific rtx, they can switch to the old
infrastructure.

Returning a magic value for "unknown" is just an implementation
detail; it could just as well be some bool* that would be set
to true or false depending on whether or not the computation
returned something useful or not.

The patch only touches seq_cost insn_rtx_cost of rtlanal.c.

Would something like this be in order, or is a new hook just
a complete no-go?

Index: coretypes.h
===================================================================
--- coretypes.h	(revision 250090)
+++ coretypes.h	(working copy)
@@ -253,6 +253,10 @@ construct that is easy to avoid even whe
   WARN_STRICT_OVERFLOW_MAGNITUDE = 5
 };
 
+/* A magic value to be returned by TARGET_INSN_COSTS to indicate that
+   the costs are not known or too complicated to work out there.  */
+#define INSN_COSTS_UNKNOWN (-1234567)
+
 /* The type of an alias set.  Code currently assumes that variables of
    this type can take the values 0 (the alias set which aliases
    everything) and -1 (sometimes indicating that the alias set is
Index: doc/tm.texi
===================================================================
--- doc/tm.texi	(revision 250123)
+++ doc/tm.texi	(working copy)
@@ -6564,6 +6564,39 @@ optimizers should use optab @code{rintdf
 The default hook returns true for all inputs.
 @end deftypefn
 
+@deftypefn {Target Hook} int TARGET_INSN_COSTS (const rtx_insn *@var{insn}, rtx @var{pattern}, bool @var{speed})
+This target hook describes the relative costs of an insn.
+
+@var{insn} might be NULL or an @code{INSN_P}.
+@var{pattern} is the pattern of @var{insn} or an rtx that is supposed
+to be used as the pattern of an insn the remainder of the compilation.
+
+In implementing this hook, you can use the construct
+@code{COSTS_N_INSNS (@var{n})} to specify a cost equal to @var{n}
+instructions.
+When optimizing for execution speed, i.e.@: when @var{speed} is
+true, this target hook should be used to estimate the relative
+execution cost of the pattern, and the size cost of the pattern if
+@var{speed} is false.
+
+Use this pattern if a @code{SET_DEST} is needed to calculate the correct
+costs or when you want to see the whole of a @code{PARALLEL} and not only
+parts of it. Notice that for a @code{single_set} you might see a
+@code{PARALLEL} @var{pattern} that contains a @code{SET} together with
+@code{COBBER}s.
+
+If the pattern is too complicated to be evaluated in this hook, return
+@code{INSN_COSTS_UNKNOWN} which directs the middle-end to use other
+approaches to get the respective costs like calling
+@code{TARGET_RTX_COSTS} for sub-rtxes of @var{pattern}.
+
+Don't implement this hook if it would always return
+@code{INSN_COSTS_UNKNOWN}.
+
+Don't use @code{INSN_COSTS_UNKNOWN} except as a return value for this hook.
+Do @emph{not use} that value as a return value for @code{TARGET_RTX_COSTS}!
+@end deftypefn
+
 @deftypefn {Target Hook} bool TARGET_RTX_COSTS (rtx @var{x}, machine_mode @var{mode}, int @var{outer_code}, int @var{opno}, int *@var{total}, bool @var{speed})
 This target hook describes the relative costs of RTL expressions.
 
Index: doc/tm.texi.in
===================================================================
--- doc/tm.texi.in	(revision 250123)
+++ doc/tm.texi.in	(working copy)
@@ -4790,6 +4790,8 @@ @samp{fold_range_test ()} is optimal.  T
 
 @hook TARGET_OPTAB_SUPPORTED_P
 
+@hook TARGET_INSN_COSTS
+
 @hook TARGET_RTX_COSTS
 
 @hook TARGET_ADDRESS_COST
Index: rtlanal.c
===================================================================
--- rtlanal.c	(revision 250090)
+++ rtlanal.c	(working copy)
@@ -5263,6 +5263,10 @@ insn_rtx_cost (rtx pat, bool speed)
   int i, cost;
   rtx set;
 
+  int icost = targetm.insn_costs (NULL, pat, speed);
+  if (icost != INSN_COSTS_UNKNOWN)
+    return icost;
+
   /* Extract the single set rtx from the instruction pattern.  We
      can't use single_set since we only have the pattern.  We also
      consider PARALLELs of a normal set and a single comparison.  In
@@ -5318,6 +5322,15 @@ seq_cost (const rtx_insn *seq, bool spee
 
   for (; seq; seq = NEXT_INSN (seq))
     {
+      if (INSN_P (seq))
+	{
+	  int icost = targetm.insn_costs (seq, PATTERN (seq), speed);
+	  if (icost != INSN_COSTS_UNKNOWN)
+	    {
+	      cost += icost;
+	      continue;
+	    }
+	}
       set = single_set (seq);
       if (set)
         cost += set_rtx_cost (set, speed);
Index: target.def
===================================================================
--- target.def	(revision 250090)
+++ target.def	(working copy)
@@ -3558,6 +3558,41 @@ DEFHOOKPOD
  appropriately.",
  unsigned int, INVALID_REGNUM)
 
+DEFHOOK
+(insn_costs,
+"This target hook describes the relative costs of an insn.\n\
+\n\
+@var{insn} might be NULL or an @code{INSN_P}.\n\
+@var{pattern} is the pattern of @var{insn} or an rtx that is supposed\n\
+to be used as the pattern of an insn the remainder of the compilation.\n\
+\n\
+In implementing this hook, you can use the construct\n\
+@code{COSTS_N_INSNS (@var{n})} to specify a cost equal to @var{n}\n\
+instructions.\n\
+When optimizing for execution speed, i.e.@: when @var{speed} is\n\
+true, this target hook should be used to estimate the relative\n\
+execution cost of the pattern, and the size cost of the pattern if\n\
+@var{speed} is false.\n\
+\n\
+Use this pattern if a @code{SET_DEST} is needed to calculate the correct\n\
+costs or when you want to see the whole of a @code{PARALLEL} and not only\n\
+parts of it. Notice that for a @code{single_set} you might see a\n\
+@code{PARALLEL} @var{pattern} that contains a @code{SET} together with\n\
+@code{COBBER}s.\n\
+\n\
+If the pattern is too complicated to be evaluated in this hook, return\n\
+@code{INSN_COSTS_UNKNOWN} which directs the middle-end to use other\n\
+approaches to get the respective costs like calling\n\
+@code{TARGET_RTX_COSTS} for sub-rtxes of @var{pattern}.\n\
+\n\
+Don't implement this hook if it would always return\n\
+@code{INSN_COSTS_UNKNOWN}.\n\
+\n\
+Don't use @code{INSN_COSTS_UNKNOWN} except as a return value for this hook.\n\
+Do @emph{not use} that value as a return value for @code{TARGET_RTX_COSTS}!",
+ int, (const rtx_insn *insn, rtx pattern, bool speed),
+ default_insn_costs)
+
 /* Compute a (partial) cost for rtx X.  Return true if the complete
    cost has been computed, and false if subexpressions should be
    scanned.  In either case, *TOTAL contains the cost result.  */
Index: targhooks.c
===================================================================
--- targhooks.c	(revision 250090)
+++ targhooks.c	(working copy)
@@ -2108,4 +2108,10 @@ default_excess_precision (enum excess_pr
   return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT;
 }
 
+int
+default_insn_costs (const rtx_insn*, rtx, bool)
+{
+  return INSN_COSTS_UNKNOWN;
+}
+
 #include "gt-targhooks.h"
Index: targhooks.h
===================================================================
--- targhooks.h	(revision 250090)
+++ targhooks.h	(working copy)
@@ -264,4 +264,6 @@ extern unsigned int default_min_arithmet
 extern enum flt_eval_method
 default_excess_precision (enum excess_precision_type ATTRIBUTE_UNUSED);
 
+extern int default_insn_costs (const rtx_insn*, rtx, bool);
+
 #endif /* GCC_TARGHOOKS_H */

Reply via email to