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! :-)

Reply via email to