https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104952

            Bug ID: 104952
           Summary: [nvptx][OpenMP] wrong code with OR / AND reduction
                    ('reduction(||:' and '&&') with SIMT
           Product: gcc
           Version: 12.0
            Status: UNCONFIRMED
          Keywords: wrong-code
          Severity: normal
          Priority: P3
         Component: target
          Assignee: unassigned at gcc dot gnu.org
          Reporter: burnus at gcc dot gnu.org
                CC: jakub at gcc dot gnu.org, vries at gcc dot gnu.org
  Target Milestone: ---
            Target: nvptx-none

* Works when compiled with -O0
* Fails when compiled with -O1 → "result" is 0 instead of 1.

Observations:
* Issue occurs with '||' and '&&' – and for char/short/int/long.
* Note: -O1 implies that omp_max_vf() returns != 1
  Thus, only with -O1 there is SIMT, which seems to cause the problem.
* When replacing 'reduction(||:'  by
                 'reduction(|:'   the code passes.

Regarding the latter: Given that the order is not determined (i.e. 'a || b' 
and 'b || a' can occur), I think '||' can always be replaced by '|' in the
reduction.

@jakub: ^  does this make sense?

* * *

Long testcase is tests/5.0/loop/test_loop_reduction_or_device.c from
https://github.com/SOLLVE/sollve_vv/
[the ..._and_... ('&&') testcase fails in the same way.] — Short testcase is
below.

Short testcase (runs into abort with -O1, works with -O0 or with
"reduction:(|"):

 * * *

int main () {
  char arr[100];
  int result = 0;
  for (int i = 0; i < 100; ++i)
    arr[i] = 0;
  arr[5] = 1;
#pragma omp target parallel map(tofrom:arr,result)
  #pragma omp loop reduction(||: result)
    for (int i = 0; i < 100; ++i)
      result = result || arr[i];

  if (result != 1)
    __builtin_abort ();
  return 0;
}

Reply via email to