public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc(refs/users/marxin/heads/loop-unswitching-switch)] Something working.
@ 2021-08-31 14:33 Martin Liska
  0 siblings, 0 replies; only message in thread
From: Martin Liska @ 2021-08-31 14:33 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:0c4194dab17ccad6993e4f84f01ba4f908f69ab5

commit 0c4194dab17ccad6993e4f84f01ba4f908f69ab5
Author: Martin Liska <mliska@suse.cz>
Date:   Tue Aug 31 15:47:33 2021 +0200

    Something working.

Diff:
---
 gcc/tree-ssa-loop-unswitch.c | 114 +++++++++++++++++++++++--------------------
 1 file changed, 61 insertions(+), 53 deletions(-)

diff --git a/gcc/tree-ssa-loop-unswitch.c b/gcc/tree-ssa-loop-unswitch.c
index c7cf0223501..762c5bde8b2 100644
--- a/gcc/tree-ssa-loop-unswitch.c
+++ b/gcc/tree-ssa-loop-unswitch.c
@@ -78,7 +78,7 @@ along with GCC; see the file COPYING3.  If not see
 
 static class loop *tree_unswitch_loop (class loop *, basic_block, tree);
 static bool tree_unswitch_single_loop (class loop *, int);
-static tree tree_may_unswitch_on (basic_block, class loop *);
+static tree tree_may_unswitch_on (basic_block, class loop *, edge *);
 static bool tree_unswitch_outer_loop (class loop *);
 static edge find_loop_guard (class loop *);
 static bool empty_bb_without_guard_p (class loop *, basic_block);
@@ -105,7 +105,25 @@ tree_ssa_unswitch_loops (void)
     }
 
   if (changed)
-    return TODO_cleanup_cfg;
+    {
+      basic_block bb;
+      edge_iterator ei;
+      edge e;
+
+      if (dump_file)
+	dump_function_to_file (cfun->decl, dump_file, dump_flags);
+
+      FOR_EACH_BB_FN (bb, cfun)
+	FOR_EACH_EDGE (e, ei, bb->succs)
+	  if (e->flags & EDGE_IGNORE)
+	    {
+	      if (dump_file)
+		fprintf (dump_file, "%d->%d\n", e->src->index, e->dest->index);
+	    }
+
+
+      return TODO_cleanup_cfg;
+    }
   return 0;
 }
 
@@ -187,7 +205,7 @@ is_maybe_undefined (const tree name, gimple *stmt, class loop *loop)
    basic blocks (for what it means see comments below).  */
 
 static tree
-tree_may_unswitch_on (basic_block bb, class loop *loop)
+tree_may_unswitch_on (basic_block bb, class loop *loop, edge *cond_edge)
 {
   gimple *last, *def;
   tree cond, use;
@@ -225,9 +243,13 @@ tree_may_unswitch_on (basic_block bb, class loop *loop)
     }
   else if (gswitch *stmt = safe_dyn_cast <gswitch *> (last))
     {
+      // TODO: support generic switches
+      unsigned nlabels = gimple_switch_num_labels (stmt);
+
       tree idx = gimple_switch_index (stmt);
       if (TREE_CODE (idx) != SSA_NAME
-	  || gimple_switch_num_labels (stmt) < 1)
+	  || nlabels < 1
+	  || nlabels != EDGE_COUNT (gimple_bb (stmt)->succs))
 	return NULL_TREE;
       /* Index must be invariant.  */
       def = SSA_NAME_DEF_STMT (idx);
@@ -241,14 +263,24 @@ tree_may_unswitch_on (basic_block bb, class loop *loop)
 	return NULL_TREE;
       /* TODO: pick based on profile or on biggest range (TODO: implement
 	 ranges).  */
-      tree lab = gimple_switch_label (stmt, 1);
-      if (CASE_HIGH (lab))
-	return NULL_TREE;
-      cond = build2 (EQ_EXPR, boolean_type_node, idx, CASE_LOW (lab));
-      return cond;
+
+      for (unsigned i = 1; i < gimple_switch_num_labels (stmt); ++i)
+	{
+	  tree lab = gimple_switch_label (stmt, i);
+	  if (CASE_HIGH (lab))
+	    continue;
+
+	  basic_block dest = label_to_block (cfun, CASE_LABEL (lab));
+	  edge e = find_edge (gimple_bb (stmt), dest);
+	  if (!(e->flags & EDGE_IGNORE))
+	    {
+	      *cond_edge = e;
+	      return build2 (EQ_EXPR, boolean_type_node, idx, CASE_LOW (lab));
+	    }
+	}
     }
