Hi!

As mentioned in the PR, maybe_optimize_range_tests considers basic blocks
with not just the final GIMPLE_COND (or for last_bb store feeding into PHI),
but also assign stmts that don't trap, don't have side-effects and where
the SSA_NAMEs they set are used only in their own bb.
Now, if we decide to optimize some range test, we can change some conditions
on previous bbs and that means we could execute some basic blocks that
wouldn't be executed in the original program.  As the stmts don't set
anything used in other bbs, they are most likely dead after the
optimization, but the problem on the testcase is that because of the
condition changes in previous bb we end up with incorrect value range
for some SSA_NAME(s).  That can result in the miscompilation of the testcase
on certain targets.

Fixed by resetting the value range info of such SSA_NAMEs.  I believe it
shouldn't be a big deal, they will be mostly dead anyway.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2015-12-03  Jakub Jelinek  <ja...@redhat.com>

        PR tree-optimization/68671
        * tree-ssa-reassoc.c (maybe_optimize_range_tests): For basic
        blocks starting with the successor of first bb we've modified
        and ending with last_bb, reset value ranges of all integral
        SSA_NAMEs set in those basic blocks.

        * gcc.dg/pr68671.c: New test.

--- gcc/tree-ssa-reassoc.c.jj   2015-11-18 11:22:51.000000000 +0100
+++ gcc/tree-ssa-reassoc.c      2015-12-03 18:12:08.915210122 +0100
@@ -3204,7 +3204,7 @@ maybe_optimize_range_tests (gimple *stmt
     any_changes = optimize_range_tests (ERROR_MARK, &ops);
   if (any_changes)
     {
-      unsigned int idx;
+      unsigned int idx, max_idx = 0;
       /* update_ops relies on has_single_use predicates returning the
         same values as it did during get_ops earlier.  Additionally it
         never removes statements, only adds new ones and it should walk
@@ -3220,6 +3220,7 @@ maybe_optimize_range_tests (gimple *stmt
            {
              tree new_op;
 
+             max_idx = idx;
              stmt = last_stmt (bb);
              new_op = update_ops (bbinfo[idx].op,
                                   (enum tree_code)
@@ -3289,6 +3290,10 @@ maybe_optimize_range_tests (gimple *stmt
              && ops[bbinfo[idx].first_idx]->op != NULL_TREE)
            {
              gcond *cond_stmt = as_a <gcond *> (last_stmt (bb));
+
+             if (idx > max_idx)
+               max_idx = idx;
+
              if (integer_zerop (ops[bbinfo[idx].first_idx]->op))
                gimple_cond_make_false (cond_stmt);
              else if (integer_onep (ops[bbinfo[idx].first_idx]->op))
@@ -3305,6 +3310,30 @@ maybe_optimize_range_tests (gimple *stmt
          if (bb == first_bb)
            break;
        }
+
+      /* The above changes could result in basic blocks after the first
+        modified one, up to and including last_bb, to be executed even if
+        they would not be in the original program.  If the value ranges of
+        assignment lhs' in those bbs were dependent on the conditions
+        guarding those basic blocks which now can change, the VRs might
+        be incorrect.  As no_side_effect_bb should ensure those SSA_NAMEs
+        are only used within the same bb, it should be not a big deal if
+        we just reset all the VRs in those bbs.  See PR68671.  */
+      for (bb = last_bb, idx = 0; idx < max_idx; bb = single_pred (bb), idx++)
+       {
+         gimple_stmt_iterator gsi;
+         for (gsi = gsi_last_bb (bb); !gsi_end_p (gsi); gsi_prev (&gsi))
+           {
+             gimple *g = gsi_stmt (gsi);
+             if (!is_gimple_assign (g))
+               continue;
+             tree lhs = gimple_assign_lhs (g);
+             if (TREE_CODE (lhs) != SSA_NAME)
+               continue;
+             if (INTEGRAL_TYPE_P (TREE_TYPE (lhs)))
+               SSA_NAME_RANGE_INFO (lhs) = NULL;
+           }
+       }
     }
 }
 
--- gcc/testsuite/gcc.dg/pr68671.c.jj   2015-12-03 18:19:24.769104484 +0100
+++ gcc/testsuite/gcc.dg/pr68671.c      2015-12-03 18:19:07.000000000 +0100
@@ -0,0 +1,23 @@
+/* PR tree-optimization/68671 */
+/* { dg-do run } */
+/* { dg-options " -O2 -fno-tree-dce" } */
+
+volatile int a = -1;
+volatile int b;
+
+static inline int
+fn1 (signed char p1, int p2)
+{
+  return (p1 < 0) || (p1 > (1 >> p2)) ? 0 : (p1 << 1);
+}
+
+int
+main ()
+{
+  signed char c = a;
+  b = fn1 (c, 1);
+  c = ((128 | c) < 0 ? 1 : 0);
+  if (c != 1)
+    __builtin_abort ();
+  return 0;
+}

        Jakub

Reply via email to