]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Make sure to cost bb[0], work around unreachable predicates
authorRichard Biener <rguenther@suse.de>
Wed, 18 May 2022 09:57:10 +0000 (11:57 +0200)
committerRichard Biener <rguenther@suse.de>
Wed, 18 May 2022 09:57:10 +0000 (11:57 +0200)
This applies a workaround to avoid unswitching on predicates from
BBs that are considered unreachable and to that effect makes sure
to always cost bb[0] which we always put on the worklist as reachable.

gcc/tree-ssa-loop-unswitch.cc

index c5d3762e867851db649ed257d4bd1bc1658c8d87..d5ec23e276dda8ff6489908bcaa392708293c3ba 100644 (file)
@@ -793,9 +793,11 @@ evaluate_insns (class loop *loop, basic_block *bbs,
                int reachable_flag, int ignored_edge_flag)
 {
   auto_vec<basic_block> worklist (loop->num_nodes);
-  worklist.quick_push (bbs[0]);
   hash_set<edge> ignored_edges;
 
+  bbs[0]->flags |= reachable_flag;
+  worklist.quick_push (bbs[0]);
+
   while (!worklist.is_empty ())
     {
       edge e;
@@ -804,10 +806,7 @@ evaluate_insns (class loop *loop, basic_block *bbs,
       basic_block bb = worklist.pop ();
 
       gimple *last = last_stmt (bb);
-      gcond *cond = last != NULL ? dyn_cast<gcond *> (last) : NULL;
-      gswitch *swtch = last != NULL ? dyn_cast<gswitch *> (last) : NULL;
-
-      if (cond != NULL)
+      if (gcond *cond = safe_dyn_cast <gcond *> (last))
        {
          if (gimple_cond_true_p (cond))
            flags = EDGE_FALSE_VALUE;
@@ -824,11 +823,11 @@ evaluate_insns (class loop *loop, basic_block *bbs,
                         ? EDGE_FALSE_VALUE : EDGE_TRUE_VALUE);
            }
        }
-      else if (swtch != NULL
-              && !get_predicates_for_bb (bb).is_empty ())
-       evaluate_control_stmt_using_entry_checks (swtch, predicate_path,
-                                                 ignored_edge_flag,
-                                                 &ignored_edges);
+      else if (gswitch *swtch = safe_dyn_cast<gswitch *> (last))
+       if (!get_predicates_for_bb (bb).is_empty ())
+         evaluate_control_stmt_using_entry_checks (swtch, predicate_path,
+                                                   ignored_edge_flag,
+                                                   &ignored_edges);
 
       /* ???  We fail to account for removed condition or switch stmts.  */
 
@@ -909,6 +908,9 @@ tree_unswitch_single_loop (class loop *loop, dump_user_location_t loc,
 
   for (unsigned i = 0; i < loop->num_nodes; i++)
     {
+      /* ???  The caller computed reachability of blocks when
+        evaluating costs but we are still processing predicates
+        on unreachable ones.  */
       for (auto pred : get_predicates_for_bb (bbs[i]))
        {
          if (bitmap_bit_p (handled, pred->num))
@@ -917,8 +919,13 @@ tree_unswitch_single_loop (class loop *loop, dump_user_location_t loc,
          evaluate_loop_insns_for_predicate (loop, bbs, predicate_path,
                                             pred, ignored_edge_flag,
                                             &true_size, &false_size);
+
          gcc_assert (true_size + false_size >= loop_size);
 
+         /* When the block was unreachable the predicate has no effect.  */
+         if (true_size == loop_size && false_size == loop_size)
+           continue;
+
          /* FIXME: right now we select first candidate, but we can choose
             the cheapest or hottest one.  */
          if (true_size + false_size < budget + loop_size)