samedi 23 novembre 2019

How can a literal 0 and 0 as a variable yield different behavior with the function __builtin_clz?

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