[SimplifyLibCalls] Turn memchr(const, C, const) into a bitfield check.
authorBenjamin Kramer <benny.kra@googlemail.com>
Sat, 21 Mar 2015 21:09:33 +0000 (21:09 +0000)
committerBenjamin Kramer <benny.kra@googlemail.com>
Sat, 21 Mar 2015 21:09:33 +0000 (21:09 +0000)
commitfd48a80e144fdca6e5c7e6091942f70c2ea4ea8f
tree493785136baa1544685b59644b2f80da37aa9d94
parent2bb644f4692965e4aab98e446d17580cc8613520
[SimplifyLibCalls] Turn memchr(const, C, const) into a bitfield check.

strchr("123!", C) != nullptr is a common pattern to check if C is one
of 1, 2, 3 or !. If the largest element of the string is smaller than
the target's register size we can easily create a bitfield and just
do a simple test for set membership.

int foo(char C) { return strchr("123!", C) != nullptr; } now becomes

cmpl $64, %edi ## range check
sbbb %al, %al
movabsq $0xE000200000001, %rcx
btq %rdi, %rcx ## bit test
sbbb %cl, %cl
andb %al, %cl ## and the two conditions
andb $1, %cl
movzbl %cl, %eax ## returning an int
ret

(imho the backend should expand this into a series of branches, but
that's a different story)

The code is currently limited to bit fields that fit in a register, so
usually 64 or 32 bits. Sadly, this misses anything using alpha chars
or {}. This could be fixed by just emitting a i128 bit field, but that
can generate really ugly code so we have to find a better way. To some
degree this is also recreating switch lowering logic, but we can't
simply emit a switch instruction and thus change the CFG within
instcombine.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@232902 91177308-0d34-0410-b5e6-96231b3b80d8
lib/Target/README.txt
lib/Transforms/Utils/SimplifyLibCalls.cpp
test/Transforms/InstCombine/memchr.ll
test/Transforms/InstCombine/strchr-1.ll