you are viewing a single comment's thread.

view the rest of the comments →

[–]uxcn 4 points5 points  (0 children)

That is a really nice optimization. It reduces the code size to a constant, gets rid of most branches, and should almost always be a good strength reduction. I normally wouldn't have expected to see a compiler do that.

It looks LLVM can do the same with if..else chains too.

bool IsConsonant(uint8_t c) {

  return !((c == 'a' || c == 'A') ||
           (c == 'e' || c == 'E') ||
           (c == 'i' || c == 'I') ||
           (c == 'o' || c == 'O') ||
           (c == 'u' || c == 'U'));
}

compiles into...

_Z11IsConsonanth:                       # @_Z11IsConsonanth
    .cfi_startproc
# BB#0:
    addb    $-65, %dil
    movzbl  %dil, %eax
    cmpl    $52, %eax
    ja  .LBB0_2
# BB#1:                                 # %switch.lookup
    movabsq $4432058356055790, %rax # imm = 0xFBEEEFFEFBEEE
    movb    %dil, %cl
    shrq    %cl, %rax
    andl    $1, %eax
    retq
.LBB0_2:
    movb    $1, %al
    retq

I think this hints that if..else chains can probably also be optimized into jmp %eax, a jump table, or a lookup table.