[flang-commits] [flang] 8305195 - [flang][OpenMP] incorrect handling for local variable in OpenMP parallel workshare firstprivate(P) (#195616)
via flang-commits
flang-commits at lists.llvm.org
Wed Sep 2 23:29:53 PDT 2026
Author: SunilKuravinakop
Date: 2026-09-03T11:59:47+05:30
New Revision: 83051952abc253395a811902921d2683d0a494ee
URL: https://github.com/llvm/llvm-project/commit/83051952abc253395a811902921d2683d0a494ee
DIFF: https://github.com/llvm/llvm-project/commit/83051952abc253395a811902921d2683d0a494ee.diff
LOG: [flang][OpenMP] incorrect handling for local variable in OpenMP parallel workshare firstprivate(P) (#195616)
Changes to handle "!$omp parallel workshare firstprivate(P)" where P is
an array. Handling the creation and initialization of the local copy
properly.
This also Fixes
[195337](https://github.com/llvm/llvm-project/issues/195337) .
---------
Sunil Kuravinakop <koops at hpe.com>
Added:
flang/test/Lower/OpenMP/Todo/workshare-firstprivate-polymorphic.f90
flang/test/Lower/OpenMP/workshare-firstprivate.f90
Modified:
llvm/include/llvm/Frontend/OpenMP/ConstructDecompositionT.h
Removed:
################################################################################
diff --git a/flang/test/Lower/OpenMP/Todo/workshare-firstprivate-polymorphic.f90 b/flang/test/Lower/OpenMP/Todo/workshare-firstprivate-polymorphic.f90
new file mode 100644
index 0000000000000..5fbcf2c13c179
--- /dev/null
+++ b/flang/test/Lower/OpenMP/Todo/workshare-firstprivate-polymorphic.f90
@@ -0,0 +1,23 @@
+! Tests that firstprivate of a polymorphic variable in a parallel workshare
+! region is not yet supported.
+
+! RUN: %not_todo_cmd %flang_fc1 -emit-hlfir -fopenmp -o - %s 2>&1 | FileCheck %s
+
+module shapes
+ type :: shape
+ real :: area
+ end type
+end module
+
+subroutine poly_workshare_firstprivate(p, a, n)
+ use shapes
+ implicit none
+ integer :: n
+ class(shape), allocatable :: p(:)
+ real :: a(n)
+
+ !CHECK: not yet implemented: create polymorphic host associated copy
+ !$omp parallel workshare firstprivate(p)
+ a = p%area + 1.0
+ !$omp end parallel workshare
+end subroutine
diff --git a/flang/test/Lower/OpenMP/workshare-firstprivate.f90 b/flang/test/Lower/OpenMP/workshare-firstprivate.f90
new file mode 100644
index 0000000000000..7625f9e111fcc
--- /dev/null
+++ b/flang/test/Lower/OpenMP/workshare-firstprivate.f90
@@ -0,0 +1,53 @@
+! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=51 %s -o - | FileCheck %s --check-prefix HLFIR
+! RUN: %flang_fc1 -emit-fir -fopenmp -fopenmp-version=51 %s -o - | FileCheck %s --check-prefix FIR
+
+! firstprivate on "parallel workshare" is applied to the parallel leaf, so it
+! uses the standard omp.private delayed privatization. After the LowerWorkshare
+! pass the private clause is preserved on omp.parallel; array assignments are
+! workshared (omp.wsloop) while FORALL runs in omp.single.
+
+! HLFIR: omp.private {type = firstprivate} @{{.*}}_firstprivate_box_ptr_Uxi32 : !fir.box<!fir.ptr<!fir.array<?xi32>>>
+! HLFIR: omp.private {type = firstprivate} @{{.*}}_firstprivate_box_heap_Uxi32 : !fir.box<!fir.heap<!fir.array<?xi32>>>
+! HLFIR: hlfir.assign %{{.*}} to %{{.*}} realloc
+
+! Pointer firstprivate, array assignment -> workshared loop.
+subroutine test_ptr(p)
+ integer, pointer, intent(in) :: p(:)
+ integer :: a(4)
+ !$omp parallel workshare firstprivate(p)
+ a = p + 1
+ !$omp end parallel workshare
+end subroutine
+
+! FIR-LABEL: func.func @{{.*}}test_ptr(
+! FIR: omp.parallel private(@{{.*}}test_ptrEp_firstprivate{{.*}} -> %{{.*}} :
+! FIR-SAME: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) {
+! FIR: omp.wsloop
+
+! Allocatable firstprivate, array assignment -> workshared loop.
+subroutine test_alloc(p)
+ integer, allocatable :: p(:)
+ integer :: a(4)
+ !$omp parallel workshare firstprivate(p)
+ a = p + 1
+ !$omp end parallel workshare
+end subroutine
+
+! FIR-LABEL: func.func @{{.*}}test_alloc(
+! FIR: omp.parallel private(@{{.*}}test_allocEp_firstprivate{{.*}} -> %{{.*}} :
+! FIR-SAME: !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) {
+! FIR: omp.wsloop
+
+! FORALL body runs in omp.single (not workshared).
+subroutine test_forall(p)
+ integer, pointer, intent(in) :: p(:)
+ integer :: i
+ !$omp parallel workshare firstprivate(p)
+ forall (i=1:size(p)) p(i) = i*i
+ !$omp end parallel workshare
+end subroutine
+
+! FIR-LABEL: func.func @{{.*}}test_forall(
+! FIR: omp.parallel private(@{{.*}}test_forallEp_firstprivate{{.*}} -> %{{.*}} :
+! FIR-SAME: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) {
+! FIR: omp.single
diff --git a/llvm/include/llvm/Frontend/OpenMP/ConstructDecompositionT.h b/llvm/include/llvm/Frontend/OpenMP/ConstructDecompositionT.h
index 7bd55875eec45..ffb340e610f40 100644
--- a/llvm/include/llvm/Frontend/OpenMP/ConstructDecompositionT.h
+++ b/llvm/include/llvm/Frontend/OpenMP/ConstructDecompositionT.h
@@ -612,17 +612,20 @@ bool ConstructDecompositionT<C, H>::applyClause(
}
// [5.2:340:8]
- auto findWorksharing = [&]() {
+ // Match only a worksharing construct that accepts firstprivate; "workshare"
+ // does not, so it falls through to "parallel" per [5.2:340:10].
+ auto findWorksharingAcceptingFirstprivate = [&]() {
auto worksharing = getWorksharing();
for (auto &leaf : leafs) {
auto found = llvm::find(worksharing, leaf.id);
- if (found != std::end(worksharing))
+ if (found != std::end(worksharing) &&
+ llvm::omp::isAllowedClauseForDirective(leaf.id, input->id, version))
return &leaf;
}
return static_cast<typename decltype(leafs)::value_type *>(nullptr);
};
- auto dirWorksharing = findWorksharing();
+ auto dirWorksharing = findWorksharingAcceptingFirstprivate();
if (dirWorksharing != nullptr) {
dirWorksharing->clauses.push_back(input);
applied = true;
More information about the flang-commits
mailing list