Nvc++ 26.5 -O2 miscompilation: wrong final value for a loop counter when a copy loop is inlined

Hello,

While adding support for EDG front-end based compilers to Boost.Container I noticed nvc++ 26.5 miscompiles a very common C++ idiom. When the function is inlined at -O2 or -fast and the source iterators are class-type contiguous iterators (std::vector::iterator), the loop’s element copies are performed correctly but the counter variable ends up with a wrong final value (1 instead of the number of elements). Compiling with -O0 produces the correct value, and g++ is correct at every optimization level.

Godbolt link:

Code:

#include <vector>

#include <cstddef>

#include <cstdio>

template <class InpIt, class FwdIt>

std::size_t ucopy(InpIt first, InpIt last, FwdIt dest)

{

   std::size_t constructed = 0;

   for (; first != last; ++dest, ++first, ++constructed)

      *dest = *first;

   return constructed;

}

int main()

{

   const std::size_t N = 25;

   std::vector<char> src(N, 'x');

   char buf[256];

   for (std::size_t i = 0; i < sizeof buf; ++i) buf[i] = 0;

   const std::size_t n = ucopy(src.begin(), src.end(), buf);

   std::size_t copied = 0;

   while (copied < sizeof buf && buf[copied] == 'x') ++copied;

   std::printf("returned count : %zu (expected %zu)%s\n", n, N, n == N ? "" : "   <<< WRONG");

   std::printf("bytes actually copied : %zu\n", copied);

   return n == N ? 0 : 1;

}

Thanks in advance!

Hi igaztanaga and welcome!

Thanks for the report and example. I was able to reproduce the issue here and filed a report, TPR#38907. We’ll have engineering investigate.

What appears to be happening is that idiom recognition is correctly detecting and replacing the “ucopy” for loop with a call to memcpy. However, it seems to have missed the second update expression, “constructed”, causing the value of “1” to be returned from the routine.

Hence another work around is to disable idiom recognition via “-Mnoidiom”.

% nvc++ -O2 test.cpp; a.out
Constructed, should be 25 1
returned count : 1 (expected 25)   <<< WRONG
bytes actually copied : 25
% nvc++ -O2 -Mnoidiom test.cpp ; a.out
Constructed, should be 25 25
returned count : 25 (expected 25)
bytes actually copied : 25

-Mat

Thanks for the quick reply!

Hi - great news! This is now fixed in the latest release (26.9)! Thanks for letting us know!

Let us know if you run into any other issues!

Cheers,

Seth.