This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix PR81181


The following fixes another case of endless compute_antic iteration
in PRE.  After a lengthy four-eyes discussion here we concluded that
the way clean () operates on expressions rather than values can
cause oscillation in the dataflow problem.

Thus we have to delay it (at the cost of some intermediate extra size of
ANTIC_IN sets).

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk.

2017-08-01  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/81181
	* tree-ssa-pre.c (compute_antic_aux): Defer clean() to ...
	(compute_antic): ... end of iteration here.

	* gcc.dg/torture/pr81181.c: New testcase.

Index: gcc/tree-ssa-pre.c
===================================================================
--- gcc/tree-ssa-pre.c	(revision 250725)
+++ gcc/tree-ssa-pre.c	(working copy)
@@ -2115,7 +2166,8 @@ static sbitmap has_abnormal_preds;
      ANTIC_OUT[BLOCK] = phi_translate (ANTIC_IN[succ(BLOCK)])
 
    ANTIC_IN[BLOCK] = clean(ANTIC_OUT[BLOCK] U EXP_GEN[BLOCK] - TMP_GEN[BLOCK])
-*/
+
+   Note that clean() is deferred until after the iteration.  */
 
 static bool
 compute_antic_aux (basic_block block, bool block_has_abnormal_pred_edge)
@@ -2215,7 +2267,8 @@ compute_antic_aux (basic_block block, bo
     bitmap_value_insert_into_set (ANTIC_IN (block),
 				  expression_for_id (bii));
 
-  clean (ANTIC_IN (block));
+  /* clean (ANTIC_IN (block)) is defered to after the iteration converged
+     because it can cause non-convergence, see for example PR81181.  */
 
   if (!was_visited || !bitmap_set_equal (old, ANTIC_IN (block)))
     changed = true;
@@ -2449,6 +2504,12 @@ compute_antic (void)
       gcc_checking_assert (num_iterations < 500);
     }
 
+  /* We have to clean after the dataflow problem converged as cleaning
+     can cause non-convergence because it is based on expressions
+     rather than values.  */
+  FOR_EACH_BB_FN (block, cfun)
+    clean (ANTIC_IN (block));
+
   statistics_histogram_event (cfun, "compute_antic iterations",
 			      num_iterations);
 
Index: gcc/testsuite/gcc.dg/torture/pr81181.c
===================================================================
--- gcc/testsuite/gcc.dg/torture/pr81181.c	(nonexistent)
+++ gcc/testsuite/gcc.dg/torture/pr81181.c	(working copy)
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+
+unsigned int lh;
+
+void
+ny (int t3, int ys, int rt, int p8)
+{
+  if (lh != 0)
+    {
+      if (0)
+	{
+oo:
+	  do
+	    {
+	      rt = (p8 != 0) ? t3 : 0;
+	      rt = (rt != 0 || lh != (unsigned int)ys);
+	      rt += lh + ys;
+	    }
+	  while (t3 <= 0);
+
+	  lh = ys;
+	  ys = rt;
+	}
+
+      if (lh != 0)
+	p8 = lh;
+    }
+
+  goto oo;
+}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]