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.

Reply via email to