-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[Flang][OpenMP] Fix bug with default(none) and host-assoc threadprivate variable #134122
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR fixes an issue where a host-associated threadprivate variable was incorrectly reported as missing a DSA in parallel regions with default(none).
- Replace the direct threadprivate flag check with a check on the ultimate symbol to correctly determine threadprivateness.
- Ensures that the compiler no longer flags pre-determined threadprivate variables erroneously.
Files not reviewed (1)
- flang/test/Lower/OpenMP/threadprivate-host-association-3.f90: Language not supported
Comments suppressed due to low confidence (1)
flang/lib/Semantics/resolve-directives.cpp:2304
- Ensure that GetUltimate() is guaranteed to return a valid symbol to avoid potential null dereferences.
!symbol->GetUltimate().test(Symbol::Flag::OmpThreadprivate) &&
@llvm/pr-subscribers-flang-semantics @llvm/pr-subscribers-flang-openmp Author: Michael Klemm (mjklemm) ChangesWhen a host associated Full diff: https://github.com/llvm/llvm-project/pull/134122.diff 2 Files Affected:
diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
index f905da0a7239d..cc76abec56946 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -2301,7 +2301,7 @@ void OmpAttributeVisitor::Post(const parser::Name &name) {
if (symbol != found) {
name.symbol = found; // adjust the symbol within region
} else if (GetContext().defaultDSA == Symbol::Flag::OmpNone &&
- !symbol->test(Symbol::Flag::OmpThreadprivate) &&
+ !symbol->GetUltimate().test(Symbol::Flag::OmpThreadprivate) &&
// Exclude indices of sequential loops that are privatised in
// the scope of the parallel region, and not in this scope.
// TODO: check whether this should be caught in IsObjectWithDSA
diff --git a/flang/test/Lower/OpenMP/threadprivate-host-association-3.f90 b/flang/test/Lower/OpenMP/threadprivate-host-association-3.f90
new file mode 100644
index 0000000000000..22ee51f82bc0f
--- /dev/null
+++ b/flang/test/Lower/OpenMP/threadprivate-host-association-3.f90
@@ -0,0 +1,44 @@
+! This test checks lowering of OpenMP Threadprivate Directive.
+! Test for threadprivate variable in host association.
+
+!RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s
+
+!CHECK: func.func @_QQmain() attributes {fir.bindc_name = "main"} {
+!CHECK: %[[A:.*]] = fir.alloca i32 {bindc_name = "a", uniq_name = "_QFEa"}
+!CHECK: %[[A_DECL:.*]]:2 = hlfir.declare %[[A]] {fortran_attrs = #fir.var_attrs<internal_assoc>, uniq_name = "_QFEa"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+!CHECK: %[[A_ADDR:.*]] = fir.address_of(@_QFEa) : !fir.ref<i32>
+!CHECK: %[[TP_A:.*]] = omp.threadprivate %[[A_ADDR]] : !fir.ref<i32> -> !fir.ref<i32>
+!CHECK: %[[TP_A_DECL:.*]]:2 = hlfir.declare %[[TP_A]] {fortran_attrs = #fir.var_attrs<internal_assoc>, uniq_name = "_QFEa"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+!CHECK: fir.call @_QFPsub() fastmath<contract> : () -> ()
+!CHECK: return
+!CHECK: }
+!CHECK: func.func private @_QFPsub() attributes {fir.host_symbol = {{.*}}, llvm.linkage = #llvm.linkage<internal>} {
+!CHECK: %[[A:.*]] = fir.alloca i32 {bindc_name = "a", uniq_name = "_QFEa"}
+!CHECK: %[[A_DECL:.*]]:2 = hlfir.declare %[[A]] {uniq_name = "_QFEa"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+!CHECK: %[[A_ADDR:.*]] = fir.address_of(@_QFEa) : !fir.ref<i32>
+!CHECK: %[[TP_A:.*]] = omp.threadprivate %[[A_ADDR]] : !fir.ref<i32> -> !fir.ref<i32>
+!CHECK: %[[TP_A_DECL:.*]]:2 = hlfir.declare %[[TP_A]] {uniq_name = "_QFEa"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+!CHECK: omp.parallel {
+!CHECK: %[[PAR_TP_A:.*]] = omp.threadprivate %[[A_ADDR]] : !fir.ref<i32> -> !fir.ref<i32>
+!CHECK: %[[PAR_TP_A_DECL:.*]]:2 = hlfir.declare %[[PAR_TP_A]] {uniq_name = "_QFEa"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+!CHECK: %{{.*}} = fir.load %[[PAR_TP_A_DECL]]#0 : !fir.ref<i32>
+!CHECK: omp.terminator
+!CHECK: }
+!CHECK: return
+!CHECK: }
+!CHECK: fir.global internal @_QFEa : i32 {
+!CHECK: %[[A:.*]] = fir.undefined i32
+!CHECK: fir.has_value %[[A]] : i32
+!CHECK: }
+
+program main
+ integer :: a
+ !$omp threadprivate(a)
+ call sub()
+contains
+ subroutine sub()
+ !$omp parallel default(none)
+ print *, a
+ !$omp end parallel
+ end
+end
|
@llvm/pr-subscribers-flang-fir-hlfir Author: Michael Klemm (mjklemm) ChangesWhen a host associated Full diff: https://github.com/llvm/llvm-project/pull/134122.diff 2 Files Affected:
diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
index f905da0a7239d..cc76abec56946 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -2301,7 +2301,7 @@ void OmpAttributeVisitor::Post(const parser::Name &name) {
if (symbol != found) {
name.symbol = found; // adjust the symbol within region
} else if (GetContext().defaultDSA == Symbol::Flag::OmpNone &&
- !symbol->test(Symbol::Flag::OmpThreadprivate) &&
+ !symbol->GetUltimate().test(Symbol::Flag::OmpThreadprivate) &&
// Exclude indices of sequential loops that are privatised in
// the scope of the parallel region, and not in this scope.
// TODO: check whether this should be caught in IsObjectWithDSA
diff --git a/flang/test/Lower/OpenMP/threadprivate-host-association-3.f90 b/flang/test/Lower/OpenMP/threadprivate-host-association-3.f90
new file mode 100644
index 0000000000000..22ee51f82bc0f
--- /dev/null
+++ b/flang/test/Lower/OpenMP/threadprivate-host-association-3.f90
@@ -0,0 +1,44 @@
+! This test checks lowering of OpenMP Threadprivate Directive.
+! Test for threadprivate variable in host association.
+
+!RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s
+
+!CHECK: func.func @_QQmain() attributes {fir.bindc_name = "main"} {
+!CHECK: %[[A:.*]] = fir.alloca i32 {bindc_name = "a", uniq_name = "_QFEa"}
+!CHECK: %[[A_DECL:.*]]:2 = hlfir.declare %[[A]] {fortran_attrs = #fir.var_attrs<internal_assoc>, uniq_name = "_QFEa"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+!CHECK: %[[A_ADDR:.*]] = fir.address_of(@_QFEa) : !fir.ref<i32>
+!CHECK: %[[TP_A:.*]] = omp.threadprivate %[[A_ADDR]] : !fir.ref<i32> -> !fir.ref<i32>
+!CHECK: %[[TP_A_DECL:.*]]:2 = hlfir.declare %[[TP_A]] {fortran_attrs = #fir.var_attrs<internal_assoc>, uniq_name = "_QFEa"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+!CHECK: fir.call @_QFPsub() fastmath<contract> : () -> ()
+!CHECK: return
+!CHECK: }
+!CHECK: func.func private @_QFPsub() attributes {fir.host_symbol = {{.*}}, llvm.linkage = #llvm.linkage<internal>} {
+!CHECK: %[[A:.*]] = fir.alloca i32 {bindc_name = "a", uniq_name = "_QFEa"}
+!CHECK: %[[A_DECL:.*]]:2 = hlfir.declare %[[A]] {uniq_name = "_QFEa"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+!CHECK: %[[A_ADDR:.*]] = fir.address_of(@_QFEa) : !fir.ref<i32>
+!CHECK: %[[TP_A:.*]] = omp.threadprivate %[[A_ADDR]] : !fir.ref<i32> -> !fir.ref<i32>
+!CHECK: %[[TP_A_DECL:.*]]:2 = hlfir.declare %[[TP_A]] {uniq_name = "_QFEa"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+!CHECK: omp.parallel {
+!CHECK: %[[PAR_TP_A:.*]] = omp.threadprivate %[[A_ADDR]] : !fir.ref<i32> -> !fir.ref<i32>
+!CHECK: %[[PAR_TP_A_DECL:.*]]:2 = hlfir.declare %[[PAR_TP_A]] {uniq_name = "_QFEa"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+!CHECK: %{{.*}} = fir.load %[[PAR_TP_A_DECL]]#0 : !fir.ref<i32>
+!CHECK: omp.terminator
+!CHECK: }
+!CHECK: return
+!CHECK: }
+!CHECK: fir.global internal @_QFEa : i32 {
+!CHECK: %[[A:.*]] = fir.undefined i32
+!CHECK: fir.has_value %[[A]] : i32
+!CHECK: }
+
+program main
+ integer :: a
+ !$omp threadprivate(a)
+ call sub()
+contains
+ subroutine sub()
+ !$omp parallel default(none)
+ print *, a
+ !$omp end parallel
+ end
+end
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the fix!
A semantics test (debug-dump-symbols or debug-unparse-with-symbols) would be better here. |
Hm. I have copied one of the existing tests for host associated threadprivate variables. I'll have a look to see if I can extend these tests, too. Would you oppose approving with these extensions? |
A semantics change is best tested with a semantics test. I am fine with the extension. Approving in advance. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LG.
Looking at making the semantics checks a separate PR now. |
When a host associated
threadprivate
variable was used in a parallel region withdefault(none)
in an internal subroutine was failing, because the compiler did not properly determine that the variable was pre-determinedthreadprivate
and thus should not have been reported as missing a DSA.