Hãy xem xét các chương trình sau đây:răng cưa chặt chẽ, -ffast-toán và SSE
#include <iostream>
#include <cmath>
#include <cstring>
#include <xmmintrin.h>
using namespace std;
int main()
{
// 4 float32s.
__m128 nans;
// Set them all to 0xffffffff which should be NaN.
memset(&nans, 0xff, 4*4);
// cmpord should return a mask of 0xffffffff for any non-NaNs, and 0x00000000 for NaNs.
__m128 mask = _mm_cmpord_ps(nans, nans);
// AND the mask with nans to zero any of the nans. The result should be 0x00000000 for every component.
__m128 z = _mm_and_ps(mask, nans);
cout << z[0] << " " << z[1] << " " << z[2] << " " << z[3] << endl;
return 0;
}
Nếu tôi biên dịch với Apple Clang 7.0.2 có và không có -ffast-math
, tôi nhận được kết quả mong muốn 0 0 0 0
:
$ clang --version
Apple LLVM version 7.0.2 (clang-700.1.81)
Target: x86_64-apple-darwin14.5.0
Thread model: posix
$ clang test.cpp -o test
$ ./test
0 0 0 0
$ clang test.cpp -ffast-math -o test
$ ./test
0 0 0 0
Tuy nhiên sau khi cập nhật lên 8.1.0 (xin lỗi tôi không biết phiên bản Clang nào tương ứng với - Apple không còn xuất bản thông tin đó nữa), -ffast-math
dường như vi phạm điều này:
$ clang --version
Apple LLVM version 8.1.0 (clang-802.0.42)
Target: x86_64-apple-darwin16.6.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
$ clang test.cpp -o test
$ ./test
0 0 0 0
$ clang test.cpp -ffast-math -o test
$ ./test
nan nan nan nan
Tôi nghi ngờ điều này là do quy tắc bí danh nghiêm ngặt hoặc điều gì đó tương tự. Bất cứ ai có thể giải thích hành vi này?
Chỉnh sửa: Tôi quên đề cập rằng nếu bạn làm nans = { std::nanf(nullptr), ...
thì nó hoạt động tốt.
Cũng tìm kiếm trên godbolt có vẻ như hành vi đã thay đổi giữa Clang 3.8.1 và Clang 3.9 - sau này loại bỏ lệnh cmpordps
. GCC 7.1 dường như để nó ở.
Huh Tôi không biết rằng ... Cảm ơn! – Timmmm