[英]Visual C++ comma operator and sse intrinsics
我一直在调试一些SSE优化的矢量代码,并注意到一些奇怪的行为。 公平地说,代码风格很糟糕,但是编译器所做的事情对我来说仍然是错误的。 这是有问题的功能:
inline void daxpy(int n, double alph, const double* x, int incx, double* y, int incy) {
__m128d sse_alph = _mm_load1_pd(&alph);
while (n >= 4) {
n -= 4;
__m128d y1 = _mm_load_pd(y+n), y2 = _mm_load_pd(y+n+2);
__m128d x1 = _mm_load_pd(x+n), x2 = _mm_load_pd(x+n+2);
y1 = _mm_add_pd(y1, _mm_mul_pd(x1, sse_alph));
y2 = _mm_add_pd(y2, _mm_mul_pd(x2, sse_alph));
_mm_store_pd(y+n, y1), _mm_store_pd(y+n+2, y2);
}
}
函数是数组y = y + alph * x。 我们保证两个数组都具有相同的长度n
,它是4的倍数,并且x和y在16字节边界上对齐(为清楚起见,我省略了相关的断言)。
循环的最后一行已使用逗号运算符编写,因此看起来像两条加载线。 问题是第一个_mm_store_pd
调用未执行。 没错吗 我猜编译器可能已经决定只需要第二次调用就可以计算该表达式,但是很明显内在函数具有副作用。
我是否误解了这里发生了什么? 我意识到使用像这样的逗号运算符是很糟糕的样式-我的问题是编译器是否错误。 有问题的编译器是Visual C ++ 2010 SP 1。
使用Microsoft Visual Studio 2008、2010和2012构建此代码显示它们全部消除了逗号运算符的左操作数。 仅在启用优化的情况下才会发生这种情况。 使用gcc 4.8.1构建此代码时,即使使用了完全优化,也不会消除逗号运算符的左操作数。
C99规范指出:“逗号运算符的左操作数被评估为void表达式;评估后有一个序列点。然后评估右操作数”。
我认为,Microsoft优化器无法删除此代码。 这是因为语言规范指出两个操作数都被求值。 逗号运算符的两个操作数之间的唯一区别是它们的求值顺序,哪个为逗号运算符提供了结果。 在这种情况下,结果是无效的。
解决方法:用分号替换逗号。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.