re PR middle-end/34400 (bad interaction between DF and SJLJ exceptions)
authorSeongbae Park <seongbae.park@gmail.com>
Thu, 17 Jan 2008 20:02:56 +0000 (20:02 +0000)
committerSeongbae Park <spark@gcc.gnu.org>
Thu, 17 Jan 2008 20:02:56 +0000 (20:02 +0000)
2008-01-17  Seongbae Park  <seongbae.park@gmail.com>

PR rtl-optimization/34400
* df-core.c (df_worklist_dataflow_overeager,
df_worklist_dataflow_doublequeue): New functions.
(df_worklist_dataflow): Two different worklist solvers.
* params.def (PARAM_DF_DOUBLE_QUEUE_THRESHOLD_FACTOR):
New param.

From-SVN: r131608

gcc/ChangeLog
gcc/df-core.c
gcc/params.def

index 3803760fc68389fa522d407758dabb9182b35303..c7e5849c0052347f7cbab669dd9f83fb7b7d0d6e 100644 (file)
@@ -1,3 +1,12 @@
+2008-01-17  Seongbae Park  <seongbae.park@gmail.com>
+
+       PR rtl-optimization/34400
+       * df-core.c (df_worklist_dataflow_overeager,
+       df_worklist_dataflow_doublequeue): New functions.
+       (df_worklist_dataflow): Two different worklist solvers.
+       * params.def (PARAM_DF_DOUBLE_QUEUE_THRESHOLD_FACTOR):
+       New param.
+
 2008-01-16  Sebastian Pop  <sebastian.pop@amd.com>
 
        PR testsuite/34821
index 9692dbbb7dc7185bbdd3d4b1c46e54a5f6c21bd0..5404000ef3972f753041ec55fa200f8e04e0db79 100644 (file)
@@ -399,6 +399,7 @@ are write-only operations.
 #include "timevar.h"
 #include "df.h"
 #include "tree-pass.h"
+#include "params.h"
 
 static void *df_get_bb_info (struct dataflow *, unsigned int);
 static void df_set_bb_info (struct dataflow *, unsigned int, void *);
@@ -931,6 +932,105 @@ df_worklist_propagate_backward (struct dataflow *dataflow,
 }
 
 
