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 PR66945


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.

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(;;)
+	;
+}


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