diff mbox

Fix PR66945

Message ID alpine.LSU.2.11.1507221102010.9923@zhemvz.fhfr.qr
State New
Headers show

Commit Message

Richard Biener July 22, 2015, 9:08 a.m. UTC
The following fixes issues that arise when a SSA propagator ends up
deciding only a single outgoing edge is executable but the folder
at substitute-and-fold time decides the other one is executable.
This can of course only happen with undefined behavior (or with
bugs...).  In this case the propagator (copyprop) sees a
condition if (0 > unsigned-var) and decides this always evaluates
to false.  But fold, given more context and being inherently more
powerful than a simple copyprop sees that unsigned-var is actually
0 % 0 and 0 > 0 % 0 evaluates to true (because we have that match.pd
pattern saying that X % Y is smaller than Y which is a valid answer
considering that % 0 invokes undefined behavior).

Rather than trying to fix this by conditionalizing that pattern
against a zero modulo I decided that of course what the propagator
things of edge executability has to agree with what fold produces,
thus we just force the propagators idea.

Otherwise you run into this testcases issue where the lattice
contains a value that is computed in the path that fold now
decides to delete.

Bootstrapped on x86_64-unknown-linux-gnu, testing in progress.

Richard.

2015-07-22  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/66945
	* tree-ssa-propagate.c (substitute_and_fold_dom_walker
	::before_dom_children): Force the propagators idea of
	non-executable edges to materialize, not what the folder
	chooses.

	* gcc.dg/torture/pr66945.c: New testcase.
diff mbox

Patch

Index: gcc/tree-ssa-propagate.c
===================================================================
--- gcc/tree-ssa-propagate.c	(revision 226042)
+++ gcc/tree-ssa-propagate.c	(working copy)
@@ -1236,13 +1236,33 @@  substitute_and_fold_dom_walker::before_d
 
       /* If we made a replacement, fold the statement.  */
       if (did_replace)
-	fold_stmt (&i, follow_single_use_edges);
+	{
+	  fold_stmt (&i, follow_single_use_edges);
+	  stmt = gsi_stmt (i);
+	}
+
+      /* If this is a control statement the propagator left edges
+         unexecuted on force the condition in a way consistent with
+	 that.  See PR66945 for cases where the propagator can end
+	 up with a different idea of a taken edge than folding
+	 (once undefined behavior is involved).  */
+      if (gimple_code (stmt) == GIMPLE_COND)
+	{
+	  if ((EDGE_SUCC (bb, 0)->flags & EDGE_EXECUTABLE)
+	      ^ (EDGE_SUCC (bb, 1)->flags & EDGE_EXECUTABLE))
+	    {
+	      if (((EDGE_SUCC (bb, 0)->flags & EDGE_TRUE_VALUE) != 0)
+		  == ((EDGE_SUCC (bb, 0)->flags & EDGE_EXECUTABLE) != 0))
+		gimple_cond_make_true (as_a <gcond *> (stmt));
+	      else
+		gimple_cond_make_false (as_a <gcond *> (stmt));
+	      did_replace = true;
+	    }
+	}
 
       /* Now cleanup.  */
       if (did_replace)
 	{
-	  stmt = gsi_stmt (i);
-
 	  /* If we cleaned up EH information from the statement,
 	     remove EH edges.  */
 	  if (maybe_clean_or_replace_eh_stmt (old_stmt, stmt))
Index: gcc/testsuite/gcc.dg/torture/pr66945.c
===================================================================
--- gcc/testsuite/gcc.dg/torture/pr66945.c	(revision 0)
+++ gcc/testsuite/gcc.dg/torture/pr66945.c	(working copy)
@@ -0,0 +1,12 @@ 
+/* { dg-do compile } */
+
+unsigned b;
+void f()
+{
+  for(;;)
+    if(!b?:(b=0))
+      ;
+    else if(b%0<b?:b) /* { dg-warning "division by zero" } */
+      for(;;)
+	;
+}