On 6/29/17 8:58 AM, Richard Biener wrote:
> On Thu, 29 Jun 2017, Peter Bergner wrote:
> 
>> On 6/29/17 4:03 AM, Richard Biener wrote:
>>>
>>> This refactors things a bit to make CFG cleanup handle switches with
>>> just a default label.  If we make sure to cleanup the CFG after
>>> group_case_labels removes cases with just __builtin_unreachable ()
>>> inside then this fixes the ICE seen in PR81994 as well.
>>>
>>> I wonder if find_taken_edge should generally handle successors
>>> with __builtin_unreachable () -- OTOH that would get rid of those
>>> too early I guess.
>>
>> Should we offer an early out of group_case_labels_stmt() for the
>> fairly common case of new_size == old_size?  There's no reason to
>> execute the compress labels loop if we didn't combine any of the
>> labels.
> 
> We can also merge both loops, counting new_size upwards, storing
> to label new_size if new_size != i ...

Like this.  I'm bootstrapping and regtesting the following patch on
powerpc64le-linux.  Ok if it survives?

Peter

        * tree-cfg.c (group_case_labels_stmt): Merge scanning and compressing
        loops.  Remove now unneeded calls to gimple_switch_set_label() that
        just set removed labels to NULL_TREE.

Index: gcc/tree-cfg.c
===================================================================
--- gcc/tree-cfg.c      (revision 249801)
+++ gcc/tree-cfg.c      (working copy)
@@ -1679,13 +1679,13 @@ bool
 group_case_labels_stmt (gswitch *stmt)
 {
   int old_size = gimple_switch_num_labels (stmt);
-  int i, j, base_index, new_size = old_size;
+  int i, next_index, new_size;
   basic_block default_bb = NULL;

   default_bb = label_to_block (CASE_LABEL (gimple_switch_default_label 
(stmt)));

   /* Look for possible opportunities to merge cases.  */
-  i = 1;
+  new_size = i = 1;
   while (i < old_size)
     {
       tree base_case, base_high;
@@ -1699,23 +1699,21 @@ group_case_labels_stmt (gswitch *stmt)
       /* Discard cases that have the same destination as the default case.  */
       if (base_bb == default_bb)
        {
-         gimple_switch_set_label (stmt, i, NULL_TREE);
          i++;
-         new_size--;
          continue;
        }

       base_high = CASE_HIGH (base_case)
          ? CASE_HIGH (base_case)
          : CASE_LOW (base_case);
-      base_index = i++;
+      next_index = i + 1;

       /* Try to merge case labels.  Break out when we reach the end
         of the label vector or when we cannot merge the next case
         label with the current one.  */
-      while (i < old_size)
+      while (next_index < old_size)
        {
-         tree merge_case = gimple_switch_label (stmt, i);
+         tree merge_case = gimple_switch_label (stmt, next_index);
          basic_block merge_bb = label_to_block (CASE_LABEL (merge_case));
          wide_int bhp1 = wi::add (base_high, 1);

@@ -1727,9 +1725,7 @@ group_case_labels_stmt (gswitch *stmt)
              base_high = CASE_HIGH (merge_case) ?
                  CASE_HIGH (merge_case) : CASE_LOW (merge_case);
              CASE_HIGH (base_case) = base_high;
-             gimple_switch_set_label (stmt, i, NULL_TREE);
-             new_size--;
-             i++;
+             next_index++;
            }
          else
            break;
@@ -1742,23 +1738,22 @@ group_case_labels_stmt (gswitch *stmt)
          edge base_edge = find_edge (gimple_bb (stmt), base_bb);
          if (base_edge != NULL)
            remove_edge_and_dominated_blocks (base_edge);
-         gimple_switch_set_label (stmt, base_index, NULL_TREE);
-         new_size--;
+         i = next_index;
+         continue;
        }
-    }

-  /* Compress the case labels in the label vector, and adjust the
-     length of the vector.  */
-  for (i = 0, j = 0; i < new_size; i++)
-    {
-      while (! gimple_switch_label (stmt, j))
-       j++;
-      gimple_switch_set_label (stmt, i,
-                              gimple_switch_label (stmt, j++));
+      if (new_size < i)
+       gimple_switch_set_label (stmt, new_size,
+                                gimple_switch_label (stmt, i));
+      i = next_index;
+      new_size++;
     }

   gcc_assert (new_size <= old_size);
-  gimple_switch_set_num_labels (stmt, new_size);
+
+  if (new_size < old_size)
+    gimple_switch_set_num_labels (stmt, new_size);
+
   return new_size < old_size;
 }


Reply via email to