summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Law <law@redhat.com>2016-01-18 23:43:54 -0700
committerJeff Law <law@gcc.gnu.org>2016-01-18 23:43:54 -0700
commit2bedb645f2aef48d7cbb70bf5ddb8bf0a4342019 (patch)
tree01f06939e38904f487d71de67d847c5e7cc30273
parent17c15cb932563bb814865c39abc2b952c7707f79 (diff)
re PR tree-optimization/69320 (wrong code generation at -O2 and higher)
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. From-SVN: r232548
-rw-r--r--gcc/ChangeLog11
-rw-r--r--gcc/testsuite/ChangeLog8
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr69320-1.c20
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr69320-2.c35
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr69320-3.c17
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr69320-4.c18
-rw-r--r--gcc/tree-ssa-dom.c38
-rw-r--r--gcc/tree-ssanames.c3
8 files changed, 144 insertions, 6 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index de6e1ede674..b39f864c323 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 9245b50b567..fc476b96b80 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 00000000000..0aba2fc4b19
--- /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 00000000000..b85672ce528
--- /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 00000000000..213c93f4d08
--- /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 00000000000..356cd0f8528
--- /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 829863794a3..3eeaa9cdcf9 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 b6f72e2ba2c..ed87f3ee7d4 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;