<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/84561>84561</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
[flang][OpenMP] Host threadprivate variable is not being treated as such in subroutine
</td>
</tr>
<tr>
<th>Labels</th>
<td>
flang
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
luporl
</td>
</tr>
</table>
<pre>
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.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzsV01v4zYT_jX0ZRCDIm3ZPviQxDHe91B0W_RuUNJYmi5FqiTlNP--ICU5SuMERdEWe9ggUBDymZlnPjVS3lNtEPds_cDWh4XqQ2PdXveddXpR2Opl_0uDENAH6JytnWqhQG2f4Vl5wN87LANWECx0jkyADM7WgdIaQuNQVZ6JRyj6ABSA_AAiU0MG1uiXBLYGwZ4hRDOjjLxn_MD49Mz5-Jv-nWi0isxwAtR2mkoKYKzB8QzIBKzRRQJeXRCiVnkPBEwegE8oJjImVrbtRuOdo4sKyMSWmNjNacygnXJKa9STkjI6fLb2vdLSUaBSXZFDlJi4j7ToPR5N9U7m7e1b28OztCYoMn6S8H3hbB_IYGIltldXAOb6PJla4-vNEJvsFjSaHuBQ2u7lVphgAF1tD6eJ85Cym-m8HkamOWdi4-H4_59jtbTko0lQBljObdst3-Yo52A7dCqQNaBMFWX6JBGLyTqqySgdZSliL8qRKjQCGR9QVZ-XGcC5N-UyPmA0CGzFTz8dv1xjCioER0Uf0APbPJzJLWPVOaP0qXO2jEnW-tIuNZmvqsYUXibk_IzJx0mGySe2OURN8wyseRKLylVVOfT-ZM_RfiLzFOMfazvmKmIcnqNKKaK2uZqMyXuRVDU6AisstXI4Wtg89IZ-OxnVTizFqF0kTsnA9pYNsYM7Jp8-vH68yWxekDGzN2srsRaSjwZW_BTvTyTFhx7HYMzjl1wvs1HmAMpRaJalNT6oNK_STJBilBhCM0zFmWSwcOUyCXzg2Mxyqlh0LRkVrJumyObwinEYemeujT5d3WyRhxdolemV1i-gquovNwYT29gbQ2NQ8ODQ9zpcu0DsoiuxY6bJ-mzdVw-z-f69U76RTmFiPRB7l_OpPrOPPJxMf-66_Nh18e0OCfnfDon08-mkkP_EpAD4ZFh8Pivizkbe9wiVRW-Y2ATwiC041Gpc2FjO54GMr97H2PQ2NOjAU0tauWkmeFDaW_CNfU6jwscSKLBRF7Lu-772r-5rf9rK_v6S9VoVKZmN6jo0HmhYvuOaNFrKOehIhjw8u4iq4tuCKgQVYVeXcg4VOSwDXXC5qPay2smdWuA-2_DdTvJsKxfNXm1ywfF8LqvNruRbnuWF4ltZKNzyElebBe0FFysu-VZwmQu5XO-w3G2rYl1tzlkud2zFsVWkl-l1YF29SG7st6t1ni20KlD79AUjxFkrU8d5tD4s3D7i74q-9mzFNfngXzUECjp99gwS6wNbP_zYofnhC1sf4H_Wh7cVNlsfPRgboMC0aTpMDaU8-L5sgMwsOYve6X0TQpc-acSRiWNNoemLZWlbJo6RzPjnrnP2VywDE8fkm2fimNz7IwAA__-6QfBV">