+
+/* This will free "pending". */
+static void 
+df_worklist_dataflow_overeager (struct dataflow *dataflow,
+                               bitmap pending,
+                                sbitmap considered,
+                                int *blocks_in_postorder,
+                               unsigned *bbindex_to_postorder)
+{
+  enum df_flow_dir dir = dataflow->problem->dir;
+  int count = 0;
+
+  while (!bitmap_empty_p (pending))
+    {
+      unsigned bb_index;
+      int index;
+      count++;
+
+      index = bitmap_first_set_bit (pending);
+      bitmap_clear_bit (pending, index);
+
+      bb_index = blocks_in_postorder[index];
+
+      if (dir == DF_FORWARD)
+       df_worklist_propagate_forward (dataflow, bb_index,
+                                      bbindex_to_postorder,
+                                      pending, considered);
+      else 
+       df_worklist_propagate_backward (dataflow, bb_index,
+                                       bbindex_to_postorder,
+                                       pending, considered);
+    }
+
+  BITMAP_FREE (pending);
+
+  /* Dump statistics. */
+  if (dump_file)
+    fprintf (dump_file, "df_worklist_dataflow_overeager:"
+            "n_basic_blocks %d n_edges %d"
+            " count %d (%5.2g)\n",
+            n_basic_blocks, n_edges,
+            count, count / (float)n_basic_blocks);
+}
+
+static void 
+df_worklist_dataflow_doublequeue (struct dataflow *dataflow,
+                                 bitmap pending,
+                                  sbitmap considered,
+                                  int *blocks_in_postorder,
+                                 unsigned *bbindex_to_postorder)
+{
+  enum df_flow_dir dir = dataflow->problem->dir;
+  int dcount = 0;
+  bitmap worklist = BITMAP_ALLOC (&df_bitmap_obstack);
+
+  /* Double-queueing. Worklist is for the current iteration,
+     and pending is for the next. */
+  while (!bitmap_empty_p (pending))
+    {
+      /* Swap pending and worklist. */
+      bitmap temp = worklist;
+      worklist = pending;
+      pending = temp;
+
+      do
+       {
+         int index;
+         unsigned bb_index;
+         dcount++;
+
+         index = bitmap_first_set_bit (worklist);
+         bitmap_clear_bit (worklist, index);
+
+         bb_index = blocks_in_postorder[index];
+
+         if (dir == DF_FORWARD)
+           df_worklist_propagate_forward (dataflow, bb_index,
+                                          bbindex_to_postorder,
+                                          pending, considered);
+         else 
+           df_worklist_propagate_backward (dataflow, bb_index,
+                                           bbindex_to_postorder,
+                                           pending, considered);
+       }
+      while (!bitmap_empty_p (worklist));
+    }
+
+  BITMAP_FREE (worklist);
+  BITMAP_FREE (pending);
+
+  /* Dump statistics. */
+  if (dump_file)
+    fprintf (dump_file, "df_worklist_dataflow_doublequeue:"
+            "n_basic_blocks %d n_edges %d"
+            " count %d (%5.2g)\n",
+            n_basic_blocks, n_edges,
+            dcount, dcount / (float)n_basic_blocks);
+}
+
 /* Worklist-based dataflow solver. It uses sbitmap as a worklist,
    with "n"-th bit representing the n-th block in the reverse-postorder order. 
    This is so-called over-eager algorithm where it propagates
@@ -942,7 +1042,14 @@ df_worklist_propagate_backward (struct dataflow *dataflow,
    iterative algorithm by some margin overall.  
    Note that this is slightly different from the traditional textbook worklist solver,
    in that the worklist is effectively sorted by the reverse postorder.
-   For CFGs with no nested loops, this is optimal.  */
+   For CFGs with no nested loops, this is optimal. 
+   
+   The overeager algorithm while works well for typical inputs,
+   it could degenerate into excessive iterations given CFGs with high loop nests
+   and unstructured loops. To cap the excessive iteration on such case,
+   we switch to double-queueing when the original algorithm seems to 
+   get into such.
+   */
 
 void 
 df_worklist_dataflow (struct dataflow *dataflow,
@@ -983,29 +1090,31 @@ df_worklist_dataflow (struct dataflow *dataflow,
       bitmap_set_bit (pending, i);
     }
 
+  /* Initialize the problem. */
   if (dataflow->problem->init_fun)
     dataflow->problem->init_fun (blocks_to_consider);
 
-  while (!bitmap_empty_p (pending))
+  /* Solve it. Determine the solving algorithm
+     based on a simple heuristic. */
+  if (n_edges > PARAM_VALUE (PARAM_DF_DOUBLE_QUEUE_THRESHOLD_FACTOR)
+      * n_basic_blocks)
     {
-      unsigned bb_index;
-
-      index = bitmap_first_set_bit (pending);
-      bitmap_clear_bit (pending, index);
-
-      bb_index = blocks_in_postorder[index];
-
-      if (dir == DF_FORWARD)
-        df_worklist_propagate_forward (dataflow, bb_index,
-                                       bbindex_to_postorder,
-                                       pending, considered);
-      else 
-        df_worklist_propagate_backward (dataflow, bb_index,
-                                        bbindex_to_postorder,
-                                        pending, considered);
+      /* High average connectivity, meaning dense graph
+         with more likely deep nested loops
+        or unstructured loops. */
+      df_worklist_dataflow_doublequeue (dataflow, pending, considered,
+                                       blocks_in_postorder,
+                                       bbindex_to_postorder);
+    }
+  else 
+    {
+      /* Most inputs fall into this case
+        with relatively flat or structured CFG. */
+      df_worklist_dataflow_overeager (dataflow, pending, considered,
+                                     blocks_in_postorder,
+                                     bbindex_to_postorder);
     }
 
-  BITMAP_FREE (pending);
   sbitmap_free (considered);
   free (bbindex_to_postorder);
 }
index 1915727e28b342f50eac0624667f8f99a456cd25..0baff3d1d6106dd82fd18e9da0d7acd01c83413a 100644 (file)
@@ -724,6 +724,11 @@ DEFPARAM (PARAM_SCCVN_MAX_SCC_SIZE,
          10000, 10, 0)
 
 
+DEFPARAM (PARAM_DF_DOUBLE_QUEUE_THRESHOLD_FACTOR,
+         "df-double-queue-threshold-factor",
+         "Multiplier used for determining the double-queueing threshold",
+         2, 0, 0)
+
 /*
 Local variables:
 mode:c