-  else
-    return NULL_TREE;
+
+  return NULL_TREE;
 }
 
 /* Simplifies COND using checks in front of the entry of the LOOP.  Just very
@@ -314,9 +346,9 @@ tree_unswitch_single_loop (class loop *loop, int num)
       if (tree_num_loop_insns (loop, &eni_size_weights)
 	  > (unsigned) param_max_unswitch_insns)
 	{
-	  if (dump_file && (dump_flags & TDF_DETAILS))
-	    fprintf (dump_file, ";; Not unswitching, loop too big\n");
-	  return false;
+//	  if (dump_file && (dump_flags & TDF_DETAILS))
+//	    fprintf (dump_file, ";; Not unswitching, loop too big\n");
+//	  return false;
 	}
 
       /* If the loop is not expected to iterate, there is no need
@@ -339,17 +371,18 @@ tree_unswitch_single_loop (class loop *loop, int num)
 
   while (1)
     {
+      edge cond_edge = NULL;
       /* Find a bb to unswitch on.  */
       for (; i < loop->num_nodes; i++)
-	if ((cond = tree_may_unswitch_on (bbs[i], loop)))
+	if ((cond = tree_may_unswitch_on (bbs[i], loop, &cond_edge)))
 	  break;
 
       if (i == loop->num_nodes)
 	{
-	  if (dump_file
-	      && num > param_max_unswitch_level
-	      && (dump_flags & TDF_DETAILS))
-	    fprintf (dump_file, ";; Not unswitching anymore, hit max level\n");
+//	  if (dump_file
+//	      && num > param_max_unswitch_level
+//	      && (dump_flags & TDF_DETAILS))
+//	    fprintf (dump_file, ";; Not unswitching anymore, hit max level\n");
 
 	  if (found == loop->num_nodes)
 	    {
@@ -385,34 +418,10 @@ tree_unswitch_single_loop (class loop *loop, int num)
 						 boolean_false_node);
 	  else
 	    {
-	      start_recording_case_labels ();
 	      // we should know the edge already
-	      gswitch *gs = as_a <gswitch *> (stmt);
-	      tree lab = gimple_switch_label (gs, 1);
-	      basic_block dest = label_to_block (cfun, CASE_LABEL (lab));
-	      edge e = find_edge (gimple_bb (stmt), dest);
-	      unsigned nlabels = gimple_switch_num_labels (gs);
-	      for (unsigned i = 1; i < nlabels - 1; i++)
-		{
-		  tree next_label = gimple_switch_label (gs, i + 1);
-		  gimple_switch_set_label (gs, i, next_label);
-		  basic_block next_dest
-		    = label_to_block (cfun, CASE_LABEL (next_label));
-
-		  /* Shared edge among multiple cases.  */ 
-		  if (e != NULL && e->dest == next_dest)
-		    e = NULL;
-		}
-	      // modifying the CFG here may play havoc on things like
-	      // dominators and we really would like to prevent doing
-	      // full update_ssa for each individual unswitching as well
-	      if (e != NULL)
-		remove_edge (e);
-
-	      gimple_switch_set_num_labels (gs, nlabels  - 1);
-	      end_recording_case_labels ();
+	      cond_edge->flags |= EDGE_IGNORE;
 	      /* Update based on the adjusted switch.  */
-	      cond = tree_may_unswitch_on (bbs[i], loop);
+	      cond = tree_may_unswitch_on (bbs[i], loop, &cond_edge);
 	    }
 	  changed = true;
 	}
@@ -503,9 +512,10 @@ tree_unswitch_single_loop (class loop *loop, int num)
       free (worklist);
 
       /* Find a bb to unswitch on.  */
+      edge cond_edge;
       for (; found < loop->num_nodes; found++)
 	if ((bbs[found]->flags & BB_REACHABLE)
-	    && (cond = tree_may_unswitch_on (bbs[found], loop)))
+	    && (cond = tree_may_unswitch_on (bbs[found], loop, &cond_edge)))
 	  break;
 
       if (found == loop->num_nodes)
@@ -529,16 +539,14 @@ tree_unswitch_single_loop (class loop *loop, int num)
     }
 
   /* Update the SSA form after unswitching.  */
-  free_dominance_info (CDI_DOMINATORS);
-  cleanup_tree_cfg (TODO_update_ssa);
-  //update_ssa (TODO_update_ssa);
+  // free_dominance_info (CDI_DOMINATORS);
+  // cleanup_tree_cfg (TODO_update_ssa);
+  update_ssa (TODO_update_ssa);
   free_original_copy_tables ();
 
   /* Invoke itself on modified loops.  */
-  if (nloop->aux != (void *)0xa5a5a5a5a5a5a5a5)
-    tree_unswitch_single_loop (nloop, num + 1);
-  if (loop->aux != (void *)0xa5a5a5a5a5a5a5a5)
-    tree_unswitch_single_loop (loop, num + 1);
+  tree_unswitch_single_loop (nloop, num + 1);
+  tree_unswitch_single_loop (loop, num + 1);
   free (bbs);
   return true;
 }


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2021-08-31 14:33 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-08-31 14:33 [gcc(refs/users/marxin/heads/loop-unswitching-switch)] Something working Martin Liska

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).