Skip to content

Commit 34bab84

Browse files
committed
[flang][OpenMP] Implement copyin for pointers and allocatables.
The copyin clause currently forbids pointer and allocatable variables, which are allowed by the OpenMP 1.1 and 3.0 specifications respectively. For pointer variables it is sufficient to remove the check to get correct behaviour. For allocatables we need to ensure that the master thread allocatable is assigned to all of the threads, so we add an hlfir.assign.
1 parent 9e9971b commit 34bab84

File tree

4 files changed

+94
-4
lines changed

4 files changed

+94
-4
lines changed

flang/include/flang/Lower/AbstractConverter.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,9 @@ class AbstractConverter {
326326
virtual Fortran::lower::SymbolBox
327327
lookupOneLevelUpSymbol(const Fortran::semantics::Symbol &sym) = 0;
328328

329+
virtual Fortran::lower::SymbolBox
330+
shallowLookupSymbol(const Fortran::semantics::Symbol &sym) = 0;
331+
329332
/// Return the mlir::SymbolTable associated to the ModuleOp.
330333
/// Look-ups are faster using it than using module.lookup<>,
331334
/// but the module op should be queried in case of failure

flang/lib/Lower/Bridge.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1175,7 +1175,7 @@ class FirConverter : public Fortran::lower::AbstractConverter {
11751175

11761176
/// Find the symbol in the inner-most level of the local map or return null.
11771177
Fortran::lower::SymbolBox
1178-
shallowLookupSymbol(const Fortran::semantics::Symbol &sym) {
1178+
shallowLookupSymbol(const Fortran::semantics::Symbol &sym) override {
11791179
if (Fortran::lower::SymbolBox v = localSymbols.shallowLookupSymbol(sym))
11801180
return v;
11811181
return {};

flang/lib/Lower/OpenMP/ClauseProcessor.cpp

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "Clauses.h"
1515

1616
#include "flang/Lower/PFTBuilder.h"
17+
#include "flang/Lower/SymbolMap.h"
1718
#include "flang/Parser/tools.h"
1819
#include "flang/Semantics/tools.h"
1920
#include "llvm/Frontend/OpenMP/OMPIRBuilder.h"
@@ -619,9 +620,28 @@ bool ClauseProcessor::processCopyin() const {
619620
checkAndCopyHostAssociateVar(&*mem, &insPt);
620621
break;
621622
}
622-
if (semantics::IsAllocatableOrObjectPointer(&sym->GetUltimate()))
623-
TODO(converter.getCurrentLocation(),
624-
"pointer or allocatable variables in Copyin clause");
623+
if (semantics::IsAllocatable(sym->GetUltimate())) {
624+
// copyin should copy the association of the allocatable
625+
626+
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
627+
const Fortran::semantics::Symbol &hsym = sym->GetUltimate();
628+
629+
Fortran::lower::SymbolBox hsb =
630+
converter.lookupOneLevelUpSymbol(hsym);
631+
assert(hsb && "Host symbol box not found");
632+
633+
Fortran::lower::SymbolBox sb = converter.shallowLookupSymbol(*sym);
634+
assert(sb && "Host-associated symbol box not found");
635+
assert(hsb.getAddr() != sb.getAddr() &&
636+
"Host and associated symbol boxes are the same");
637+
638+
mlir::Location loc = converter.genLocation(sym->name());
639+
mlir::OpBuilder::InsertionGuard ipGuard{builder};
640+
builder.setInsertionPointAfter(sb.getAddr().getDefiningOp());
641+
builder.create<hlfir::AssignOp>(loc, hsb.getAddr(), sb.getAddr(),
642+
true, false, false);
643+
}
644+
625645
assert(sym->has<semantics::HostAssocDetails>() &&
626646
"No host-association found");
627647
checkAndCopyHostAssociateVar(sym);

flang/test/Lower/OpenMP/copyin.f90

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,3 +356,70 @@ 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_5]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
400+
! CHECK: %[[VAL_7:.*]] = fir.box_addr %[[VAL_6]] : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>>
401+
! CHECK: %[[VAL_8:.*]] = fir.convert %[[VAL_7]] : (!fir.heap<!fir.array<?xi32>>) -> i64
402+
! CHECK: %[[VAL_9:.*]] = arith.constant 0 : i64
403+
! CHECK: %[[VAL_10:.*]] = arith.cmpi ne, %[[VAL_8]], %[[VAL_9]] : i64
404+
! CHECK: fir.if %[[VAL_10]] {
405+
! CHECK: %[[VAL_11:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
406+
! CHECK: hlfir.assign %[[VAL_11]] to %[[VAL_6]] temporary_lhs : !fir.box<!fir.heap<!fir.array<?xi32>>>, !fir.box<!fir.heap<!fir.array<?xi32>>>
407+
! CHECK: }
408+
! CHECK: hlfir.assign %[[VAL_3]]#0 to %[[VAL_5]]#0 realloc : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
409+
! CHECK: omp.barrier
410+
! CHECK: %[[VAL_12:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
411+
! CHECK: %[[VAL_13:.*]] = fir.box_addr %[[VAL_12]] : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>>
412+
! CHECK: %[[VAL_14:.*]] = fir.convert %[[VAL_13]] : (!fir.heap<!fir.array<?xi32>>) -> !fir.ref<!fir.array<?xi32>>
413+
! CHECK: fir.call @_QPsub8(%[[VAL_14]]) fastmath<contract> : (!fir.ref<!fir.array<?xi32>>) -> ()
414+
! CHECK: omp.terminator
415+
! CHECK: }
416+
! CHECK: return
417+
! CHECK: }
418+
subroutine allocatable()
419+
integer, allocatable, save :: p(:)
420+
!$omp threadprivate(p)
421+
422+
!$omp parallel copyin(p)
423+
call sub8(p)
424+
!$omp end parallel
425+
end subroutine

0 commit comments

Comments
 (0)