How does Visual Studio 2022 handle double-to-long long out-of-range conversion?

157 views Asked by At

Consider the following code in C++, compiled with Visual Studio 2022:

#include <iostream>
#include <intrin.h>
int main() {
    std::cout << _cvt_dtoll_sent(1e31) << "\n";
    std::cout << _cvt_dtoll_sat(1e31) << "\n";
    std::cout << _cvt_dtoll_fast(1e31) << "\n";
    std::cout << (long long)1e31 << "\n";
}

In x86 it prints:

-9223372036854775808
9223372036854775807
4016683251292700672
-4571153621781053440

In x64 it prints:

-9223372036854775808
9223372036854775807
-9223372036854775808
-4571153621781053440

The program uses four different ways to convert double to long long. As 1e31 does not fit into long long (signed 64-bit integer), the behavior is undefined under C++ standard. However, VS2022 has a special option that defaults to /fpcvt:BC, quoting:

The /fpcvt:BC option also makes conversion to signed types return the minimum possible value when the source is invalid

So I'd expect (long long)1e31 to return a sentinel value of -9223372036854775808, just like _cvt_dtoll_sent. However, not only it does not return the sentinel, it does not coincide with either "saturated" or "fast" version of the conversion. Why is that?

0

There are 0 answers