Sle*_*lei 9 c++ compiler-construction assembly compiler-optimization
我有这个功能
long long int divideBy10(long long int a){
return a / 10;
}
Run Code Online (Sandbox Code Playgroud)
它被编译为:
mov rax, rdi
movabs rcx, 7378697629483820647
imul rcx
mov rax, rdx
shr rax, 63
sar rdx, 2
add rax, rdx
ret
Run Code Online (Sandbox Code Playgroud)
如果我添加 __builtin_assume(a > 0);
它被编译为
mov rax, rdi
movabs rcx, -3689348814741910323
mul rcx
mov rax, rdx
shr rax, 3
ret
Run Code Online (Sandbox Code Playgroud)
代码效率更高,因为它不必担心负号。现在,如果我添加 __builtin_assume(a < 10000); 我原以为它会被编译成一个乘法而没有移位。但事实并非如此。
我想也许编译器只跟踪数字是正数还是负数,但是
long long int noBranch(long long int a){
__builtin_assume(a < 400);
if( a < 500){
return a;
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
编译为一条移动指令,以便编译器能够跟踪这些边界。
为什么编译器不能优化转移?(这发生在 GCC 和 Clang 中)。
这是我希望生成的代码:
long long int d10(long long int a){
__builtin_assume(a > 0);
__builtin_assume(a < 10'000);
__uint128_t e = a;
e *= 0x199999999999999A;
return e >> 64;
}
Run Code Online (Sandbox Code Playgroud)
d10(long long): # @d10(long long)
mov rax, rdi
movabs rcx, 1844674407370955162
mul rcx
mov rax, rdx
ret
Run Code Online (Sandbox Code Playgroud)
编辑:我知道你需要一个班次才能涵盖 long long int 的整个范围。我在问如果范围受到限制,为什么编译器不能优化转移。
归档时间: |
|
查看次数: |
206 次 |
最近记录: |