I have two functions which both check if an input char is a number (along other characters), but they do it in different ways:
foo_precheck(char c)first checks if the ascii code of char is in a certain range which denotes a number.foo_switch(char c)uses a jumptable with fallthrough cases from 0-9 to determine that a char is a number.
The question now is: which function is faster? I was curious if this would optimize to the same assembly under -O2, but it didn't:
#include <cstdio>
void foo_precheck(char c)
{
if (c >= 0x30 && c <= 0x39) {
printf("Was a number!\n");
return ;
}
switch(c) {
case '{':
case '[': {
printf("Other stuff!\n");
break;
}
default: break;
}
}
void foo_switch(char c)
{
switch(c) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9': {
printf("Was a number!\n");
break;
}
case '{':
case '[': {
printf("Other stuff!\n");
break;
}
default: break;
}
}
const volatile char r = '5';
int main()
{
foo_precheck(r);
foo_switch(r);
}
This is the assembly generated for each function (clang -O2):
foo_precheck(char): # @foo_precheck(char)
lea eax, [rdi - 48]
cmp al, 10
jae .LBB0_2
lea rdi, [rip + .Lstr.4]
jmp puts@PLT # TAILCALL
.LBB0_2:
movsx eax, dil
or eax, 32
cmp eax, 123
jne .LBB0_5
lea rdi, [rip + .Lstr.3]
jmp puts@PLT # TAILCALL
.LBB0_5:
ret
foo_switch(char): # @foo_switch(char)
lea eax, [rdi - 48]
cmp eax, 10
jae .LBB1_2
lea rdi, [rip + .Lstr.4]
jmp puts@PLT # TAILCALL
.LBB1_2:
cmp edi, 123
je .LBB1_4
cmp edi, 91
jne .LBB1_6
.LBB1_4:
lea rdi, [rip + .Lstr.3]
jmp puts@PLT # TAILCALL
.LBB1_6:
ret
Can you make a general estimate which one is faster? I know it is architecture dependent, but the fact that it doesn't generate the same assembly made me curious if you make a general statement on what I should go for.