https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119479
Bug ID: 119479
Summary: wrong sign caused by substraction operand swap of two
dot product operands
Product: gcc
Version: 14.2.1
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: target
Assignee: unassigned at gcc dot gnu.org
Reporter: jondaniel879 at gmail dot com
Target Milestone: ---
Created attachment 60891
--> https://gcc.gnu.org/bugzilla/attachment.cgi?id=60891&action=edit
testcase compile with -O > 0 and Intel SIMD >= SSE4_2
/* permute and rotate indices */
template<size_t IN>
storage<T,std::min(IN, N)> pinr(std::array<size_t, IN>& indices) const
{
storage<T, std::min(IN, N)> dst;
for(size_t i = 0; i < std::min(IN, N); i++)
dst[i] = (*this)[indices[i]];
std::rotate(indices.begin(), indices.begin() + 1, indices.end());
return dst;
}
/* 3x3 matrix determinant of 3 vectors */
static inline constexpr T det(const storage<T, 3>& a, const storage<T, 3>& b,
const storage<T, 3>& c)
{
static std::array<size_t, 3> i = { 0, 1, 2 };
static std::array<size_t, 3> j = { 2, 1, 0 };
float s = storage<float, 3>::dot(a.pinr(i), b.pinr(i), c.pinr(i));
float t = storage<float, 3>::dot(a.pinr(j), b.pinr(j), c.pinr(j));
return s-t;
}
g++ interchanges the operands s-t with t-s: -575-142=-717 != 142-(-575)=717
causing the wrong sub/add.
The generated assembler output snippet:
g++:
vdpps $113, 72(%rsp), 24(%rsp), %xmm3
vdpps $113, 72(%rsp), 24(%rsp), %xmm2
vsubss %xmm2, %xmm3, %xmm0
Notice the second dot product result as the first source operand
clang++:
vdpps $113, %xmm2, %xmm1, %xmm4
vdpps $113, %xmm0, %xmm1, %xmm1
vsubss %xmm4, %xmm0, %xmm0
Notice the first dot product result as the first source operand
The C++ analog is the difference between std::reduce and std::accumulate but
for sub operands.