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