[llvm-commits] PATCH: replace if-chain in AsmParser's directive parsing code
Eli Bendersky
eliben at google.com
Tue Dec 18 14:05:53 PST 2012
>> AsmParser has a couple of if-chains when parsing directives. The
>> attached patch replaces the if-chains with enum+switch. No change in
>> functionality.
>>
>> Unfortunately I didn't measure any significant speedups for the whole
>> llvm-mc (only 1-2%), so I'll do more fine-grained measurements once I
>> get the opportunity.
>>
>> Also, I should add that in general AsmParser's parsing code can be
>> cleaned up even more (for example w.r.t. the extensions registersing
>> directive parsers, which can be unified with other directive parsing
>> code). So this patch should just be seen as a first step in a
>> (hopefully) right direction.
>
> Just MHO, but this makes the code more complex and hopefully won't provide a speedup.
> We generally expect that:
>
> StringRef X = …
>
> if (X == "foo")
> return ...
> if (x == "bar")
> return …
>
> to be turned into a switch on X[0].
>
I may be missing something, but this code:
int main(int argc, char** argv) {
StringRef r(argv[1]);
if (r == "something")
return 17;
if (r == "foo")
return 31;
if (r == "bar")
return 71;
if (r == "baz")
return 97;
return 0;
}
When compiled with 'clang -O3' (Clang 3.2) does not produce a jump
table, but a chain of tests and jumps as usual from an if-chain (**).
I tried several variations (else-ifs...), and the result is similar.
By the way, this is also what GCC does (and I suspect that many
developers have their LLVM compiled with GCC).
Perhaps I am missing something?
Besides, the actual pattern in AsmParser is not a pure "if X return Y"
chain. Some "then" statements don't return, and some conditions are
logical ANDs of several tests, and so on. So detecting a clean switch
pattern could be difficult.
> Just MHO, but this makes the code more complex and hopefully won't provide a speedup.
To address the "more complex" point. Whimsically, it would be hard to
make that code path in AsmParser more complex ;-) But seriously, a
longer-term plan would be to combine this lookup table with another
that already exists in the same function - DirectiveMap, which is used
for assembler extensions registering themselves on certain directives.
My thinking was to first get the general if-chain removal approved,
and then try to fuse the two lookup tables to attain some level of
consistency in the code. IMHO the end result would be much cleaner and
more readable than what it has now.
(**) Methodology:
$ ~/llvm/3.2rc2/bin/clang++ -fno-rtti -O3 stringref_switch.cpp
`~/llvm/3.2rc2/bin/llvm-config --cxxflags --libs`
`~/llvm/3.2rc2/bin/llvm-config --ldflags` -o stringref_switch
Followed by objdump -d. Here's a typical piece of assembly output:
4005c0: 53 push %rbx
4005c1: 48 8b 5e 08 mov 0x8(%rsi),%rbx
4005c5: 48 89 df mov %rbx,%rdi
4005c8: e8 e3 fe ff ff callq 4004b0 <strlen at plt>
4005cd: 48 89 c1 mov %rax,%rcx
4005d0: 48 83 f9 03 cmp $0x3,%rcx
4005d4: 75 60 jne 400636 <main+0x76>
4005d6: 48 8d 35 89 01 00 00 lea 0x189(%rip),%rsi
# 400766 <_IO_stdin_used+0xe>
4005dd: 48 89 df mov %rbx,%rdi
4005e0: 48 89 ca mov %rcx,%rdx
4005e3: e8 d8 fe ff ff callq 4004c0 <memcmp at plt>
4005e8: 89 c1 mov %eax,%ecx
4005ea: b8 1f 00 00 00 mov $0x1f,%eax
4005ef: 85 c9 test %ecx,%ecx
4005f1: 74 6f je 400662 <main+0xa2>
4005f3: 48 8d 35 70 01 00 00 lea 0x170(%rip),%rsi
# 40076a <_IO_stdin_used+0x12>
4005fa: 48 89 df mov %rbx,%rdi
4005fd: ba 03 00 00 00 mov $0x3,%edx
400602: e8 b9 fe ff ff callq 4004c0 <memcmp at plt>
400607: 89 c1 mov %eax,%ecx
400609: b8 47 00 00 00 mov $0x47,%eax
40060e: 85 c9 test %ecx,%ecx
400610: 74 50 je 400662 <main+0xa2>
400612: 48 8d 35 55 01 00 00 lea 0x155(%rip),%rsi
# 40076e <_IO_stdin_used+0x16>
400619: 48 89 df mov %rbx,%rdi
40061c: ba 03 00 00 00 mov $0x3,%edx
400621: e8 9a fe ff ff callq 4004c0 <memcmp at plt>
400626: 89 c1 mov %eax,%ecx
400628: ba 61 00 00 00 mov $0x61,%edx
40062d: 31 c0 xor %eax,%eax
I do notice that the compiler tries to be smart about the length of
the string, but for strings of the same length it has no choice but
sequentially "memcmp" them. Note that the vast majority of assembly
directives fall into very few bins in terms of string length.
Eli
More information about the llvm-commits
mailing list