在AVX中,有两个指令可以执行按位或VORPD和VORPS.文档说:
VORPD (VEX.256 encoded version)
DEST[63:0] <- SRC1[63:0] BITWISE OR SRC2[63:0]
DEST[127:64] <- SRC1[127:64] BITWISE OR SRC2[127:64]
DEST[191:128] <- SRC1[191:128] BITWISE OR SRC2[191:128]
DEST[255:192] <- SRC1[255:192] BITWISE OR SRC2[255:192]
Run Code Online (Sandbox Code Playgroud)
和
VORPS (VEX.256 encoded version)
DEST[31:0] <- SRC1[31:0] BITWISE OR SRC2[31:0]
DEST[63:32] <- SRC1[63:32] BITWISE OR SRC2[63:32]
DEST[95:64] <- SRC1[95:64] BITWISE OR SRC2[95:64]
DEST[127:96] <- SRC1[127:96] BITWISE OR SRC2[127:96]
DEST[159:128] <- SRC1[159:128] BITWISE OR SRC2[159:128]
DEST[191:160] <- SRC1[191:160] BITWISE OR SRC2[191:160]
DEST[223:192] <- SRC1[223:192] BITWISE OR SRC2[223:192]
DEST[255:224] <- SRC1[255:224] BITWISE …Run Code Online (Sandbox Code Playgroud) 我观察到 GCC 的 C++ 编译器生成以下汇编代码:
sub $0xffffffffffffff80,%rsp
Run Code Online (Sandbox Code Playgroud)
这相当于
add $0x80,%rsp
Run Code Online (Sandbox Code Playgroud)
即从堆栈中删除 128 个字节。
为什么 GCC 生成第一个子变体而不是添加变体?对我来说,添加变体似乎比利用下溢更自然。
在相当大的代码库中,这只发生一次。我没有最小的 C++ 代码示例来触发此操作。我正在使用海湾合作委员会7.5.0
考虑以下 C++ 代码:
#include <fenv.h>
#include <iostream>
using namespace std;
int main(){
fesetround(FE_TONEAREST);
double a = 0x1.efc7f0001p+376;
double b = -0x1.0fdfdp+961;
double c = a*b;
cout << a << " "<< b << " " << c << endl;
}
Run Code Online (Sandbox Code Playgroud)
我看到的输出是
2.98077e+113 -2.06992e+289 -inf
Run Code Online (Sandbox Code Playgroud)
我不明白为什么c是无穷大。我的理解是,无论最小的非无穷大浮点数是多少,它都应该更接近实际值,a*b因为-inf最小非无穷大浮点数是有限的,并且任何有限数都比负无穷更接近任何其他有限数。为什么这里会输出无穷大呢?
它在 64 位 x86 上运行,并且程序集使用 SSE 指令。它是用 -O0 编译的,并且在 clang 和 gcc 中都会发生。
如果对浮点使用向零舍入模式,则结果是最小有限浮点。我的结论是这个问题与四舍五入有关。