A check was missing for is-single when contracting, so if a
multi-successor node that was not a condition node (e.g. a switch) a
random edge would be picked and contracted into.
---
 gcc/testsuite/gcc.misc-tests/gcov-23.c | 48 ++++++++++++++++++++++++++
 gcc/tree-profile.cc                    |  4 +++
 2 files changed, 52 insertions(+)

diff --git a/gcc/testsuite/gcc.misc-tests/gcov-23.c 
b/gcc/testsuite/gcc.misc-tests/gcov-23.c
index c4afc5e700d..856e97f5088 100644
--- a/gcc/testsuite/gcc.misc-tests/gcov-23.c
+++ b/gcc/testsuite/gcc.misc-tests/gcov-23.c
@@ -3,6 +3,7 @@
 int id (int);
 int idp (int *);
 int err;
+char c;
 
 /* This becomes problematic only under optimization for the case when the
    compiler cannot inline the function but have to generate a call.  It is not
@@ -72,4 +73,51 @@ exit:
     return a;
 }
 
+/* Adapted from icu4c-73.1 common/ucase.cpp ucase_getLocaleCase ().  */
+int
+mcdc003 (const char *locale)
+{
+    /* extern, so its effect won't be optimized out.  */
+    c = *locale++;
+    if (c == 'z') /* conditions(0/2) true(0) false(0) */
+                 /* conditions(end) */
+    {
+       return 1;
+    }
+    else if (c >= 'a') /* conditions(0/2) true(0) false(0) */
+                     /* conditions(end) */
+    {
+       if (id (c)) /* conditions(0/2) true(0) false(0) */
+                   /* conditions(end) */
+           c = *locale++;
+    }
+    else
+    {
+       if (c == 'T')
+       {
+           if (id (c)) /* conditions(0/2) true(0) false(0) */
+                       /* conditions(end) */
+               c = *locale++;
+           if (id (c)) /* conditions(0/2) true(0) false(0) */
+                       /* conditions(end) */
+               c = *locale++;
+       }
+       else if (c == 'L')
+           c = *locale++;
+       else if (c == 'E')
+           c = *locale++;
+       else if (c == 'N')
+           c = *locale++;
+       else if (c == 'H')
+       {
+           c = *locale++;
+           if (id (c)) /* conditions(0/2) true(0) false(0) */
+                       /* conditions(end) */
+               c = *locale++;
+       }
+    }
+
+    return 1;
+}
+
 /* { dg-final { run-gcov conditions { --conditions gcov-23.c } } } */
diff --git a/gcc/tree-profile.cc b/gcc/tree-profile.cc
index 26e1924d444..ce679130ca0 100644
--- a/gcc/tree-profile.cc
+++ b/gcc/tree-profile.cc
@@ -297,6 +297,10 @@ contract_edge (edge e, sbitmap G = nullptr)
            return source;
        if (block_conditional_p (dest))
            return e;
+       /* This happens for switches, and must be checked after the 
is-conditional
+          (which is also not single).  */
+       if (!single (dest->succs))
+           return source;
 
        if (G)
            bitmap_set_bit (G, dest->index);
-- 
2.30.2

Reply via email to