There's only 1 circumstance where __builtin_clz
gives the wrong answer. I'm curious what's causing that behavior.
When I use the literal value 0 I always get 32 as expected. But 0 as a variable yields 31. Why does the method of storing the value 0 matter?
I've taken an architecture class but don't understand the diffed assembly. It looks like when given the literal value 0, the assembly somehow always has the correct answer of 32 hard coded even without optimizations. And the method for counting leading zeros is different when using -march=native.
This post about emulating __builtin_clz
with _BitScanReverse
and the line bsrl %eax, %eax
seem to imply that bit scan reverse doesn't work for 0.
+-------------------+-------------+--------------+
| Compile | literal.cpp | variable.cpp |
+-------------------+-------------+--------------+
| g++ | 32 | 31 |
| g++ -O | 32 | 32 |
| g++ -march=native | 32 | 32 |
+-------------------+-------------+--------------+
literal.cpp
#include <iostream>
int main(){
int i = 0;
std::cout << __builtin_clz(0) << std::endl;
}
variable.cpp
#include <iostream>
int main(){
int i = 0;
std::cout << __builtin_clzl(i) << std::endl;
}
Diff for g++ -S [in name] -o [out name]
1c1
< .file "literal.cpp"
---
> .file "variable.cpp"
23c23,26
< movl $32, %esi
---
> movl -4(%rbp), %eax
> bsrl %eax, %eax
> xorl $31, %eax
> movl %eax, %esi
Diff for g++ -march=native -S [in name] -o [out name]
1c1
< .file "literal.cpp"
---
> .file "variable.cpp"
23c23,25
< movl $32, %esi
---
> movl -4(%rbp), %eax
> lzcntl %eax, %eax
> movl %eax, %esi
Diff for g++ -O -S [in name] -o [out name]
1c1
< .file "literal.cpp"
---
> .file "variable.cpp"
Aucun commentaire:
Enregistrer un commentaire