Skip to content

Commit 53b5902

Browse files
authored
[flang][OpenMP] Implement copyin for pointers and allocatables. (#107425)
The copyin clause currently forbids pointer and allocatable variables, which are allowed by the OpenMP 1.1 and 3.0 specifications respectively.
1 parent 2459679 commit 53b5902

File tree

3 files changed

+99
-6
lines changed

3 files changed

+99
-6
lines changed

flang/lib/Lower/Bridge.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1261,9 +1261,10 @@ class FirConverter : public Fortran::lower::AbstractConverter {
12611261
auto loadVal = builder->create<fir::LoadOp>(loc, rhs);
12621262
builder->create<fir::StoreOp>(loc, loadVal, lhs);
12631263
} else if (isAllocatable &&
1264-
flags.test(Fortran::semantics::Symbol::Flag::OmpFirstPrivate)) {
1265-
// For firstprivate allocatable variables, RHS must be copied only when
1266-
// LHS is allocated.
1264+
(flags.test(Fortran::semantics::Symbol::Flag::OmpFirstPrivate) ||
1265+
flags.test(Fortran::semantics::Symbol::Flag::OmpCopyIn))) {
1266+
// For firstprivate and copyin allocatable variables, RHS must be copied
1267+
// only when LHS is allocated.
12671268
hlfir::Entity temp =
12681269
hlfir::derefPointersAndAllocatables(loc, *builder, lhs);
12691270
mlir::Value addr = hlfir::genVariableRawAddress(loc, *builder, temp);

flang/lib/Lower/OpenMP/ClauseProcessor.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -619,9 +619,7 @@ bool ClauseProcessor::processCopyin() const {
619619
checkAndCopyHostAssociateVar(&*mem, &insPt);
620620
break;
621621
}
622-
if (semantics::IsAllocatableOrObjectPointer(&sym->GetUltimate()))
623-
TODO(converter.getCurrentLocation(),
624-
"pointer or allocatable variables in Copyin clause");
622+
625623
assert(sym->has<semantics::HostAssocDetails>() &&
626624
"No host-association found");
627625
checkAndCopyHostAssociateVar(sym);

flang/test/Lower/OpenMP/copyin.f90

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,3 +356,97 @@ subroutine common_2()
356356
end do
357357
!$omp end parallel do
358358
end subroutine
359+
360+
! CHECK-LABEL: func.func @_QPpointer() {
361+
! CHECK: %[[VAL_0:.*]] = fir.address_of(@_QFpointerEp) : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>
362+
! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFpointerEp"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>)
363+
! CHECK: %[[VAL_2:.*]] = omp.threadprivate %[[VAL_1]]#1 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>> -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>
364+
! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFpointerEp"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>)
365+
! CHECK: omp.parallel {
366+
! CHECK: %[[VAL_4:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?xi32>>> {pinned}
367+
! CHECK: %[[VAL_5:.*]] = omp.threadprivate %[[VAL_1]]#1 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>> -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>
368+
! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_5]] {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFpointerEp"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>)
369+
! CHECK: %[[VAL_7:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>
370+
! CHECK: fir.store %[[VAL_7]] to %[[VAL_6]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>
371+
! CHECK: omp.barrier
372+
! CHECK: %[[VAL_8:.*]] = fir.load %[[VAL_6]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>
373+
! CHECK: %[[VAL_9:.*]]:2 = hlfir.copy_in %[[VAL_8]] to %[[VAL_4]] : (!fir.box<!fir.ptr<!fir.array<?xi32>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> (!fir.box<!fir.ptr<!fir.array<?xi32>>>, i1)
374+
! CHECK: %[[VAL_10:.*]] = fir.box_addr %[[VAL_9]]#0 : (!fir.box<!fir.ptr<!fir.array<?xi32>>>) -> !fir.ptr<!fir.array<?xi32>>
375+
! CHECK: %[[VAL_11:.*]] = fir.convert %[[VAL_10]] : (!fir.ptr<!fir.array<?xi32>>) -> !fir.ref<!fir.array<?xi32>>
376+
! CHECK: fir.call @_QPsub7(%[[VAL_11]]) fastmath<contract> : (!fir.ref<!fir.array<?xi32>>) -> ()
377+
! CHECK: hlfir.copy_out %[[VAL_4]], %[[VAL_9]]#1 to %[[VAL_8]] : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, i1, !fir.box<!fir.ptr<!fir.array<?xi32>>>) -> ()
378+
! CHECK: omp.terminator
379+
! CHECK: }
380+
! CHECK: return
381+
! CHECK: }
382+
subroutine pointer()
383+
integer, pointer, save :: p(:)
384+
!$omp threadprivate(p)
385+
386+
!$omp parallel copyin(p)
387+
call sub7(p)
388+
!$omp end parallel
389+
end subroutine
390+
391+
! CHECK-LABEL: func.func @_QPallocatable() {
392+
! CHECK: %[[VAL_0:.*]] = fir.address_of(@_QFallocatableEp) : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
393+
! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFallocatableEp"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>)
394+
! CHECK: %[[VAL_2:.*]] = omp.threadprivate %[[VAL_1]]#1 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
395+
! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFallocatableEp"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>)
396+
! CHECK: omp.parallel {
397+
! CHECK: %[[VAL_4:.*]] = omp.threadprivate %[[VAL_1]]#1 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
398+
! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]] {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFallocatableEp"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>)
399+
! CHECK: %[[VAL_6:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
400+
! CHECK: hlfir.assign %[[VAL_6]] to %[[VAL_5]]#0 realloc : !fir.box<!fir.heap<!fir.array<?xi32>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
401+
! CHECK: omp.barrier
402+
! CHECK: %[[VAL_7:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
403+
! CHECK: %[[VAL_8:.*]] = fir.box_addr %[[VAL_7]] : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>>
404+
! CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_8]] : (!fir.heap<!fir.array<?xi32>>) -> !fir.ref<!fir.array<?xi32>>
405+
! CHECK: fir.call @_QPsub8(%[[VAL_9]]) fastmath<contract> : (!fir.ref<!fir.array<?xi32>>) -> ()
406+
! CHECK: omp.terminator
407+
! CHECK: }
408+
! CHECK: return
409+
! CHECK: }
410+
subroutine allocatable()
411+
integer, allocatable, save :: p(:)
412+
!$omp threadprivate(p)
413+
414+
!$omp parallel copyin(p)
415+
call sub8(p)
416+
!$omp end parallel
417+
end subroutine
418+
419+
! CHECK-LABEL: func.func @_QPallocatable2() {
420+
! CHECK: %[[VAL_0:.*]] = fir.address_of(@_QFallocatable2Ea) : !fir.ref<!fir.box<!fir.heap<i32>>>
421+
! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFallocatable2Ea"} : (!fir.ref<!fir.box<!fir.heap<i32>>>) -> (!fir.ref<!fir.box<!fir.heap<i32>>>, !fir.ref<!fir.box<!fir.heap<i32>>>)
422+
! CHECK: %[[VAL_2:.*]] = omp.threadprivate %[[VAL_1]]#1 : !fir.ref<!fir.box<!fir.heap<i32>>> -> !fir.ref<!fir.box<!fir.heap<i32>>>
423+
! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFallocatable2Ea"} : (!fir.ref<!fir.box<!fir.heap<i32>>>) -> (!fir.ref<!fir.box<!fir.heap<i32>>>, !fir.ref<!fir.box<!fir.heap<i32>>>)
424+
! CHECK: omp.parallel {
425+
! CHECK: %[[VAL_4:.*]] = omp.threadprivate %[[VAL_1]]#1 : !fir.ref<!fir.box<!fir.heap<i32>>> -> !fir.ref<!fir.box<!fir.heap<i32>>>
426+
! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]] {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFallocatable2Ea"} : (!fir.ref<!fir.box<!fir.heap<i32>>>) -> (!fir.ref<!fir.box<!fir.heap<i32>>>, !fir.ref<!fir.box<!fir.heap<i32>>>)
427+
! CHECK: %[[VAL_6:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref<!fir.box<!fir.heap<i32>>>
428+
! CHECK: %[[VAL_7:.*]] = fir.box_addr %[[VAL_6]] : (!fir.box<!fir.heap<i32>>) -> !fir.heap<i32>
429+
! CHECK: %[[VAL_8:.*]] = fir.convert %[[VAL_7]] : (!fir.heap<i32>) -> i64
430+
! CHECK: %[[VAL_9:.*]] = arith.constant 0 : i64
431+
! CHECK: %[[VAL_10:.*]] = arith.cmpi ne, %[[VAL_8]], %[[VAL_9]] : i64
432+
! CHECK: fir.if %[[VAL_10]] {
433+
! CHECK: %[[VAL_11:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<!fir.box<!fir.heap<i32>>>
434+
! CHECK: %[[VAL_12:.*]] = fir.box_addr %[[VAL_11]] : (!fir.box<!fir.heap<i32>>) -> !fir.heap<i32>
435+
! CHECK: %[[VAL_13:.*]] = fir.load %[[VAL_12]] : !fir.heap<i32>
436+
! CHECK: hlfir.assign %[[VAL_13]] to %[[VAL_5]]#0 realloc : i32, !fir.ref<!fir.box<!fir.heap<i32>>>
437+
! CHECK: }
438+
! CHECK: omp.barrier
439+
! CHECK: %[[VAL_14:.*]] = arith.constant 1 : i32
440+
! CHECK: hlfir.assign %[[VAL_14]] to %[[VAL_5]]#0 realloc : i32, !fir.ref<!fir.box<!fir.heap<i32>>>
441+
! CHECK: omp.terminator
442+
! CHECK: }
443+
! CHECK: return
444+
! CHECK: }
445+
subroutine allocatable2()
446+
integer, allocatable, save :: a
447+
!$omp threadprivate(a)
448+
449+
!$omp parallel copyin(a)
450+
a = 1
451+
!$omp end parallel
452+
end subroutine

0 commit comments

Comments
 (0)