re PR tree-optimization/78496 (Missed opportunities for jump threading)
authorJeff Law <law@redhat.com>
Sat, 6 May 2017 15:03:40 +0000 (09:03 -0600)
committerJeff Law <law@gcc.gnu.org>
Sat, 6 May 2017 15:03:40 +0000 (09:03 -0600)
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.

PR tree-optimization/78496
* gcc.dg/tree-ssa/ssa-thread-16.c: New test.
* gcc.dg/tree-ssa/ssa-thread-17.c: New test.

From-SVN: r247721

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-16.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-17.c [new file with mode: 0644]
gcc/tree-vrp.c

index b0c253b09aea0c496a51b4220ff2a91016858a62..0f78f2a2ed1e6132bc6184474d3a27624b7413be 100644 (file)
@@ -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.
index fca5b87e7983c09dc6bc3e4f297dccbad9f6d5c1..42782a6d17c6f10352a58e221b034d5e33331b5e 100644 (file)
@@ -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 (file)
index 0000000..78c349c
--- /dev/null
@@ -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 (file)
index 0000000..692658f
--- /dev/null
@@ -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 ();
+}
index cf50e908257c00bd9ecd5f1274cdaf5fa0896949..461a48f5c9c734bd674319cb220a3256ead57f99 100644 (file)
@@ -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;
        }