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] [tree-optimization/69320] Optimize tests of boolean ranged objects against constants not 0 or 1



The problem with 69320 (and its various duplicates) is via various paths we can end up with tests of a boolean ranged object against a constant outside a boolean range. ie

if (x != 23)

Where x is a boolean ranged object.

That in turn ran afoul of code in record_edge_info which assumed that a test against a boolean ranged object would only use boolean ranged constants.

We want to do two things here. First we want to optimize those tests, which this patch does. Second we want to make record_edge_info more robust against such braindamage in the IL, just in case it was to sneak through again which is patch also does.

The 4 tests are actually from duplicate bug reports. They're much nicer than ffmpeg to work with.

Bootstrapped and regression tested on x86_64-linux-gnu. Installed on the trunk.

Note there's a few other bugs that were recently reported (code gen issues) which may be further duplicates. I'll look at them tomorrow if nobody else gets to them first.

Sorry for the breakage and wasted time folks.

jeff
commit 99d5655457f90a85a880f17490cef5e2a487abe0
Author: law <law@138bc75d-0d04-0410-961f-82ee72b054a4>
Date:   Tue Jan 19 06:43:54 2016 +0000

    2016-01-18  Jeff Law  <law@redhat.com>
    
    	PR tree-optimization/69320
    	* tree-ssa-dom.c (record_edge_info): For comparisons against a boolean
    	ranged object, do nothing if the RHS constant is not [0..1].
    	(optimize_stmt): Comparing a boolean ranged object against a
    	constant outside [0..1] results in a compile-time constant.
    
    	* tree-ssanames.c (ssa_name_has_boolean_range): Remove unnecessary
    	test.
    
    	PR tree-optimization/69320
    	* gcc.c-torture/pr69320-1.c: New test.
    	* gcc.c-torture/pr69320-2.c: New test.
    	* gcc.c-torture/pr69320-3.c: New test.
    	* gcc.c-torture/pr69320-4.c: New test.
    
    git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@232548 138bc75d-0d04-0410-961f-82ee72b054a4

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index de6e1ed..b39f864 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,14 @@
+2016-01-18  Jeff Law  <law@redhat.com>
+
+	PR tree-optimization/69320
+	* tree-ssa-dom.c (record_edge_info): For comparisons against a boolean
+	ranged object, do nothing if the RHS constant is not [0..1].
+	(optimize_stmt): Comparing a boolean ranged object against a
+	constant outside [0..1] results in a compile-time constant.
+
+	* tree-ssanames.c (ssa_name_has_boolean_range): Remove unnecessary
+	test.
+
 2016-01-18  Sandra Loosemore <sandra@codesourcery.com>
 
 	* doc/invoke.texi (Invoking GCC): Add new section to menu.
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 9245b50..fc476b9 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,11 @@
+2016-01-15  Jeff Law  <law@redhat.com>
+
+	PR tree-optimization/69320
+	* gcc.c-torture/pr69320-1.c: New test.
+	* gcc.c-torture/pr69320-2.c: New test.
+	* gcc.c-torture/pr69320-3.c: New test.
+	* gcc.c-torture/pr69320-4.c: New test.
+
 2016-01-18  Patrick Palka  <ppalka@gcc.gnu.org>
 
 	PR c++/11858
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr69320-1.c b/gcc/testsuite/gcc.c-torture/execute/pr69320-1.c
new file mode 100644
index 0000000..0aba2fc
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr69320-1.c
@@ -0,0 +1,20 @@
+#include <stdlib.h>
+int a, b, d, f;
+char c;
+static int *e = &d;
+int main() {
+  int g = -1L;
+  *e = g;
+  c = 4;
+  for (; c >= 14; c++)
+    *e = 1;
+  f = a == 0;
+  *e ^= f;
+  int h = ~d;
+  if (d)
+    b = h;
+  if (h)
+    exit (0);
+  abort ();
+}
+
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr69320-2.c b/gcc/testsuite/gcc.c-torture/execute/pr69320-2.c
new file mode 100644
index 0000000..b85672c
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr69320-2.c
@@ -0,0 +1,35 @@
+
+#include <stdlib.h>
+
+int a, *c, d, e, g, f;
+short b;
+
+int 
+fn1 ()
+{
+  int h = d != 10;
+  if (h > g)
+     asm volatile ("" : : : "memory");
+  if (h == 10)
+    {
+      int *i = 0;
+      a = 0;
+      for (; a < 7; a++)
+	for (; *i;)
+	  ;
+    }
+  else
+    {
+      b = e / h;
+      return f;
+    }
+  c = &h;
+  abort ();
+}
+
+int
+main ()
+{
+  fn1 ();
+  exit (0);
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr69320-3.c b/gcc/testsuite/gcc.c-torture/execute/pr69320-3.c
new file mode 100644
index 0000000..213c93f
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr69320-3.c
@@ -0,0 +1,17 @@
+#include <stdlib.h>
+
+static int a[40] = {7, 5, 3, 3, 0, 0, 3};
+short b;
+int c = 5;
+int main() {
+  b = 0;
+  for (; b <= 3; b++)
+    if (a[b + 6] ^ (0 || c))
+      ;
+    else
+      break;
+  if (b != 4)
+    abort ();
+  exit (0);
+}
+
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr69320-4.c b/gcc/testsuite/gcc.c-torture/execute/pr69320-4.c
new file mode 100644
index 0000000..356cd0f
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr69320-4.c
@@ -0,0 +1,18 @@
+#include <stdlib.h>
+
+int a;
+char b, d;
+short c;
+short fn1(int p1, int p2) { return p2 >= 2 ? p1 : p1 > p2; }
+
+int main() {
+  int *e = &a, *f = &a;
+  b = 1;
+  for (; b <= 9; b++) {
+    c = *e != 5 || d;
+    *f = fn1(c || b, a);
+  }
+  if ((long long) a != 1)
+    abort ();
+  exit (0);
+}
diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c
index 8298637..3eeaa9c 100644
--- a/gcc/tree-ssa-dom.c
+++ b/gcc/tree-ssa-dom.c
@@ -387,11 +387,16 @@ record_edge_info (basic_block bb)
 
           /* Special case comparing booleans against a constant as we
              know the value of OP0 on both arms of the branch.  i.e., we
-             can record an equivalence for OP0 rather than COND.  */
-          if ((code == EQ_EXPR || code == NE_EXPR)
-              && TREE_CODE (op0) == SSA_NAME
+             can record an equivalence for OP0 rather than COND. 
+
+	     However, don't do this if the constant isn't zero or one.
+	     Such conditionals will get optimized more thoroughly during
+	     the domwalk.  */
+	  if ((code == EQ_EXPR || code == NE_EXPR)
+	      && TREE_CODE (op0) == SSA_NAME
 	      && ssa_name_has_boolean_range (op0)
-              && is_gimple_min_invariant (op1))
+	      && is_gimple_min_invariant (op1)
+	      && (integer_zerop (op1) || integer_onep (op1)))
             {
 	      tree true_val = constant_boolean_node (true, TREE_TYPE (op0));
 	      tree false_val = constant_boolean_node (false, TREE_TYPE (op0));
@@ -1828,6 +1833,31 @@ optimize_stmt (basic_block bb, gimple_stmt_iterator si,
 	    }
 	}
 
+      if (gimple_code (stmt) == GIMPLE_COND)
+	{
+	  tree lhs = gimple_cond_lhs (stmt);
+	  tree rhs = gimple_cond_rhs (stmt);
+
+	  /* If the LHS has a range [0..1] and the RHS has a range ~[0..1],
+	     then this conditional is computable at compile time.  We can just
+	     shove either 0 or 1 into the LHS, mark the statement as modified
+	     and all the right things will just happen below.
+
+	     Note this would apply to any case where LHS has a range
+	     narrower than its type implies and RHS is outside that
+	     narrower range.  Future work.  */
+	  if (TREE_CODE (lhs) == SSA_NAME
+	      && ssa_name_has_boolean_range (lhs)
+	      && TREE_CODE (rhs) == INTEGER_CST
+	      && ! (integer_zerop (rhs) || integer_onep (rhs)))
+	    {
+	      gimple_cond_set_lhs (as_a <gcond *> (stmt),
+				   fold_convert (TREE_TYPE (lhs),
+						 integer_zero_node));
+	      gimple_set_modified (stmt, true);
+	    }
+	}
+
       update_stmt_if_modified (stmt);
       eliminate_redundant_computations (&si, const_and_copies,
 					avail_exprs_stack);
diff --git a/gcc/tree-ssanames.c b/gcc/tree-ssanames.c
index b6f72e2..ed87f3e 100644
--- a/gcc/tree-ssanames.c
+++ b/gcc/tree-ssanames.c
@@ -437,8 +437,7 @@ ssa_name_has_boolean_range (tree op)
      only takes on values [0..1] as determined by VRP
      analysis.  */
   if (INTEGRAL_TYPE_P (TREE_TYPE (op))
-      && (TYPE_PRECISION (TREE_TYPE (op)) > 1
-	  || TYPE_UNSIGNED (TREE_TYPE (op)))
+      && (TYPE_PRECISION (TREE_TYPE (op)) > 1)
       && wi::eq_p (get_nonzero_bits (op), 1))
     return true;
 

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