pla*_*cel 16 c++ optimization performance x86 bit-manipulation
是否有任何聪明的位技巧来检测是否有少数整数(比如3或4)具有特定值?
直截了当
bool test(int a, int b, int c, int d)
{
// The compiler will pretty likely optimize it to (a == d | b == d | c == d)
return (a == d || b == d || c == d);
}
Run Code Online (Sandbox Code Playgroud)
test(int, int, int, int):
cmp ecx, esi
sete al
cmp ecx, edx
sete dl
or eax, edx
cmp edi, ecx
sete dl
or eax, edx
ret
Run Code Online (Sandbox Code Playgroud)
这些sete指令有较高的延迟比我要忍受,所以我宁愿用一些按位(&,|,^,~)的东西,比较单一.
我发现的唯一解决方案是:
int s1 = ((a-d) >> 31) | ((d-a) >> 31);
int s2 = ((b-d) >> 31) | ((d-b) >> 31);
int s3 = ((c-d) >> 31) | ((d-c) >> 31);
int s = s1 & s2 & s3;
return (s & 1) == 0;
Run Code Online (Sandbox Code Playgroud)
替代变体:
int s1 = (a-d) | (d-a);
int s2 = (b-d) | (d-b);
int s3 = (c-d) | (d-c);
int s = (s1 & s2 & s3);
return (s & 0x80000000) == 0;
Run Code Online (Sandbox Code Playgroud)
两者都被翻译成:
mov eax, ecx
sub eax, edi
sub edi, ecx
or edi, eax
mov eax, ecx
sub eax, esi
sub esi, ecx
or esi, eax
and esi, edi
mov eax, edx
sub eax, ecx
sub ecx, edx
or ecx, eax
test esi, ecx
setns al
ret
Run Code Online (Sandbox Code Playgroud)
其中 sete 指令较少,但显然 mov/sub 较多。
更新:正如 BeeOnRope@ 建议的那样 - 将输入变量转换为无符号是有意义的