https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109637

            Bug ID: 109637
           Summary: unnecessary range check in complete switch on bitfield
           Product: gcc
           Version: 13.1.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: middle-end
          Assignee: unassigned at gcc dot gnu.org
          Reporter: mattiase at acm dot org
  Target Milestone: ---

This fully populated switch still produces some kind of useless range check:

struct S { unsigned x : 2; };
int f (struct S *s) {
    switch(s->x) {
        case 0: return 0;
        case 1: return 1;
        case 2: return 2;
        case 3: return 3;
    }
}

->
        movzbl  (%rdi), %eax
        andl    $3, %eax
        leal    -1(%rax), %edx
        movzbl  %al, %eax
        cmpb    $3, %dl
        movl    $0, %edx
        cmovnb  %edx, %eax
        ret

GCC apparently understands that the switch is complete at some level since
anything after the switch is recognised as dead code, so the range check is a
bit puzzling.

The code is fine if we explicitly mask the switch value as in `switch(s->x &
3)`:

        movzbl  (%rdi), %eax
        andl    $3, %eax
        ret

Reply via email to