Hi,
This patch restricts predcom pass using register pressure information.
In case of high register pressure, we now prune additional chains as well
as disable unrolling in predcom.  In generally, I think this patch set is
useful.

Bootstrap and test on x86_64 ongoing.  Any comments?

Thanks,
bin
2018-04-27  Bin Cheng  <bin.ch...@arm.com>

        * tree-predcom.c (stor-layout.h, tree-ssa-live.h): Include.
        (REG_RELAX_RATIO, prune_chains): New.
        (tree_predictive_commoning_loop): Compute reg pressure using class
        region.  Prune chains based on reg pressure.  Force to not unroll
        if reg pressure is high.
From 1b488665f8fea619c4ce35f71650c342df69de2f Mon Sep 17 00:00:00 2001
From: Bin Cheng <binch...@e108451-lin.cambridge.arm.com>
Date: Wed, 25 Apr 2018 16:30:41 +0100
Subject: [PATCH 6/6] pcom-reg-pressure-20180423

---
 gcc/tree-predcom.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 74 insertions(+)

diff --git a/gcc/tree-predcom.c b/gcc/tree-predcom.c
index aeadbf7..d0c18b3 100644
--- a/gcc/tree-predcom.c
+++ b/gcc/tree-predcom.c
@@ -217,6 +217,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-pass.h"
 #include "ssa.h"
 #include "gimple-pretty-print.h"
+#include "stor-layout.h"
 #include "alias.h"
 #include "fold-const.h"
 #include "cfgloop.h"
@@ -227,6 +228,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-ssa-loop-ivopts.h"
 #include "tree-ssa-loop-manip.h"
 #include "tree-ssa-loop-niter.h"
+#include "tree-ssa-live.h"
 #include "tree-ssa-loop.h"
 #include "tree-into-ssa.h"
 #include "tree-dfa.h"
@@ -242,6 +244,10 @@ along with GCC; see the file COPYING3.  If not see
 
 #define MAX_DISTANCE (target_avail_regs[GENERAL_REGS] < 16 ? 4 : 8)
 
+/* The ratio by which register pressure check is relaxed.  */
+
+#define REG_RELAX_RATIO (2)
+
 /* Data references (or phi nodes that carry data reference values across
    loop iterations).  */
 
@@ -3156,6 +3162,59 @@ insert_init_seqs (struct loop *loop, vec<chain_p> chains)
       }
 }
 
+/* Prune chains causing high register pressure.  */
+
+static void
+prune_chains (vec<chain_p> *chains, unsigned *max_pressure)
+{
+  bool pruned_p = false;
+  machine_mode mode;
+  enum reg_class cl;
+  unsigned i, new_pressure;
+
+  for (i = 0; i < chains->length ();)
+    {
+      chain_p chain = (*chains)[i];
+      /* Always allow combined chain and zero-length chain.  */
+      if (chain->combined || chain->type == CT_COMBINATION
+	  || chain->length == 0 || chain->type == CT_STORE_STORE)
+	{
+	  i++;
+	  continue;
+	}
+
+      gcc_assert (chain->refs.length () > 0);
+      mode = TYPE_MODE (TREE_TYPE (chain->refs[0]->ref->ref));
+      /* Bypass chain that doesn't contribute to any reg_class, although
+	 something could be wrong when mapping type mode to reg_class.  */
+      if (ira_mode_classes[mode] == NO_REGS)
+	{
+	  i++;
+	  continue;
+	}
+
+      cl = ira_pressure_class_translate[ira_mode_classes[mode]];
+      /* Prune chain if it causes higher register pressure than available
+	 registers; otherwise keep the chain and update register pressure
+	 information.  */
+      new_pressure = max_pressure[cl] + chain->length - 1;
+      if (new_pressure <= target_avail_regs[cl] * REG_RELAX_RATIO)
+	{
+	  i++;
+	  max_pressure[cl] = new_pressure;
+	}
+      else
+	{
+	  release_chain (chain);
+	  chains->unordered_remove (i);
+	  pruned_p = true;
+	}
+    }
+
+  if (pruned_p && dump_file && (dump_flags & TDF_DETAILS))
+    fprintf (dump_file, "Prune chain because of high reg pressure\n");
+}
+
 /* Performs predictive commoning for LOOP.  Sets bit 1<<0 of return value
    if LOOP was unrolled; Sets bit 1<<1 of return value if loop closed ssa
    form was corrupted.  */
@@ -3171,6 +3230,9 @@ tree_predictive_commoning_loop (struct loop *loop)
   struct tree_niter_desc desc;
   bool unroll = false, loop_closed_ssa = false;
   edge exit;
+  lr_region *region;
+  unsigned max_pressure[N_REG_CLASSES];
+  bool high_pressure_p;
 
   if (dump_file && (dump_flags & TDF_DETAILS))
     fprintf (dump_file, "Processing loop %d\n",  loop->num);
@@ -3239,6 +3301,11 @@ tree_predictive_commoning_loop (struct loop *loop)
   /* Try to combine the chains that are always worked with together.  */
   try_combine_chains (loop, &chains);
 
+  region = new lr_region (loop);
+  high_pressure_p = region->calculate_pressure (max_pressure);
+  delete region;
+  prune_chains (&chains, max_pressure);
+
   insert_init_seqs (loop, chains);
 
   if (dump_file && (dump_flags & TDF_DETAILS))
@@ -3250,6 +3317,13 @@ tree_predictive_commoning_loop (struct loop *loop)
   /* Determine the unroll factor, and if the loop should be unrolled, ensure
      that its number of iterations is divisible by the factor.  */
   unroll_factor = determine_unroll_factor (chains);
+  /* Force to not unroll if register pressure is high.  */
+  if (high_pressure_p && unroll_factor > 1)
+    {
+      unroll_factor = 1;
+      if (dump_file && (dump_flags & TDF_DETAILS))
+	fprintf (dump_file, "Force to not unroll because of high reg pressure\n");
+    }
   scev_reset ();
   unroll = (unroll_factor > 1
 	    && can_unroll_loop_p (loop, unroll_factor, &desc));
-- 
1.9.1

Reply via email to