[PATCH.v1] ifcvt: Account for parallelism when costing noce sequences

wangjue <[email protected]>
Newsgroups gmane.comp.gcc.patches
Message-ID <[email protected]>
From: juewang <[email protected]>

seq_cost treats every instruction in a replacement sequence as serial.
This can overestimate simple register-only sequences on superscalar
targets and reject profitable if-conversion.

Build dependency levels for simple, single-cycle register operations.
Cost each level using the target issue rate.  Fall back to the serial
cost for unsupported sequences, size optimization, and targets without
an issue rate hook.

gcc/ChangeLog:

	* ifcvt.cc (noce_parallel_cost_node): New.
	(noce_parallel_seq_cost): New.
	(default_noce_conversion_profitable_p): Use it.
---
 gcc/ifcvt.cc | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 83 insertions(+), 1 deletion(-)

diff --git a/gcc/ifcvt.cc b/gcc/ifcvt.cc
index 5ea25f8fbe7..146c738d32f 100644
--- a/gcc/ifcvt.cc
+++ b/gcc/ifcvt.cc
@@ -803,6 +803,88 @@ noce_reversed_cond_code (struct noce_if_info *if_info)
   return reversed_comparison_code (if_info->cond, if_info->jump);
 }
 
+/* A destination and its dependency level in a noce sequence.  */
+
+struct noce_parallel_cost_node
+{
+  rtx dest;
+  unsigned int level;
+};
+
+/* Estimate the cost of independent, single-cycle register operations in
+   SEQ using the target issue rate.
+
+   In an instrumented build of all SPEC CPU2017 Integer rate benchmarks
+   for RISC-V, the analysis handled 16,947 of 30,120 candidates (56.26%).
+   It reduced the cost for 15,024 of the handled candidates (88.65%).
+   The parallel-to-serial cost ratios for the handled candidates were:
+
+     0.8 < ratio <= 1.0  11.54 percent
+     0.6 < ratio <= 0.8  47.31 percent
+     0.4 < ratio <= 0.6  40.24 percent
+     0.2 < ratio <= 0.4   0.91 percent
+     0.0 < ratio <= 0.2   0.00 percent.  */
+
+static unsigned int
+noce_parallel_seq_cost (rtx_insn *seq, bool speed_p)
+{
+  unsigned int serial_cost = seq_cost (seq, speed_p);
+
+  if (!speed_p)
+    return serial_cost;
+
+  if (!targetm.sched.issue_rate)
+    return serial_cost;
+
+  unsigned int issue_rate = MAX (targetm.sched.issue_rate (), 1);
+  auto_vec<noce_parallel_cost_node> nodes;
+  auto_vec<unsigned int> insns_per_level;
+
+  /* Build register dependency levels.  Place an instruction after its
+     deepest producer; independent instructions remain at the same level.  */
+
+  for (rtx_insn *insn = seq; insn; insn = NEXT_INSN (insn))
+    {
+      if (!NONDEBUG_INSN_P (insn))
+	continue;
+
+      rtx set = single_set (insn);
+      if (!set)
+	return serial_cost;
+
+      rtx dest = SET_DEST (set);
+      rtx src = SET_SRC (set);
+
+      if (!REG_P (dest)
+	  || contains_mem_rtx_p (src)
+	  || side_effects_p (src)
+	  || may_trap_p (src)
+	  || set_rtx_cost (set, speed_p) != COSTS_N_INSNS (1))
+	return serial_cost;
+
+      unsigned int level = 0;
+      for (unsigned int i = 0; i < nodes.length (); ++i)
+	if (reg_overlap_mentioned_p (nodes[i].dest, src))
+	  level = MAX (level, nodes[i].level + 1);
+
+      if (insns_per_level.length () <= level)
+	insns_per_level.safe_grow_cleared (level + 1, true);
+      ++insns_per_level[level];
+
+      noce_parallel_cost_node node = { dest, level };
+      nodes.safe_push (node);
+    }
+
+  /* Sum the issue cycles needed for each dependency level.  */
+
+  unsigned int parallel_cost = 0;
+  for (unsigned int i = 0; i < insns_per_level.length (); ++i)
+    parallel_cost
+      += COSTS_N_INSNS (CEIL (insns_per_level[i], issue_rate));
+
+  return MIN (serial_cost, parallel_cost);
+}
+
 /* Return true if SEQ is a good candidate as a replacement for the
    if-convertible sequence described in IF_INFO.
    This is the default implementation that targets can override
@@ -815,7 +897,7 @@ default_noce_conversion_profitable_p (rtx_insn *seq,
   bool speed_p = if_info->speed_p;
 
   /* Cost up the new sequence.  */
-  unsigned int cost = seq_cost (seq, speed_p);
+  unsigned int cost = noce_parallel_seq_cost (seq, speed_p);
 
   if (cost <= if_info->original_cost)
     return true;
-- 
2.34.1
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.