aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-16.c38
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-17.c36
-rw-r--r--gcc/tree-vrp.c55
5 files changed, 141 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index b0c253b..0f78f2a 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,12 @@
+2017-05-06 Jeff Law <law@redhat.com>
+
+ PR tree-optimization/78496
+ * tree-vrp.c (simplify_assert_expr_using_ranges): New function.
+ (simplify_stmt_using_ranges): Call it.
+ (vrp_dom_walker::before_dom_children): Extract equivalences
+ from an ASSERT_EXPR with an equality comparison against a
+ constant.
+
2017-05-06 Richard Sandiford <richard.sandiford@linaro.org>
* lra-constraints.c (lra_copy_reg_equiv): New function.
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index fca5b87..42782a6 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2017-05-06 Jeff Law <law@redhat.com>
+
+ PR tree-optimization/78496
+ * gcc.dg/tree-ssa/ssa-thread-16.c: New test.
+ * gcc.dg/tree-ssa/ssa-thread-17.c: New test.
+
2017-05-06 Richard Sandiford <richard.sandiford@linaro.org>
* gcc.target/aarch64/spill_1.c: New test.
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-16.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-16.c
new file mode 100644
index 0000000..78c349c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-16.c
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-vrp1-details" } */
+
+/* We should thread the if (exp == 2) conditional on the
+ the path from inside the if (x) THEN arm. It is the only
+ jump threading opportunity in this code. */
+
+/* { dg-final { scan-tree-dump-times "Threaded" 1 "vrp1" } } */
+
+
+extern void abort (void) __attribute__ ((__nothrow__, __leaf__))
+ __attribute__ ((__noreturn__));
+
+int x;
+
+
+int code;
+void
+do_jump (int exp)
+{
+ switch (code)
+ {
+ case 4:
+ if ((exp) == 1)
+ goto normal;
+ if (x)
+ {
+ if (exp != 0)
+ abort ();
+ }
+ if ((exp) == 2)
+ goto normal;
+ case 3:
+ abort ();
+ }
+ normal:
+ ;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-17.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-17.c
new file mode 100644
index 0000000..692658f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-17.c
@@ -0,0 +1,36 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-vrp1-details" } */
+
+/* We should simplify one ASSERT_EXPR from a relational
+ into an equality test. */
+/* { dg-final { scan-tree-dump-times "Folded into:\[^\r\n\]*ASSERT_EXPR\*\[^\r\n\]* == 1" 1 "vrp1" } } */
+
+/* And simplification of the ASSERT_EXPR leads to a jump threading opportunity. */
+/* { dg-final { scan-tree-dump-times "Threaded" 1 "vrp1" } } */
+
+extern void abort (void) __attribute__ ((__nothrow__, __leaf__))
+ __attribute__ ((__noreturn__));
+
+union gimple_statement_d;
+typedef union gimple_statement_d *gimple;
+
+
+
+union gimple_statement_d
+{
+ unsigned num_ops;
+};
+
+void
+gimple_assign_set_rhs_with_ops_1 (int code, gimple stmt, unsigned new_rhs_ops)
+{
+
+ stmt->num_ops = new_rhs_ops + 1;
+ if (stmt->num_ops <= 1)
+ abort ();
+ if (new_rhs_ops > 1)
+ if (stmt->num_ops <= 2)
+ abort ();
+ if (new_rhs_ops > 2)
+ abort ();
+}
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index cf50e90..461a48f 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -9600,6 +9600,43 @@ range_fits_type_p (value_range *vr, unsigned dest_precision, signop dest_sgn)
return true;
}
+/* Simplify STMT, an ASSERT_EXPR, using ranges. This is helpful because jump
+ threading looks at the ASSERT_EXPRs. Collapsing the condition of
+ an ASSERT_EXPR from a relational to an equality test is where most
+ of the benefit occurrs, so that's the only thing we currently do. */
+
+static bool
+simplify_assert_expr_using_ranges (gimple *stmt)
+{
+ return false;
+ tree cond = TREE_OPERAND (gimple_assign_rhs1 (stmt), 1);
+ tree_code code = TREE_CODE (cond);
+ tree op0 = TREE_OPERAND (cond, 0);
+
+ /* The condition of the ASSERT_EXPR must be a simple relational
+ between an SSA_NAME (with a range) and a constant. */
+ if (TREE_CODE (op0) != SSA_NAME
+ || !INTEGRAL_TYPE_P (TREE_TYPE (op0)))
+ return false;
+
+ tree op1 = TREE_OPERAND (cond, 1);
+ if (TREE_CODE (op1) != INTEGER_CST)
+ return false;
+
+ value_range *vr = get_value_range (op0);
+ if (!vr || vr->type != VR_RANGE)
+ return false;
+
+ tree res = test_for_singularity (code, op0, op1, vr);
+ if (res)
+ {
+ TREE_SET_CODE (cond, EQ_EXPR);
+ TREE_OPERAND (cond, 1) = res;
+ return true;
+ }
+ return false;
+}
+
/* Simplify a conditional using a relational operator to an equality
test if the range information indicates only one value can satisfy
the original conditional. */
@@ -10334,6 +10371,9 @@ simplify_stmt_using_ranges (gimple_stmt_iterator *gsi)
case MAX_EXPR:
return simplify_min_or_max_using_ranges (gsi, stmt);
+ case ASSERT_EXPR:
+ return simplify_assert_expr_using_ranges (stmt);
+
default:
break;
}
@@ -10598,6 +10638,18 @@ vrp_dom_walker::before_dom_children (basic_block bb)
{
tree rhs1 = gimple_assign_rhs1 (stmt);
tree cond = TREE_OPERAND (rhs1, 1);
+ tree lhs = gimple_assign_lhs (stmt);
+ m_const_and_copies->record_const_or_copy (lhs, TREE_OPERAND (rhs1, 0));
+
+ if (TREE_CODE (cond) == EQ_EXPR)
+ {
+ tree cond_op0 = TREE_OPERAND (cond, 0);
+ tree cond_op1 = TREE_OPERAND (cond, 1);
+ if (TREE_CODE (cond_op0) == SSA_NAME)
+ m_const_and_copies->record_const_or_copy (cond_op0, cond_op1);
+ continue;
+ }
+
tree inverted = invert_truthvalue (cond);
vec<cond_equivalence> p;
p.create (3);
@@ -10605,9 +10657,6 @@ vrp_dom_walker::before_dom_children (basic_block bb)
for (unsigned int i = 0; i < p.length (); i++)
m_avail_exprs_stack->record_cond (&p[i]);
- tree lhs = gimple_assign_lhs (stmt);
- m_const_and_copies->record_const_or_copy (lhs,
- TREE_OPERAND (rhs1, 0));
p.release ();
continue;
}