re PR tree-optimization/58946 (internal compiler error: in operator[], at vec.h:722)
authorJakub Jelinek <jakub@redhat.com>
Mon, 4 Nov 2013 10:29:42 +0000 (11:29 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Mon, 4 Nov 2013 10:29:42 +0000 (11:29 +0100)
PR tree-optimization/58946
* tree-ssa-reassoc.c (maybe_optimize_range_tests): Update all
bbs with bbinfo[idx].op != NULL before all blocks with
bbinfo[idx].op == NULL.

* gcc.c-torture/compile/pr58946.c: New test.

From-SVN: r204348

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/compile/pr58946.c [new file with mode: 0644]
gcc/tree-ssa-reassoc.c

index b02cf8af5aa87d7bd5ebc8e7cdaa228e24137898..7306064b140ec24e32ea4d514ec278e2622cea90 100644 (file)
@@ -1,3 +1,10 @@
+2013-11-04  Jakub Jelinek  <jakub@redhat.com>
+
+       PR tree-optimization/58946
+       * tree-ssa-reassoc.c (maybe_optimize_range_tests): Update all
+       bbs with bbinfo[idx].op != NULL before all blocks with
+       bbinfo[idx].op == NULL.
+
 2013-11-04  Richard Sandiford  <rdsandiford@googlemail.com>
 
        * config/avr/avr-log.c (avr_double_int_pop_digit): Delete.
index 19e5c3803fc73de3f68e05594d37445485deb7b6..ad988239b381512699c7bab9b2ab28c17200bab5 100644 (file)
@@ -1,3 +1,8 @@
+2013-11-04  Jakub Jelinek  <jakub@redhat.com>
+
+       PR tree-optimization/58946
+       * gcc.c-torture/compile/pr58946.c: New test.
+
 2013-11-03  Paolo Carlini  <paolo.carlini@oracle.com>
 
        PR c++/52071
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr58946.c b/gcc/testsuite/gcc.c-torture/compile/pr58946.c
new file mode 100644 (file)
index 0000000..0ec5eba
--- /dev/null
@@ -0,0 +1,20 @@
+/* PR tree-optimization/58946 */
+
+int
+foo (unsigned int c)
+{
+  unsigned int d, e, f;
+  if ((int) c < 0)
+    d = 0;
+  else
+    d = c;
+  if (d == 0)
+    e = __INT_MAX__ + 1U;
+  else
+    e = d;
+  if ((int) e < 0)
+    f = 0;
+  else
+    f = e;
+  return f;
+}
index 39982f1a8d33bf2963163454147f752df7c330bb..538a8ef0e4a25e874b97ff9dc1f772544b2f3b53 100644 (file)
@@ -2657,6 +2657,7 @@ maybe_optimize_range_tests (gimple stmt)
   edge e;
   vec<operand_entry_t> ops = vNULL;
   vec<inter_bb_range_test_entry> bbinfo = vNULL;
+  bool any_changes = false;
 
   /* Consider only basic blocks that end with GIMPLE_COND or
      a cast statement satisfying final_range_test_p.  All
@@ -2870,41 +2871,31 @@ maybe_optimize_range_tests (gimple stmt)
        break;
     }
   if (ops.length () > 1)
+    any_changes = optimize_range_tests (ERROR_MARK, &ops);
+  if (any_changes)
     {
       unsigned int idx;
-      bool any_changes = optimize_range_tests (ERROR_MARK, &ops);
-      for (bb = last_bb, idx = 0; any_changes; bb = single_pred (bb), idx++)
+      /* 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
+        from the single imm use and check the predicate already before
+        making those changes.
+        On the other side, the handling of GIMPLE_COND directly can turn
+        previously multiply used SSA_NAMEs into single use SSA_NAMEs, so
+        it needs to be done in a separate loop afterwards.  */
+      for (bb = last_bb, idx = 0; ; bb = single_pred (bb), idx++)
        {
-         if (bbinfo[idx].first_idx < bbinfo[idx].last_idx)
+         if (bbinfo[idx].first_idx < bbinfo[idx].last_idx
+             && bbinfo[idx].op != NULL_TREE)
            {
-             gimple stmt = last_stmt (bb);
              tree new_op;
 
-             if (bbinfo[idx].op == NULL_TREE)
-               {
-                 if (ops[bbinfo[idx].first_idx]->op != NULL_TREE)
-                   {
-                     if (integer_zerop (ops[bbinfo[idx].first_idx]->op))
-                       gimple_cond_make_false (stmt);
-                     else if (integer_onep (ops[bbinfo[idx].first_idx]->op))
-                       gimple_cond_make_true (stmt);
-                     else
-                       {
-                         gimple_cond_set_code (stmt, NE_EXPR);
-                         gimple_cond_set_lhs (stmt,
-                                              ops[bbinfo[idx].first_idx]->op);
-                         gimple_cond_set_rhs (stmt, boolean_false_node);
-                       }
-                     update_stmt (stmt);
-                   }
-                 bbinfo[idx].op = new_op = boolean_false_node;
-               }
-             else
-               new_op = update_ops (bbinfo[idx].op,
-                                    (enum tree_code)
-                                    ops[bbinfo[idx].first_idx]->rank,
-                                    ops, &bbinfo[idx].first_idx,
-                                    loop_containing_stmt (stmt));
+             stmt = last_stmt (bb);
+             new_op = update_ops (bbinfo[idx].op,
+                                  (enum tree_code)
+                                  ops[bbinfo[idx].first_idx]->rank,
+                                  ops, &bbinfo[idx].first_idx,
+                                  loop_containing_stmt (stmt));
              if (new_op == NULL_TREE)
                {
                  gcc_assert (bb == last_bb);
@@ -2956,6 +2947,28 @@ maybe_optimize_range_tests (gimple stmt)
          if (bb == first_bb)
            break;
        }
+      for (bb = last_bb, idx = 0; ; bb = single_pred (bb), idx++)
+       {
+         if (bbinfo[idx].first_idx < bbinfo[idx].last_idx
+             && bbinfo[idx].op == NULL_TREE
+             && ops[bbinfo[idx].first_idx]->op != NULL_TREE)
+           {
+             stmt = last_stmt (bb);
+             if (integer_zerop (ops[bbinfo[idx].first_idx]->op))
+               gimple_cond_make_false (stmt);
+             else if (integer_onep (ops[bbinfo[idx].first_idx]->op))
+               gimple_cond_make_true (stmt);
+             else
+               {
+                 gimple_cond_set_code (stmt, NE_EXPR);
+                 gimple_cond_set_lhs (stmt, ops[bbinfo[idx].first_idx]->op);
+                 gimple_cond_set_rhs (stmt, boolean_false_node);
+               }
+             update_stmt (stmt);
+           }
+         if (bb == first_bb)
+           break;
+       }
     }
   bbinfo.release ();
   ops.release ();