[gcc(refs/users/marxin/heads/if-to-switch-v4)] Allow more transforms.

Martin Liska marxin@gcc.gnu.org
Tue Oct 13 13:13:49 GMT 2020


https://gcc.gnu.org/g:b064cbf06fa6aa4c59debe93686405058e59d3e9

commit b064cbf06fa6aa4c59debe93686405058e59d3e9
Author: Martin Liska <mliska@suse.cz>
Date:   Tue Oct 13 15:11:16 2020 +0200

    Allow more transforms.

Diff:
---
 gcc/gimple-if-to-switch.cc   | 78 ++++++++++++++++----------------------------
 gcc/tree-switch-conversion.h | 11 +++++--
 2 files changed, 37 insertions(+), 52 deletions(-)

diff --git a/gcc/gimple-if-to-switch.cc b/gcc/gimple-if-to-switch.cc
index 2a25650c3dc..ba78a2c7233 100644
--- a/gcc/gimple-if-to-switch.cc
+++ b/gcc/gimple-if-to-switch.cc
@@ -100,8 +100,7 @@ condition_info::record_phi_mapping (edge e, mapping_vec *vec)
 struct if_chain
 {
   /* Default constructor.  */
-  if_chain():
-    m_first_condition (NULL), m_index (NULL_TREE), m_entries ()
+  if_chain(): m_entries ()
   {
     m_entries.create (2);
   }
@@ -112,9 +111,6 @@ struct if_chain
     m_entries.release ();
   }
 
-  /* Set index and check that it is not a different one.  */
-  bool set_and_check_index (tree index);
-
   /* Verify that all case ranges do not overlap.  */
   bool check_non_overlapping_cases ();
 
@@ -122,26 +118,10 @@ struct if_chain
      a bit test (at least partially).  */
   bool is_beneficial ();
 
-  /* First condition of the chain.  */
-  gcond *m_first_condition;
-  /* Switch index.  */
-  tree m_index;
   /* If chain entries.  */
   vec<condition_info *> m_entries;
 };
 
-bool
-if_chain::set_and_check_index (tree index)
-{
-  if (TREE_CODE (index) != SSA_NAME || !INTEGRAL_TYPE_P (TREE_TYPE (index)))
-    return false;
-
-  if (m_index == NULL)
-    m_index = index;
-
-  return index == m_index;
-}
-
 /* Compare two case ranges by minimum value.  */
 
 static int
@@ -215,10 +195,11 @@ if_chain::is_beneficial ()
       for (unsigned j = 0; j < info->m_ranges.length (); j++)
 	{
 	  range_entry *range = &info->m_ranges[j];
+	  basic_block bb = info->m_true_edge->dest;
+	  bool has_forwarder = !info->m_true_edge_phi_mapping.is_empty ();
 	  clusters.safe_push (new simple_cluster (range->low, range->high,
-						  NULL_TREE,
-						  info->m_true_edge->dest,
-						  prob));
+						  NULL_TREE, bb, prob,
+						  has_forwarder));
 	}
     }
 
@@ -234,7 +215,9 @@ if_chain::is_beneficial ()
       simple_cluster *right = static_cast<simple_cluster *> (clusters[i]);
       tree type = TREE_TYPE (left->get_low ());
       tree pos_one = build_int_cst (type, 1);
-      if (left->m_case_bb == right->m_case_bb)
+      if (!left->m_has_forward_bb
+	  && !right->m_has_forward_bb
+	  && left->m_case_bb == right->m_case_bb)
 	{
 	  tree next = int_const_binop (PLUS_EXPR, left->get_high (), pos_one);
 	  if (tree_int_cst_equal (next, right->get_low ()))
@@ -472,25 +455,13 @@ public:
 unsigned int
 pass_if_to_switch::execute (function *fun)
 {
+  auto_vec<if_chain *> all_candidates;
   hash_map<basic_block, condition_info> conditions_in_bbs;
 
   basic_block bb;
   FOR_EACH_BB_FN (bb, fun)
     find_conditions (bb, &conditions_in_bbs);
 
-  FOR_EACH_BB_FN (bb, fun)
-    {
-      condition_info *info = conditions_in_bbs.get (bb);
-      if (info)
-	{
-	  debug_bb (gimple_bb (info->m_cond));
-	  for (unsigned i = 0; i < info->m_ranges.length (); i++)
-	    debug_range_entry (&info->m_ranges[i]);
-	}
-    }
-
-  fprintf (stderr, "=====================\n");
-
   int *rpo = XNEWVEC (int, n_basic_blocks_for_fn (fun));
   unsigned n = pre_and_rev_post_order_compute_fn (fun, NULL, rpo, false);
 
@@ -522,26 +493,35 @@ pass_if_to_switch::execute (function *fun)
 	      info = info2;
 	    }
 
-	  fprintf (stderr, "Found chain with %d items\n", chain->m_entries.length ());
 	  chain->m_entries.reverse ();
-	  for (unsigned i = 0; i < chain->m_entries.length (); i++)
+	  if (chain->m_entries.length () >= 3
+	      && chain->is_beneficial ())
 	    {
-	      debug_bb (chain->m_entries[i]->m_true_edge->src);
-	    }
-
-	  if (chain->m_entries.length () >= 4)
-	    {
-	    convert_if_conditions_to_switch (chain);
-	    // TODO
-	    break;
+	      expanded_location loc
+		= expand_location (gimple_location (chain->m_entries[0]->m_cond));
+	      if (dump_file)
+		{
+		  fprintf (dump_file, "Condition chain (at %s:%d) with %d BBs "
+			   "transformed into a switch statement.\n",
+			   loc.file, loc.line,
+			   chain->m_entries.length ());
+		}
+	      all_candidates.safe_push (chain);
 	    }
 	}
     }
 
+  for (unsigned i = 0; i < all_candidates.length (); i++)
+    {
+      convert_if_conditions_to_switch (all_candidates[i]);
+      delete all_candidates[i];
+    }
+
   free (rpo);
   free_dominance_info (CDI_DOMINATORS);
 
-  mark_virtual_operands_for_renaming (fun);
+  if (!all_candidates.is_empty ())
+    mark_virtual_operands_for_renaming (fun);
 
   return 0;
 }
diff --git a/gcc/tree-switch-conversion.h b/gcc/tree-switch-conversion.h
index 1e25087a21d..62cfde168c8 100644
--- a/gcc/tree-switch-conversion.h
+++ b/gcc/tree-switch-conversion.h
@@ -122,7 +122,8 @@ class simple_cluster: public cluster
 public:
   /* Constructor.  */
   inline simple_cluster (tree low, tree high, tree case_label_expr,
-			 basic_block case_bb, profile_probability prob);
+			 basic_block case_bb, profile_probability prob,
+			 bool has_forward_bb = false);
 
   /* Destructor.  */
   ~simple_cluster ()
@@ -187,12 +188,16 @@ public:
 
   /* True if case is a range.  */
   bool m_range_p;
+
+  /* True if the case will use a forwarder BB.  */
+  bool m_has_forward_bb;
 };
 
 simple_cluster::simple_cluster (tree low, tree high, tree case_label_expr,
-				basic_block case_bb, profile_probability prob):
+				basic_block case_bb, profile_probability prob,
+				bool has_forward_bb):
   cluster (case_label_expr, case_bb, prob, prob),
-  m_low (low), m_high (high)
+  m_low (low), m_high (high), m_has_forward_bb (has_forward_bb)
 {
   m_range_p = m_high != NULL;
   if (m_high == NULL)


More information about the Gcc-cvs mailing list