Closed
Description
The test program below was expected to print 1 for all threads, but it is printing 1 only for one of the threads:
program main
implicit none
integer, save :: i = 0
!$omp threadprivate(i)
!$omp parallel
call foo
!$omp critical
print *, i
!$omp end critical
!$omp end parallel
contains
subroutine foo()
!$omp single
i = 1
!$omp end single copyprivate(i)
end subroutine
end program
foo
's FIR is missing an omp.threadprivate
operation and is using the original i
variable instead:
func.func private @_QFPfoo() attributes {fir.internal_proc, llvm.linkage = #llvm.linkage<internal>} {
%0 = fir.address_of(@_QFEi) : !fir.ref<i32>
%1:2 = hlfir.declare %0 {uniq_name = "_QFEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
omp.single copyprivate(%1#0 -> @_copy_i32 : !fir.ref<i32>) {
%c1_i32 = arith.constant 1 : i32
hlfir.assign %c1_i32 to %1#0 : i32, !fir.ref<i32>
omp.terminator
}
return
}
By manually adding an omp.threadprivate
operation (and using its result instead), the program works as expected:
func.func private @_QFPfoo() attributes {fir.internal_proc, llvm.linkage = #llvm.linkage<internal>} {
%0 = fir.address_of(@_QFEi) : !fir.ref<i32>
%1:2 = hlfir.declare %0 {uniq_name = "_QFEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
%2 = omp.threadprivate %1#1 : !fir.ref<i32> -> !fir.ref<i32>
%3:2 = hlfir.declare %2 {uniq_name = "_QFEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
omp.single copyprivate(%3#0 -> @_copy_i32 : !fir.ref<i32>) {
%c1_i32 = arith.constant 1 : i32
hlfir.assign %c1_i32 to %3#0 : i32, !fir.ref<i32>
omp.terminator
}
return
}
The issue doesn't seem related to copyprivate
, as other similar programs also show the same behavior:
program main
implicit none
integer, save :: i = 0
!$omp threadprivate(i)
!$omp parallel
call foo
!$omp critical
print *, i
!$omp end critical
!$omp end parallel
contains
subroutine foo()
i = 1
end subroutine
end program
The issue also happens if the i = 1
line is wrapped inside a parallel
directive.