NVC++ miscompiles for nested loops with std::vector

NVC++ produces incorrect results for the following code at -O2 and -O3:

#include <cstdio>
#include <vector>

struct Pair { int value[2]; };

std::vector<Pair> make(int n, bool horizontal) {
  std::vector<Pair> result(n);
  int nx = horizontal ? n : 1, ny = horizontal ? 1 : n, k = 0;
  for (int y = 1; y <= ny; ++y)
    for (int x = 1; x <= nx; ++x) {
      for (int i = 0; i < 2; ++i) result[k].value[i] = 0;
      if (x == nx) result[k].value[0] = 1;
      if (y == ny) result[k].value[1] = 1;
      ++k;
    }
  return result;
}

int main() {
  auto result = make(2, false);
  for (auto &p : result) std::printf("%d %d\n", p.value[0], p.value[1]);
}
> nvc++ -O0 example.cpp && ./a.out
1 0
1 1
> nvc++ -O2 example.cpp && ./a.out
0 0
1 0

Reproduced with 26.1, 26.3, 26.5 and 26.9 on aarch64, and 26.5 on x86-64. -O0 and -O1 produce the expected output. GCC also compiles this correctly.

The inner zeroing loop seems to play a role here: removing it produces the expected result. The vector constructor already initializes those values to zero. Adding -Mnoautoinline also produces the expected result at both -O2 and -O3.

Valgrind reports no errors on x86-64 with 26.5, even though the optimized program still prints the incorrect values.

Thanks!

Tom

I’ve reduced this further to only a stack array, and with no STL stuff:

int main(int n, char **) {
  int v[1]{};
  for (int x = 1; x <= n; ++x) {
    for (int i = 0; i < 1; ++i) v[x - 1] = 0;
    if (x == n) v[x - 1] = 1;
    if (!n) v[0] = 0;
  }
  return v[0];
}

Run without arguments. The expected exit is 1:

> nvc++ -O0 example.cpp -o example
> ./example; echo $?
1
> nvc++ -O2 example.cpp -o example
> ./example; echo $?
0
> nvc++ -O2 -Mnoautoinline example.cpp -o example
> ./example; echo $?
0

Reproduced with 26.5 on both x86-64 and aarch64. -O3 also returns 0; GCC returns 1.
If n is a compile-time constant then the problem goes away.

This version still fails with -Mnoautoinline, so automatic inlining is not required to trigger it as there’s nothing to inline at this point.

Thanks Tom!

I was able to reproduce the error here and sent a report to engineering. Filed as TPR #39020.

-Mat