-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[flang][OpenMP] Initialize allocatable members of derived types #120295
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
Merged
Merged
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
! Test that derived type allocatable members of private copies are properly | ||
! initialized. | ||
!RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s | ||
|
||
module m1 | ||
type x | ||
integer, allocatable :: x1(:) | ||
end type | ||
|
||
type y | ||
integer :: y1(10) | ||
end type | ||
|
||
contains | ||
|
||
!CHECK-LABEL: omp.private {type = private} @_QMm1Ftest_nested | ||
!CHECK: fir.call @_FortranAInitializeClone | ||
!CHECK-NEXT: omp.yield | ||
|
||
!CHECK-LABEL: omp.private {type = private} @_QMm1Ftest_array_of_allocs | ||
!CHECK: fir.call @_FortranAInitializeClone | ||
!CHECK-NEXT: omp.yield | ||
|
||
!CHECK-LABEL: omp.private {type = firstprivate} @_QMm1Ftest_array | ||
!CHECK-NOT: fir.call @_FortranAInitializeClone | ||
!CHECK: omp.yield | ||
|
||
!CHECK-LABEL: omp.private {type = private} @_QMm1Ftest_array | ||
!CHECK: fir.call @_FortranAInitializeClone | ||
!CHECK-NEXT: omp.yield | ||
|
||
!CHECK-LABEL: omp.private {type = private} @_QMm1Ftest_scalar | ||
!CHECK: fir.call @_FortranAInitializeClone | ||
!CHECK-NEXT: omp.yield | ||
|
||
subroutine test_scalar() | ||
type(x) :: v | ||
allocate(v%x1(5)) | ||
|
||
!$omp parallel private(v) | ||
!$omp end parallel | ||
end subroutine | ||
|
||
! Test omp sections lastprivate(v, v2) | ||
! - InitializeClone must not be called for v2, that doesn't have an | ||
! allocatable member. | ||
! - InitializeClone must be called for v, that has an allocatable member. | ||
! - To avoid race conditions between InitializeClone and lastprivate, a | ||
! barrier must be present after the initializations. | ||
!CHECK-LABEL: func @_QMm1Ptest_array | ||
!CHECK: fir.call @_FortranAInitializeClone | ||
!CHECK-NEXT: omp.barrier | ||
subroutine test_array() | ||
type(x) :: v(10) | ||
type(y) :: v2(10) | ||
allocate(v(1)%x1(5)) | ||
|
||
!$omp parallel private(v) | ||
!$omp end parallel | ||
|
||
!$omp parallel | ||
!$omp sections lastprivate(v2, v) | ||
!$omp end sections | ||
!$omp end parallel | ||
|
||
!$omp parallel firstprivate(v) | ||
!$omp end parallel | ||
end subroutine | ||
|
||
subroutine test_array_of_allocs() | ||
type(x), allocatable :: v(:) | ||
allocate(v(10)) | ||
allocate(v(1)%x1(5)) | ||
|
||
!$omp parallel private(v) | ||
!$omp end parallel | ||
end subroutine | ||
|
||
subroutine test_nested() | ||
type dt1 | ||
integer, allocatable :: a(:) | ||
end type | ||
|
||
type dt2 | ||
type(dt1) :: d1 | ||
end type | ||
|
||
type(dt2) :: d2 | ||
allocate(d2%d1%a(10)) | ||
|
||
!$omp parallel private(d2) | ||
!$omp end parallel | ||
end subroutine | ||
end module |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.
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.
@luporl Why don't we need this barrier in other cases, e.g. when
FortranAInitialize
(not the clone variant) is used?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.
Because
FortranAInitializeClone
receives an extra argument, that is the original variable.When
lastprivate
is used, the original variable is modified by one of the running threads. Without the barrier, another thread may still be using it to initialize its copy.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.
The original variable is also used for other similar cases e.g. assumed shape arrays. Maybe for now we should always use the barrier?
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.
This will likely affect performance, but it is certainly better than having hard-to-debug race conditions.
I'm OK with it as a temporary fix.
Later, we could rename
callsInitClone
toneedsBarrier
and set it whenever a given operation may modify a variable that is also read by other threads.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.
Do I understand correctly that the barrier here isn't strictly necessary because v and v2 are different symbols?
https://github.com/llvm/llvm-project/pull/120295/files#diff-7f918db826ee2c02ce8eb509f6d8367ad741d2b1537396959d510b5fe6a29a37R52
I'm trying to add the extra barriers in my re-implementation of this patch in my changes for https://discourse.llvm.org/t/rfc-openmp-supporting-delayed-task-execution-with-firstprivate-variables/83084/7
Thanks for the help!
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.
The barrier there is necessary. It prevents the original
v
variable from being updated bylastprivate
before every thread has finished initializing its private copy ofv
(using the original variablev
).As
v2
doesn't have an allocatable member,InitializeClone
doesn't need to be called for it.If it was the only symbol, as it is just written by
lastprivate
but not read by other threads, no barrier would be needed.And if both
v
andv2
had allocatable members, a single barrier after the initialization of both would be enough, as their original variables are not read by any threads after that, but only written bylastprivate
later.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!