The test case for PR81564 exposes an issue where the case labels for a
switch statement point to blocks that have already been removed by an
earlier call to cleanup_tree_cfg().  In that case, the code in
group_case_labels_stmt() that does:

  base_bb = label_to_block (CASE_LABEL (base_case));

...returns a NULL base_bb and we SEGV later on when we dereference it:

  if (EDGE_COUNT (base_bb->succs) == 0
      ...

The fix here is to just treat case labels that point to blocks that have
already been deleted similarly to case labels that point to the default
case statement, by removing them.

This passed bootstrap and regtesting on powerpc64le-linux with no regressions.
Ok for trunk?

Peter

gcc/
        PR middle-end/81564
        * tree-cfg.c (group_case_labels_stmt): Handle already deleted blocks.

gcc/testsuite/
        PR middle-end/81564
        * gcc.dg/pr81564.c: New test.

Index: gcc/tree-cfg.c
===================================================================
--- gcc/tree-cfg.c      (revision 250581)
+++ gcc/tree-cfg.c      (working copy)
@@ -1701,8 +1701,9 @@ group_case_labels_stmt (gswitch *stmt)
       gcc_assert (base_case);
       base_bb = label_to_block (CASE_LABEL (base_case));
 
-      /* Discard cases that have the same destination as the default case.  */
-      if (base_bb == default_bb)
+      /* Discard cases that have the same destination as the default case or
+        whose destination blocks have already been removed as unreachable.  */
+      if (base_bb == NULL || base_bb == default_bb)
        {
          i++;
          continue;
Index: gcc/testsuite/gcc.dg/pr81564.c
===================================================================
--- gcc/testsuite/gcc.dg/pr81564.c      (nonexistent)
+++ gcc/testsuite/gcc.dg/pr81564.c      (working copy)
@@ -0,0 +1,21 @@
+/* PR middle-end/81564 ICE in group_case_labels_stmt().  */
+/* { dg-do compile }  */
+/* { dg-options "-O2" }  */
+
+struct a {
+    int b;
+    int c;
+};
+
+void
+foo (void)
+{
+  struct a *e;
+  switch (e->c)
+  {
+    case 7:
+    case 3:
+      if (__builtin_expect(!0, 0))
+       __builtin_unreachable();
+  }
+}

Reply via email to