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.