[OpenMP] Fix nondependent inscan variables in templated functions (#191627)
Fixes https://github.com/llvm/llvm-project/issues/191549. Assisted-by: claude-4.6-opus
This commit is contained in:
committed by
GitHub
parent
00ccd11aba
commit
54d4bf2acb
@@ -20498,6 +20498,10 @@ static bool actOnOMPReductionKindClause(
|
||||
(DeclareReductionRef.isUnset() ||
|
||||
isa<UnresolvedLookupExpr>(DeclareReductionRef.get()))) {
|
||||
RD.push(RefExpr, DeclareReductionRef.get());
|
||||
// Handle non-dependent inscan reduction variables in dependent contexts.
|
||||
if (RD.RedModifier == OMPC_REDUCTION_inscan)
|
||||
Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, nullptr,
|
||||
RD.RedModifier, ASE || OASE);
|
||||
continue;
|
||||
}
|
||||
if (BOK == BO_Comma && DeclareReductionRef.isUnset()) {
|
||||
|
||||
63
clang/test/OpenMP/scan_inscan_template_nondependent.cpp
Normal file
63
clang/test/OpenMP/scan_inscan_template_nondependent.cpp
Normal file
@@ -0,0 +1,63 @@
|
||||
// RUN: %clang_cc1 -verify -fopenmp -std=c++17 %s
|
||||
// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++17 %s
|
||||
// expected-no-diagnostics
|
||||
|
||||
// Regression test for https://github.com/llvm/llvm-project/issues/191549
|
||||
// Inscan reductions with non-dependent types in function templates were
|
||||
// incorrectly rejected because the DSA stack was not populated in
|
||||
// dependent contexts.
|
||||
|
||||
template <typename T>
|
||||
void exclusive_in_template() {
|
||||
int a[100], b[100];
|
||||
int sum = 0;
|
||||
#pragma omp parallel for reduction(inscan, +: sum)
|
||||
for (int i = 0; i < 100; i++) {
|
||||
a[i] = sum;
|
||||
#pragma omp scan exclusive(sum)
|
||||
sum += b[i];
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void inclusive_in_template() {
|
||||
int a[100], b[100];
|
||||
int sum = 0;
|
||||
#pragma omp parallel for reduction(inscan, +: sum)
|
||||
for (int i = 0; i < 100; i++) {
|
||||
sum += b[i];
|
||||
#pragma omp scan inclusive(sum)
|
||||
a[i] = sum;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void for_simd_inscan_in_template() {
|
||||
int a[100], b[100];
|
||||
int sum = 0;
|
||||
#pragma omp parallel for simd reduction(inscan, +: sum)
|
||||
for (int i = 0; i < 100; i++) {
|
||||
a[i] = sum;
|
||||
#pragma omp scan exclusive(sum)
|
||||
sum += b[i];
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void simd_inscan_in_template() {
|
||||
int a[100], b[100];
|
||||
int sum = 0;
|
||||
#pragma omp simd reduction(inscan, +: sum)
|
||||
for (int i = 0; i < 100; i++) {
|
||||
a[i] = sum;
|
||||
#pragma omp scan exclusive(sum)
|
||||
sum += b[i];
|
||||
}
|
||||
}
|
||||
|
||||
void instantiate() {
|
||||
exclusive_in_template<int>();
|
||||
inclusive_in_template<int>();
|
||||
for_simd_inscan_in_template<int>();
|
||||
simd_inscan_in_template<int>();
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
// RUN: %libomp-cxx-compile-and-run | FileCheck %s
|
||||
|
||||
// Regression test for https://github.com/llvm/llvm-project/issues/191549
|
||||
// Inscan reductions with non-dependent types inside function templates were
|
||||
// rejected by Clang because the DSA stack was not populated in dependent
|
||||
// contexts. This test verifies runtime correctness of both exclusive and
|
||||
// inclusive scans in template functions.
|
||||
|
||||
#include <cstdlib>
|
||||
#include <numeric>
|
||||
#include <stdio.h>
|
||||
|
||||
#define N 100
|
||||
|
||||
template <typename T> bool test_exclusive(T *a, const T *b) {
|
||||
int sum = 0;
|
||||
#pragma omp parallel for reduction(inscan, + : sum)
|
||||
for (int i = 0; i < N; i++) {
|
||||
a[i] = sum;
|
||||
#pragma omp scan exclusive(sum)
|
||||
sum += b[i];
|
||||
}
|
||||
|
||||
for (int i = 0, prefix = 0; i < N; i++) {
|
||||
if (a[i] != prefix)
|
||||
return false;
|
||||
prefix += b[i];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T> bool test_inclusive(T *a, const T *b) {
|
||||
int sum = 0;
|
||||
#pragma omp parallel for reduction(inscan, + : sum)
|
||||
for (int i = 0; i < N; i++) {
|
||||
sum += b[i];
|
||||
#pragma omp scan inclusive(sum)
|
||||
a[i] = sum;
|
||||
}
|
||||
|
||||
for (int i = 0, prefix = 0; i < N; i++) {
|
||||
prefix += b[i];
|
||||
if (a[i] != prefix)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int main() {
|
||||
bool success = true;
|
||||
|
||||
int a[N], b[N];
|
||||
std::iota(b, b + N, 1);
|
||||
|
||||
if (test_exclusive<int>(a, b)) {
|
||||
printf("exclusive: PASS\n");
|
||||
} else {
|
||||
printf("exclusive: FAIL\n");
|
||||
success = false;
|
||||
}
|
||||
|
||||
if (test_inclusive<int>(a, b)) {
|
||||
printf("inclusive: PASS\n");
|
||||
} else {
|
||||
printf("inclusive: FAIL\n");
|
||||
success = false;
|
||||
}
|
||||
|
||||
return success ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// CHECK: exclusive: PASS
|
||||
// CHECK: inclusive: PASS
|
||||
Reference in New Issue
Block a user