Dar*_*ver 6 c++ gcc intrinsics undefined-behavior
我对内在函数很陌生,我面对的代码使用GCC-7.4和GCC-8.3的行为不同
我的代码很简单
b.cpp:
#include <iostream>
#include <xmmintrin.h>
void foo(const float num, const float denom)
{
const __v4sf num4 = {
num,
num,
num,
num,
};
const __v4sf denom4 = {
denom,
denom,
denom,
denom,
};
float res_arr[] = {0, 0, 0, 0};
__v4sf *res = (__v4sf*)res_arr;
*res = num4 / denom4;
std::cout << res_arr[0] << std::endl;
std::cout << res_arr[1] << std::endl;
std::cout << res_arr[2] << std::endl;
std::cout << res_arr[3] << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
在b.cpp中,我们基本上只是__v4sf
从float变量构造两个并执行除法
bh:
#ifndef B_H
#define B_H
void foo(const float num, const float denom);
#endif
Run Code Online (Sandbox Code Playgroud)
a.cpp:
#include "b.h"
int main (void)
{
const float denominator = 1.0f;
const float numerator = 12.0f;
foo(numerator, denominator);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在这里,我们只是从b.cpp调用函数
GCC 7.4可以正常工作:
g++-7 -c b.cpp -o b.o && g++-7 a.cpp b.o -o a.out && ./a.out
12
12
12
12
Run Code Online (Sandbox Code Playgroud)
但是GCC 8.3出了点问题
g++-8 -c b.cpp -o b.o && g++-8 a.cpp b.o -o a.out && ./a.out
inf
inf
inf
inf
Run Code Online (Sandbox Code Playgroud)
所以我的问题是-为什么使用不同版本的GCC会收到不同的结果?它是未定义的行为吗?
您在 gcc8 及更高版本中发现了一个错误,无论启用/不启用优化都会发生该错误。感谢您的举报。
启用优化后,很容易看到 asm 正在做什么,因为这些__v4sf
东西会优化掉:它只是标量除法并打印结果 4 次。(加上 4 次刷新 cout 调用,因为您std::endl
出于某种原因使用了。)
gcc7 正确地优化了它以divss xmm0, xmm1
执行num / denom
. 然后它转换为double
因为输出函数只接受double
而不是float
将其传递给iostream
函数。(GCC7 将double
位模式保存在整数寄存器r14
而不是内存中,而-mtune=skylake
.GCC8 和更高版本只使用内存,这可能更有意义。)
gcc8 及更高版本执行divss xmm0, .LC0[rip]
内存中常量所在的位置0
( 的位模式+0.0
)。所以它将除以num
零,忽略denom
。
在Godbolt 编译器浏览器上查看一下。
使用alignas(16) float res_arr[4];
来消除潜在的对齐不足__v4sf *res
没有帮助。(通常不再需要__attribute__((aligned(16)))
;C++11 引入了对齐的标准语法。)
归档时间: |
|
查看次数: |
169 次 |
最近记录: |