https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82527
Bug ID: 82527 Summary: Branch probabilities does not match on optimized switch cases Product: gcc Version: unknown Status: UNCONFIRMED Severity: normal Priority: P3 Component: gcov-profile Assignee: unassigned at gcc dot gnu.org Reporter: eDeviser at mailbox dot org CC: marxin at gcc dot gnu.org Target Milestone: --- Having a switch case with an empty case as shown below, causes a wrong branch report: #include <stdio.h> int main() { for (int i = 0; i < 100; i++) { switch (i) { case 0: printf("0"); break; case 9999: break; default: printf("d"); break; } } return 0; } Compile it, execute it and generate the *.gcov file: gcc main.c -O3 -fprofile-arcs -ftest-coverage && ./a.out && gcov -bc main.c && cat main.c.gcov Take a look to the report: -: 0:Source:main.c -: 0:Graph:main.gcno -: 0:Data:main.gcda -: 0:Runs:1 -: 0:Programs:1 -: 1:#include <stdio.h> function main called 1 returned 100% blocks executed 100% 1: 2: int main() { 101: 3: for (int i = 0; i < 100; i++) { branch 0 taken 100 branch 1 taken 1 (fallthrough) 100: 4: switch (i) { branch 0 taken 1 branch 1 taken 99 branch 2 taken 0 -: 5: case 0: -: 6: printf("0"); -: 7: break; -: 8: case 9999: -: 9: break; -: 10: default: -: 11: printf("d"); -: 12: break; -: 13: } -: 14: } -: 15: return 0; -: 16: } Doing the same thing again but with `-O0` instead of `-O3` shows this report: -: 0:Source:main.c -: 0:Graph:main.gcno -: 0:Data:main.gcda -: 0:Runs:1 -: 0:Programs:1 -: 1:#include <stdio.h> function main called 1 returned 100% blocks executed 91% 1: 2: int main() { 101: 3: for (int i = 0; i < 100; i++) { branch 0 taken 100 branch 1 taken 1 (fallthrough) 100: 4: switch (i) { branch 0 taken 1 branch 1 taken 0 branch 2 taken 99 -: 5: case 0: 1: 6: printf("0"); call 0 returned 1 1: 7: break; -: 8: case 9999: #####: 9: break; -: 10: default: 99: 11: printf("d"); call 0 returned 99 99: 12: break; -: 13: } -: 14: } 1: 15: return 0; -: 16: } The coverage report says, that the switch case has three branches. Thats right. The first branch is the `case 0`, the second one is the `case 999` and the last one is the `default`. But the optimized report looks really wrong. Lets put both branch reports next to each other to see the problem: CASE | WITH -O0 | WITH -O3 ==========|======================|===================== case 0 | branch 0 taken 1 | branch 0 taken 1 case 9999 | branch 1 taken 0 | branch 1 taken 99 default | branch 2 taken 99 | branch 2 taken 0 This is an idea what the bug is about: For me it the optimized version seems to remove the 9999 case because it is empty. So Branch 1 with -O3 is the case default and Branch 2 with -O3 is not existent and must not be shown in the report. I hope the thing is clear. If not feel free to ask! :-)