diff options
author | Benjamin Kramer <benny.kra@googlemail.com> | 2015-03-21 21:09:33 +0000 |
---|---|---|
committer | Benjamin Kramer <benny.kra@googlemail.com> | 2015-03-21 21:09:33 +0000 |
commit | 7857d723f11a3a5c732c2e08d332ebca13e075ba (patch) | |
tree | c2049605e055721a92f7a1c4f17ed00f7e160770 /clang/lib/Basic/VersionTuple.cpp | |
parent | da5ece8e35d0b54fa3faa051b37c4adef0c34746 (diff) | |
download | llvm-7857d723f11a3a5c732c2e08d332ebca13e075ba.zip llvm-7857d723f11a3a5c732c2e08d332ebca13e075ba.tar.gz llvm-7857d723f11a3a5c732c2e08d332ebca13e075ba.tar.bz2 |
[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.
llvm-svn: 232902
Diffstat (limited to 'clang/lib/Basic/VersionTuple.cpp')
0 files changed, 0 insertions, 0 deletions