[Flang][OpenMP] Support iterator modifier in depend clause (#189412)
Lower the iterator modifier on depend clause to omp.iterator. Iterated depend objects emit `!omp.iterated<!llvm.ptr>` by using `getDataOperandBaseAddr` to generate base address and `genIteratorCoordinate` to get the addr+offset. The non-iterated objects in depend clause still use existing lowering path. This patch is part of feature work for #188061. Assisted with copilot.
This commit is contained in:
parent
7ff0dc4b9f
commit
85d7927c08
@ -1289,16 +1289,14 @@ bool ClauseProcessor::processDepend(lower::SymMap &symMap,
|
||||
auto depType = std::get<clause::DependenceType>(clause.t);
|
||||
auto &objects = std::get<omp::ObjectList>(clause.t);
|
||||
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
|
||||
mlir::Location clauseLocation = converter.getCurrentLocation();
|
||||
|
||||
if (std::get<std::optional<omp::clause::Iterator>>(clause.t)) {
|
||||
TODO(converter.getCurrentLocation(),
|
||||
"Support for iterator modifiers is not implemented yet");
|
||||
}
|
||||
mlir::omp::ClauseTaskDependAttr dependTypeOperand =
|
||||
genDependKindAttr(converter, depType);
|
||||
result.dependKinds.append(objects.size(), dependTypeOperand);
|
||||
|
||||
for (const omp::Object &object : objects) {
|
||||
auto genDependVar =
|
||||
[&](const omp::Object &object, lower::SymMap &localSymMap,
|
||||
lower::StatementContext &localStmtCtx) -> mlir::Value {
|
||||
assert(object.ref() && "Expecting designator");
|
||||
mlir::Value dependVar;
|
||||
SomeExpr expr = *object.ref();
|
||||
@ -1311,18 +1309,18 @@ bool ClauseProcessor::processDepend(lower::SymMap &symMap,
|
||||
// don't need an accurate length for the array section because the
|
||||
// OpenMP standard forbids overlapping array sections.
|
||||
dependVar = genVectorSubscriptedDesignatorFirstElementAddress(
|
||||
converter.getCurrentLocation(), converter, expr, symMap, stmtCtx);
|
||||
clauseLocation, converter, expr, localSymMap, localStmtCtx);
|
||||
} else {
|
||||
// Ordinary array section e.g. A(1:512:2)
|
||||
hlfir::EntityWithAttributes entity = convertExprToHLFIR(
|
||||
converter.getCurrentLocation(), converter, expr, symMap, stmtCtx);
|
||||
clauseLocation, converter, expr, localSymMap, localStmtCtx);
|
||||
dependVar = entity.getBase();
|
||||
}
|
||||
} else if (evaluate::isStructureComponent(expr) ||
|
||||
evaluate::ExtractComplexPart(expr)) {
|
||||
SomeExpr expr = *object.ref();
|
||||
hlfir::EntityWithAttributes entity = convertExprToHLFIR(
|
||||
converter.getCurrentLocation(), converter, expr, symMap, stmtCtx);
|
||||
clauseLocation, converter, expr, localSymMap, localStmtCtx);
|
||||
dependVar = entity.getBase();
|
||||
} else {
|
||||
semantics::Symbol *sym = object.sym();
|
||||
@ -1335,8 +1333,7 @@ bool ClauseProcessor::processDepend(lower::SymMap &symMap,
|
||||
// allocations so this is not a reliable way to identify the dependency.
|
||||
if (auto ref = mlir::dyn_cast<fir::ReferenceType>(dependVar.getType()))
|
||||
if (fir::isa_box_type(ref.getElementType()))
|
||||
dependVar = fir::LoadOp::create(
|
||||
builder, converter.getCurrentLocation(), dependVar);
|
||||
dependVar = fir::LoadOp::create(builder, clauseLocation, dependVar);
|
||||
|
||||
// The openmp dialect doesn't know what to do with boxes (and it would
|
||||
// break layering to teach it about them). The dependency variable can be
|
||||
@ -1345,10 +1342,62 @@ bool ClauseProcessor::processDepend(lower::SymMap &symMap,
|
||||
// Getting the address of the box data is okay because all the runtime
|
||||
// ultimately cares about is the base address of the array.
|
||||
if (fir::isa_box_type(dependVar.getType()))
|
||||
dependVar = fir::BoxAddrOp::create(
|
||||
builder, converter.getCurrentLocation(), dependVar);
|
||||
dependVar = fir::BoxAddrOp::create(builder, clauseLocation, dependVar);
|
||||
|
||||
result.dependVars.push_back(dependVar);
|
||||
return dependVar;
|
||||
};
|
||||
|
||||
auto &iteratorModifier =
|
||||
std::get<std::optional<omp::clause::Iterator>>(clause.t);
|
||||
|
||||
llvm::SmallVector<IteratorRange> iteratorRanges;
|
||||
llvm::SmallPtrSet<const Fortran::semantics::Symbol *, 4> ivSyms;
|
||||
collectIteratorIVs(clause, converter, stmtCtx, iteratorRanges, ivSyms);
|
||||
|
||||
mlir::Type ptrTy =
|
||||
mlir::LLVM::LLVMPointerType::get(&converter.getMLIRContext());
|
||||
mlir::Type iterTy =
|
||||
mlir::omp::IteratedType::get(&converter.getMLIRContext(), ptrTy);
|
||||
|
||||
for (const omp::Object &object : objects) {
|
||||
if (iteratorModifier.has_value() &&
|
||||
hasIteratorIVReference(object, ivSyms)) {
|
||||
mlir::Value iterHandle = buildIteratorOp(
|
||||
converter, clauseLocation, iterTy, iteratorRanges,
|
||||
[&](fir::FirOpBuilder &builder, mlir::Location loc,
|
||||
llvm::ArrayRef<mlir::Value> /*ivs*/) -> mlir::Value {
|
||||
lower::StatementContext iterStmtCtx;
|
||||
if (std::optional<llvm::SmallVector<mlir::Value>> loweredIndices =
|
||||
getIteratorElementIndices(converter, object, iterStmtCtx,
|
||||
loc)) {
|
||||
const Fortran::semantics::Symbol *sym = object.sym();
|
||||
assert(sym && "expected symbol for iterator object");
|
||||
// We currently cannot reuse genDependVar here because
|
||||
// buildIteratorOp maps iterator IV symbols to bare scalar
|
||||
// values (e.g. i32), but genDependVar uses convertExprToHLFIR
|
||||
// which expects memory-backed references. Instead, manually get
|
||||
// the base address and compute the element coordinate from the
|
||||
// FIR-level lowered indices.
|
||||
fir::factory::AddrAndBoundsInfo info =
|
||||
Fortran::lower::getDataOperandBaseAddr(
|
||||
converter, builder, *sym, loc,
|
||||
/*unwrapFirBox=*/false);
|
||||
hlfir::Entity entity{info.addr};
|
||||
mlir::Value iteratedAddr = genIteratorCoordinate(
|
||||
converter, entity, *loweredIndices, loc);
|
||||
// Convert to !llvm.ptr for the omp.yield
|
||||
return fir::ConvertOp::create(builder, loc, ptrTy,
|
||||
iteratedAddr);
|
||||
}
|
||||
|
||||
TODO(loc, "object type not supported by iterator modifier");
|
||||
});
|
||||
result.dependIterated.push_back(iterHandle);
|
||||
result.dependIteratedKinds.push_back(dependTypeOperand);
|
||||
} else {
|
||||
result.dependVars.push_back(genDependVar(object, symMap, stmtCtx));
|
||||
result.dependKinds.push_back(dependTypeOperand);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -1,10 +0,0 @@
|
||||
!RUN: %not_todo_cmd bbc -emit-hlfir -fopenmp -fopenmp-version=50 -o - %s 2>&1 | FileCheck %s
|
||||
!RUN: %not_todo_cmd %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=50 -o - %s 2>&1 | FileCheck %s
|
||||
|
||||
!CHECK: Support for iterator modifiers is not implemented yet
|
||||
subroutine f00(x)
|
||||
integer :: x(10)
|
||||
!$omp task depend(iterator(i = 1:10), in: x(i))
|
||||
x = 0
|
||||
!$omp end task
|
||||
end
|
||||
439
flang/test/Lower/OpenMP/depend-iterator.f90
Normal file
439
flang/test/Lower/OpenMP/depend-iterator.f90
Normal file
@ -0,0 +1,439 @@
|
||||
! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 -o - %s | FileCheck %s
|
||||
|
||||
! Tests for the iterator modifier on the depend clause across all directives
|
||||
! that Flang currently supports: task, target, target enter data, target exit data,
|
||||
! and target update.
|
||||
! TODO: We need to add iterator test for taskwait, depobj, interop once they are
|
||||
! supported.
|
||||
|
||||
!===============================================================================
|
||||
! task
|
||||
!===============================================================================
|
||||
|
||||
subroutine task_depend_iterator_simple()
|
||||
integer, parameter :: n = 16
|
||||
integer :: a(n)
|
||||
integer :: i
|
||||
|
||||
!$omp task depend(iterator(i = 1:n), in: a(i))
|
||||
!$omp end task
|
||||
end subroutine
|
||||
|
||||
! CHECK-LABEL: func.func @_QPtask_depend_iterator_simple()
|
||||
! CHECK: %[[A:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) {uniq_name = "_QFtask_depend_iterator_simpleEa"}
|
||||
! CHECK: %[[IT:.*]] = omp.iterator(%[[IV:.*]]: index) = ({{.*}} to {{.*}} step {{.*}}) {
|
||||
! CHECK: %[[IV_I32:.*]] = fir.convert %[[IV]] : (index) -> i32
|
||||
! CHECK: %[[IV_I64:.*]] = fir.convert %[[IV_I32]] : (i32) -> i64
|
||||
! CHECK: %[[SHAPE:.*]] = fir.shape %c16 : (index) -> !fir.shape<1>
|
||||
! CHECK: %[[COOR:.*]] = fir.array_coor %[[A]]#0(%[[SHAPE]]) %[[IV_I64]] : (!fir.ref<!fir.array<16xi32>>, !fir.shape<1>, i64) -> !fir.ref<i32>
|
||||
! CHECK: %[[PTR:.*]] = fir.convert %[[COOR]] : (!fir.ref<i32>) -> !llvm.ptr
|
||||
! CHECK: omp.yield(%[[PTR]] : !llvm.ptr)
|
||||
! CHECK: } -> !omp.iterated<!llvm.ptr>
|
||||
! CHECK: omp.task depend(taskdependin -> %[[IT]] : !omp.iterated<!llvm.ptr>) {
|
||||
! CHECK: omp.terminator
|
||||
! CHECK: }
|
||||
|
||||
subroutine task_depend_iterator_2d()
|
||||
integer, parameter :: n = 4, m = 6
|
||||
integer :: a(n, m)
|
||||
integer :: i, j
|
||||
|
||||
!$omp task depend(iterator(i = 1:n, j = 1:m), inout: a(i, j))
|
||||
!$omp end task
|
||||
end subroutine
|
||||
|
||||
! CHECK-LABEL: func.func @_QPtask_depend_iterator_2d()
|
||||
! CHECK: %[[IT:.*]] = omp.iterator(%[[IV0:.*]]: index, %[[IV1:.*]]: index) = ({{.*}} to {{.*}} step {{.*}}, {{.*}} to {{.*}} step {{.*}}) {
|
||||
! CHECK: %[[IV0_I32:.*]] = fir.convert %[[IV0]] : (index) -> i32
|
||||
! CHECK: %[[IV1_I32:.*]] = fir.convert %[[IV1]] : (index) -> i32
|
||||
! CHECK: %[[IV0_I64:.*]] = fir.convert %[[IV0_I32]] : (i32) -> i64
|
||||
! CHECK: %[[IV1_I64:.*]] = fir.convert %[[IV1_I32]] : (i32) -> i64
|
||||
! CHECK: %[[SHAPE:.*]] = fir.shape %c4, %c6 : (index, index) -> !fir.shape<2>
|
||||
! CHECK: %[[COOR:.*]] = fir.array_coor %{{.*}}(%[[SHAPE]]) %[[IV0_I64]], %[[IV1_I64]] : (!fir.ref<!fir.array<4x6xi32>>, !fir.shape<2>, i64, i64) -> !fir.ref<i32>
|
||||
! CHECK: %[[PTR:.*]] = fir.convert %[[COOR]] : (!fir.ref<i32>) -> !llvm.ptr
|
||||
! CHECK: omp.yield(%[[PTR]] : !llvm.ptr)
|
||||
! CHECK: } -> !omp.iterated<!llvm.ptr>
|
||||
! CHECK: omp.task depend(taskdependinout -> %[[IT]] : !omp.iterated<!llvm.ptr>) {
|
||||
|
||||
subroutine task_depend_iterator_mixed()
|
||||
integer, parameter :: n = 16
|
||||
integer :: a(n), x
|
||||
integer :: i
|
||||
|
||||
!$omp task depend(iterator(i = 1:n), in: a(i)) depend(out: x)
|
||||
!$omp end task
|
||||
end subroutine
|
||||
|
||||
! CHECK-LABEL: func.func @_QPtask_depend_iterator_mixed()
|
||||
! CHECK: %[[A:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) {uniq_name = "_QFtask_depend_iterator_mixedEa"}
|
||||
! CHECK: %[[X:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QFtask_depend_iterator_mixedEx"}
|
||||
! CHECK: %[[IT:.*]] = omp.iterator(%[[IV:.*]]: index) = ({{.*}} to {{.*}} step {{.*}}) {
|
||||
! CHECK: omp.yield(%{{.*}} : !llvm.ptr)
|
||||
! CHECK: } -> !omp.iterated<!llvm.ptr>
|
||||
! CHECK: omp.task depend(taskdependout -> %[[X]]#0 : !fir.ref<i32>, taskdependin -> %[[IT]] : !omp.iterated<!llvm.ptr>) {
|
||||
|
||||
subroutine task_depend_iterator_step()
|
||||
integer, parameter :: n = 16
|
||||
integer :: a(n)
|
||||
integer :: i
|
||||
|
||||
!$omp task depend(iterator(i = 1:n:2), in: a(i))
|
||||
!$omp end task
|
||||
end subroutine
|
||||
|
||||
! CHECK-LABEL: func.func @_QPtask_depend_iterator_step()
|
||||
! CHECK: %[[C1_I32:.*]] = arith.constant 1 : i32
|
||||
! CHECK: %[[C16_I32:.*]] = arith.constant 16 : i32
|
||||
! CHECK: %[[LB:.*]] = fir.convert %[[C1_I32]] : (i32) -> index
|
||||
! CHECK: %[[UB:.*]] = fir.convert %[[C16_I32]] : (i32) -> index
|
||||
! CHECK: %[[C2_I32:.*]] = arith.constant 2 : i32
|
||||
! CHECK: %[[STEP:.*]] = fir.convert %[[C2_I32]] : (i32) -> index
|
||||
! CHECK: %[[IT:.*]] = omp.iterator(%[[IV:.*]]: index) = (%[[LB]] to %[[UB]] step %[[STEP]]) {
|
||||
! CHECK: omp.yield(%{{.*}} : !llvm.ptr)
|
||||
! CHECK: } -> !omp.iterated<!llvm.ptr>
|
||||
! CHECK: omp.task depend(taskdependin -> %[[IT]] : !omp.iterated<!llvm.ptr>) {
|
||||
|
||||
subroutine task_depend_iterator_multi_obj()
|
||||
integer, parameter :: n = 16
|
||||
integer :: a(n), b(n)
|
||||
integer :: i
|
||||
|
||||
!$omp task depend(iterator(i = 1:n), inout: a(i), b(i))
|
||||
!$omp end task
|
||||
end subroutine
|
||||
|
||||
! CHECK-LABEL: func.func @_QPtask_depend_iterator_multi_obj()
|
||||
! CHECK: %[[A:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) {uniq_name = "_QFtask_depend_iterator_multi_objEa"}
|
||||
! CHECK: %[[B:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) {uniq_name = "_QFtask_depend_iterator_multi_objEb"}
|
||||
! CHECK: %[[IT1:.*]] = omp.iterator(%[[IV1:.*]]: index) = ({{.*}} to {{.*}} step {{.*}}) {
|
||||
! CHECK: %[[COOR1:.*]] = fir.array_coor %[[A]]#0(%{{.*}}) %{{.*}} : (!fir.ref<!fir.array<16xi32>>, !fir.shape<1>, i64) -> !fir.ref<i32>
|
||||
! CHECK: %[[PTR1:.*]] = fir.convert %[[COOR1]] : (!fir.ref<i32>) -> !llvm.ptr
|
||||
! CHECK: omp.yield(%[[PTR1]] : !llvm.ptr)
|
||||
! CHECK: } -> !omp.iterated<!llvm.ptr>
|
||||
! CHECK: %[[IT2:.*]] = omp.iterator(%[[IV2:.*]]: index) = ({{.*}} to {{.*}} step {{.*}}) {
|
||||
! CHECK: %[[COOR2:.*]] = fir.array_coor %[[B]]#0(%{{.*}}) %{{.*}} : (!fir.ref<!fir.array<16xi32>>, !fir.shape<1>, i64) -> !fir.ref<i32>
|
||||
! CHECK: %[[PTR2:.*]] = fir.convert %[[COOR2]] : (!fir.ref<i32>) -> !llvm.ptr
|
||||
! CHECK: omp.yield(%[[PTR2]] : !llvm.ptr)
|
||||
! CHECK: } -> !omp.iterated<!llvm.ptr>
|
||||
! CHECK: omp.task depend(taskdependinout -> %[[IT1]] : !omp.iterated<!llvm.ptr>, taskdependinout -> %[[IT2]] : !omp.iterated<!llvm.ptr>) {
|
||||
|
||||
! Expression-based subscript using multiple iterator variables: a((i-1)*m+j)
|
||||
! maps a 2D logical iteration space onto a 1D array.
|
||||
subroutine task_depend_iterator_expr_subscript()
|
||||
integer, parameter :: m = 4
|
||||
integer, parameter :: n = m * m
|
||||
integer :: a(n)
|
||||
integer :: i, j
|
||||
|
||||
!$omp task depend(iterator(i = 1:m, j = 1:m), out: a((i-1)*m+j))
|
||||
!$omp end task
|
||||
end subroutine
|
||||
|
||||
! CHECK-LABEL: func.func @_QPtask_depend_iterator_expr_subscript()
|
||||
! CHECK: %[[A:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) {uniq_name = "_QFtask_depend_iterator_expr_subscriptEa"}
|
||||
! CHECK: %[[IT:.*]] = omp.iterator(%[[IV0:.*]]: index, %[[IV1:.*]]: index) = ({{.*}} to {{.*}} step {{.*}}, {{.*}} to {{.*}} step {{.*}}) {
|
||||
! CHECK: %[[IV0_I32:.*]] = fir.convert %[[IV0]] : (index) -> i32
|
||||
! CHECK: %[[IV1_I32:.*]] = fir.convert %[[IV1]] : (index) -> i32
|
||||
! CHECK: %[[C1_I32:.*]] = arith.constant 1 : i32
|
||||
! CHECK: %[[SUB:.*]] = arith.subi %[[IV0_I32]], %[[C1_I32]] : i32
|
||||
! CHECK: %[[NOREASSOC:.*]] = fir.no_reassoc %[[SUB]] : i32
|
||||
! CHECK: %[[MUL:.*]] = arith.muli %{{.*}}, %[[NOREASSOC]] : i32
|
||||
! CHECK: %[[ADD:.*]] = arith.addi %[[MUL]], %[[IV1_I32]] : i32
|
||||
! CHECK: %[[IDX:.*]] = fir.convert %[[ADD]] : (i32) -> i64
|
||||
! CHECK: %[[COOR:.*]] = fir.array_coor %[[A]]#0(%{{.*}}) %[[IDX]] : (!fir.ref<!fir.array<16xi32>>, !fir.shape<1>, i64) -> !fir.ref<i32>
|
||||
! CHECK: %[[PTR:.*]] = fir.convert %[[COOR]] : (!fir.ref<i32>) -> !llvm.ptr
|
||||
! CHECK: omp.yield(%[[PTR]] : !llvm.ptr)
|
||||
! CHECK: } -> !omp.iterated<!llvm.ptr>
|
||||
! CHECK: omp.task depend(taskdependout -> %[[IT]] : !omp.iterated<!llvm.ptr>) {
|
||||
|
||||
! Multiple depend clauses each with their own iterator on the same task.
|
||||
subroutine task_depend_multi_iter_clauses()
|
||||
integer, parameter :: n = 8
|
||||
integer :: a(n), b(n)
|
||||
integer :: i, j
|
||||
|
||||
!$omp task depend(iterator(i = 1:n), in: a(i)) &
|
||||
!$omp& depend(iterator(j = 1:n), out: b(j))
|
||||
!$omp end task
|
||||
end subroutine
|
||||
|
||||
! CHECK-LABEL: func.func @_QPtask_depend_multi_iter_clauses()
|
||||
! CHECK: %[[A:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) {uniq_name = "_QFtask_depend_multi_iter_clausesEa"}
|
||||
! CHECK: %[[B:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) {uniq_name = "_QFtask_depend_multi_iter_clausesEb"}
|
||||
! CHECK: %[[IT1:.*]] = omp.iterator(%[[IV1:.*]]: index) = ({{.*}} to {{.*}} step {{.*}}) {
|
||||
! CHECK: %[[COOR1:.*]] = fir.array_coor %[[A]]#0(%{{.*}}) %{{.*}} : (!fir.ref<!fir.array<8xi32>>, !fir.shape<1>, i64) -> !fir.ref<i32>
|
||||
! CHECK: %[[PTR1:.*]] = fir.convert %[[COOR1]] : (!fir.ref<i32>) -> !llvm.ptr
|
||||
! CHECK: omp.yield(%[[PTR1]] : !llvm.ptr)
|
||||
! CHECK: } -> !omp.iterated<!llvm.ptr>
|
||||
! CHECK: %[[IT2:.*]] = omp.iterator(%[[IV2:.*]]: index) = ({{.*}} to {{.*}} step {{.*}}) {
|
||||
! CHECK: %[[COOR2:.*]] = fir.array_coor %[[B]]#0(%{{.*}}) %{{.*}} : (!fir.ref<!fir.array<8xi32>>, !fir.shape<1>, i64) -> !fir.ref<i32>
|
||||
! CHECK: %[[PTR2:.*]] = fir.convert %[[COOR2]] : (!fir.ref<i32>) -> !llvm.ptr
|
||||
! CHECK: omp.yield(%[[PTR2]] : !llvm.ptr)
|
||||
! CHECK: } -> !omp.iterated<!llvm.ptr>
|
||||
! CHECK: omp.task depend(taskdependin -> %[[IT1]] : !omp.iterated<!llvm.ptr>, taskdependout -> %[[IT2]] : !omp.iterated<!llvm.ptr>) {
|
||||
|
||||
subroutine task_depend_iterator_negative_step()
|
||||
integer, parameter :: n = 16
|
||||
integer :: a(n)
|
||||
integer :: i
|
||||
|
||||
!$omp task depend(iterator(i = n:1:-1), in: a(i))
|
||||
!$omp end task
|
||||
end subroutine
|
||||
|
||||
! CHECK-LABEL: func.func @_QPtask_depend_iterator_negative_step()
|
||||
! CHECK: %[[C16_I32:.*]] = arith.constant 16 : i32
|
||||
! CHECK: %[[C1_I32:.*]] = arith.constant 1 : i32
|
||||
! CHECK: %[[LB:.*]] = fir.convert %[[C16_I32]] : (i32) -> index
|
||||
! CHECK: %[[UB:.*]] = fir.convert %[[C1_I32]] : (i32) -> index
|
||||
! CHECK: %[[CM1_I32:.*]] = arith.constant -1 : i32
|
||||
! CHECK: %[[STEP:.*]] = fir.convert %[[CM1_I32]] : (i32) -> index
|
||||
! CHECK: %[[IT:.*]] = omp.iterator(%[[IV:.*]]: index) = (%[[LB]] to %[[UB]] step %[[STEP]]) {
|
||||
! CHECK: omp.yield(%{{.*}} : !llvm.ptr)
|
||||
! CHECK: } -> !omp.iterated<!llvm.ptr>
|
||||
! CHECK: omp.task depend(taskdependin -> %[[IT]] : !omp.iterated<!llvm.ptr>) {
|
||||
|
||||
! Mixed iterated and non-iterated objects in the same depend clause:
|
||||
! a(1) does not reference the iterator IV, so it is lowered as a regular
|
||||
! (non-iterated) depend var, while a(i) produces an omp.iterator.
|
||||
subroutine task_depend_iterator_mixed_within_clause()
|
||||
integer, parameter :: n = 16
|
||||
integer :: a(n)
|
||||
integer :: i
|
||||
|
||||
!$omp task depend(iterator(i = 2:n:2), in: a(1), a(i))
|
||||
!$omp end task
|
||||
end subroutine
|
||||
|
||||
! CHECK-LABEL: func.func @_QPtask_depend_iterator_mixed_within_clause()
|
||||
! CHECK: %[[A:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) {uniq_name = "_QFtask_depend_iterator_mixed_within_clauseEa"}
|
||||
! CHECK: %[[A1:.*]] = hlfir.designate %[[A]]#0 (%{{.*}}) : (!fir.ref<!fir.array<16xi32>>, index) -> !fir.ref<i32>
|
||||
! CHECK: %[[IT:.*]] = omp.iterator(%[[IV:.*]]: index) = ({{.*}} to {{.*}} step {{.*}}) {
|
||||
! CHECK: %[[COOR:.*]] = fir.array_coor %[[A]]#0(%{{.*}}) %{{.*}} : (!fir.ref<!fir.array<16xi32>>, !fir.shape<1>, i64) -> !fir.ref<i32>
|
||||
! CHECK: %[[PTR:.*]] = fir.convert %[[COOR]] : (!fir.ref<i32>) -> !llvm.ptr
|
||||
! CHECK: omp.yield(%[[PTR]] : !llvm.ptr)
|
||||
! CHECK: } -> !omp.iterated<!llvm.ptr>
|
||||
! CHECK: omp.task depend(taskdependin -> %[[A1]] : !fir.ref<i32>, taskdependin -> %[[IT]] : !omp.iterated<!llvm.ptr>) {
|
||||
|
||||
!===============================================================================
|
||||
! target
|
||||
!===============================================================================
|
||||
|
||||
subroutine target_depend_iterator()
|
||||
integer, parameter :: n = 16
|
||||
integer :: a(n)
|
||||
integer :: i
|
||||
|
||||
!$omp target depend(iterator(i = 1:n), in: a(i)) map(tofrom: a)
|
||||
a(1) = 10
|
||||
!$omp end target
|
||||
end subroutine
|
||||
|
||||
! CHECK-LABEL: func.func @_QPtarget_depend_iterator()
|
||||
! CHECK: %[[A:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) {uniq_name = "_QFtarget_depend_iteratorEa"}
|
||||
! CHECK: %[[IT:.*]] = omp.iterator(%[[IV:.*]]: index) = ({{.*}} to {{.*}} step {{.*}}) {
|
||||
! CHECK: %[[IV_I32:.*]] = fir.convert %[[IV]] : (index) -> i32
|
||||
! CHECK: %[[IV_I64:.*]] = fir.convert %[[IV_I32]] : (i32) -> i64
|
||||
! CHECK: %[[SHAPE:.*]] = fir.shape %c16 : (index) -> !fir.shape<1>
|
||||
! CHECK: %[[COOR:.*]] = fir.array_coor %[[A]]#0(%[[SHAPE]]) %[[IV_I64]] : (!fir.ref<!fir.array<16xi32>>, !fir.shape<1>, i64) -> !fir.ref<i32>
|
||||
! CHECK: %[[PTR:.*]] = fir.convert %[[COOR]] : (!fir.ref<i32>) -> !llvm.ptr
|
||||
! CHECK: omp.yield(%[[PTR]] : !llvm.ptr)
|
||||
! CHECK: } -> !omp.iterated<!llvm.ptr>
|
||||
! CHECK: %[[MAP:.*]] = omp.map.info var_ptr(%[[A]]#1 : {{.*}}) map_clauses(tofrom) capture(ByRef) bounds({{.*}}) -> !fir.ref<!fir.array<16xi32>> {name = "a"}
|
||||
! CHECK: omp.target depend(taskdependin -> %[[IT]] : !omp.iterated<!llvm.ptr>) map_entries(%[[MAP]] -> %{{.*}} : !fir.ref<!fir.array<16xi32>>) {
|
||||
! CHECK: omp.terminator
|
||||
! CHECK: }
|
||||
|
||||
subroutine target_depend_iterator_multi()
|
||||
integer, parameter :: n = 8
|
||||
integer :: a(n), b(n), c(n)
|
||||
integer :: i, j
|
||||
|
||||
!$omp target depend(iterator(i = 1:n), inout: a(i), b(i)) &
|
||||
!$omp& depend(iterator(j = 1:n:2), in: c(j)) &
|
||||
!$omp& map(tofrom: a, b)
|
||||
a(1) = b(1)
|
||||
!$omp end target
|
||||
end subroutine
|
||||
|
||||
! CHECK-LABEL: func.func @_QPtarget_depend_iterator_multi()
|
||||
! CHECK: %[[A:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) {uniq_name = "_QFtarget_depend_iterator_multiEa"}
|
||||
! CHECK: %[[B:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) {uniq_name = "_QFtarget_depend_iterator_multiEb"}
|
||||
! CHECK: %[[C:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) {uniq_name = "_QFtarget_depend_iterator_multiEc"}
|
||||
! CHECK: %[[IT1:.*]] = omp.iterator(%{{.*}}: index) = ({{.*}} to {{.*}} step {{.*}}) {
|
||||
! CHECK: %[[COOR1:.*]] = fir.array_coor %[[A]]#0(%{{.*}}) %{{.*}} : (!fir.ref<!fir.array<8xi32>>, !fir.shape<1>, i64) -> !fir.ref<i32>
|
||||
! CHECK: omp.yield(%{{.*}} : !llvm.ptr)
|
||||
! CHECK: } -> !omp.iterated<!llvm.ptr>
|
||||
! CHECK: %[[IT2:.*]] = omp.iterator(%{{.*}}: index) = ({{.*}} to {{.*}} step {{.*}}) {
|
||||
! CHECK: %[[COOR2:.*]] = fir.array_coor %[[B]]#0(%{{.*}}) %{{.*}} : (!fir.ref<!fir.array<8xi32>>, !fir.shape<1>, i64) -> !fir.ref<i32>
|
||||
! CHECK: omp.yield(%{{.*}} : !llvm.ptr)
|
||||
! CHECK: } -> !omp.iterated<!llvm.ptr>
|
||||
! CHECK: %[[IT3:.*]] = omp.iterator(%{{.*}}: index) = ({{.*}} to {{.*}} step {{.*}}) {
|
||||
! CHECK: %[[COOR3:.*]] = fir.array_coor %[[C]]#0(%{{.*}}) %{{.*}} : (!fir.ref<!fir.array<8xi32>>, !fir.shape<1>, i64) -> !fir.ref<i32>
|
||||
! CHECK: omp.yield(%{{.*}} : !llvm.ptr)
|
||||
! CHECK: } -> !omp.iterated<!llvm.ptr>
|
||||
! CHECK: %[[MAP_A:.*]] = omp.map.info var_ptr(%[[A]]#1 : {{.*}}) map_clauses(tofrom) capture(ByRef) bounds({{.*}}) -> !fir.ref<!fir.array<8xi32>> {name = "a"}
|
||||
! CHECK: %[[MAP_B:.*]] = omp.map.info var_ptr(%[[B]]#1 : {{.*}}) map_clauses(tofrom) capture(ByRef) bounds({{.*}}) -> !fir.ref<!fir.array<8xi32>> {name = "b"}
|
||||
! CHECK: %[[MAP_C:.*]] = omp.map.info var_ptr(%[[C]]#1 : {{.*}}) map_clauses(implicit, tofrom) capture(ByRef) bounds({{.*}}) -> !fir.ref<!fir.array<8xi32>> {name = "c"}
|
||||
! CHECK: omp.target depend(taskdependinout -> %[[IT1]] : !omp.iterated<!llvm.ptr>, taskdependinout -> %[[IT2]] : !omp.iterated<!llvm.ptr>, taskdependin -> %[[IT3]] : !omp.iterated<!llvm.ptr>) map_entries(%[[MAP_A]] -> %{{.*}}, %[[MAP_B]] -> %{{.*}}, %[[MAP_C]] -> %{{.*}} : !fir.ref<!fir.array<8xi32>>, !fir.ref<!fir.array<8xi32>>, !fir.ref<!fir.array<8xi32>>) {
|
||||
|
||||
!===============================================================================
|
||||
! target enter data
|
||||
!===============================================================================
|
||||
|
||||
subroutine target_enter_data_depend_iterator()
|
||||
integer, parameter :: n = 16
|
||||
integer :: a(n)
|
||||
integer :: i
|
||||
|
||||
!$omp target enter data map(to: a) depend(iterator(i = 1:n), in: a(i))
|
||||
end subroutine
|
||||
|
||||
! CHECK-LABEL: func.func @_QPtarget_enter_data_depend_iterator()
|
||||
! CHECK: %[[A:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) {uniq_name = "_QFtarget_enter_data_depend_iteratorEa"}
|
||||
! CHECK: %[[IT:.*]] = omp.iterator(%[[IV:.*]]: index) = ({{.*}} to {{.*}} step {{.*}}) {
|
||||
! CHECK: %[[IV_I32:.*]] = fir.convert %[[IV]] : (index) -> i32
|
||||
! CHECK: %[[IV_I64:.*]] = fir.convert %[[IV_I32]] : (i32) -> i64
|
||||
! CHECK: %[[SHAPE:.*]] = fir.shape %c16 : (index) -> !fir.shape<1>
|
||||
! CHECK: %[[COOR:.*]] = fir.array_coor %[[A]]#0(%[[SHAPE]]) %[[IV_I64]] : (!fir.ref<!fir.array<16xi32>>, !fir.shape<1>, i64) -> !fir.ref<i32>
|
||||
! CHECK: %[[PTR:.*]] = fir.convert %[[COOR]] : (!fir.ref<i32>) -> !llvm.ptr
|
||||
! CHECK: omp.yield(%[[PTR]] : !llvm.ptr)
|
||||
! CHECK: } -> !omp.iterated<!llvm.ptr>
|
||||
! CHECK: %[[MAP:.*]] = omp.map.info var_ptr(%[[A]]#1 : {{.*}}) map_clauses(to) capture(ByRef) bounds({{.*}}) -> !fir.ref<!fir.array<16xi32>> {name = "a"}
|
||||
! CHECK: omp.target_enter_data depend(taskdependin -> %[[IT]] : !omp.iterated<!llvm.ptr>) map_entries(%[[MAP]] : !fir.ref<!fir.array<16xi32>>)
|
||||
|
||||
subroutine target_enter_data_depend_iterator_expr()
|
||||
integer, parameter :: m = 4
|
||||
integer, parameter :: n = m * m
|
||||
integer :: a(n)
|
||||
integer :: i, j
|
||||
|
||||
!$omp target enter data map(to: a) &
|
||||
!$omp& depend(iterator(i = 1:m, j = 1:m), inout: a(1), a((i-1)*m+j))
|
||||
end subroutine
|
||||
|
||||
! CHECK-LABEL: func.func @_QPtarget_enter_data_depend_iterator_expr()
|
||||
! CHECK: %[[A:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) {uniq_name = "_QFtarget_enter_data_depend_iterator_exprEa"}
|
||||
! CHECK: %[[A1:.*]] = hlfir.designate %[[A]]#0 (%{{.*}}) : (!fir.ref<!fir.array<16xi32>>, index) -> !fir.ref<i32>
|
||||
! CHECK: %[[IT:.*]] = omp.iterator(%[[IV0:.*]]: index, %[[IV1:.*]]: index) = ({{.*}} to {{.*}} step {{.*}}, {{.*}} to {{.*}} step {{.*}}) {
|
||||
! CHECK: %[[IV0_I32:.*]] = fir.convert %[[IV0]] : (index) -> i32
|
||||
! CHECK: %[[IV1_I32:.*]] = fir.convert %[[IV1]] : (index) -> i32
|
||||
! CHECK: %[[SUB:.*]] = arith.subi %[[IV0_I32]], %{{.*}} : i32
|
||||
! CHECK: %[[NOREASSOC:.*]] = fir.no_reassoc %[[SUB]] : i32
|
||||
! CHECK: %[[MUL:.*]] = arith.muli %{{.*}}, %[[NOREASSOC]] : i32
|
||||
! CHECK: %[[ADD:.*]] = arith.addi %[[MUL]], %[[IV1_I32]] : i32
|
||||
! CHECK: %[[IDX:.*]] = fir.convert %[[ADD]] : (i32) -> i64
|
||||
! CHECK: %[[COOR:.*]] = fir.array_coor %[[A]]#0(%{{.*}}) %[[IDX]] : (!fir.ref<!fir.array<16xi32>>, !fir.shape<1>, i64) -> !fir.ref<i32>
|
||||
! CHECK: omp.yield(%{{.*}} : !llvm.ptr)
|
||||
! CHECK: } -> !omp.iterated<!llvm.ptr>
|
||||
! CHECK: %[[MAP:.*]] = omp.map.info var_ptr(%[[A]]#1 : {{.*}}) map_clauses(to) capture(ByRef) bounds({{.*}}) -> !fir.ref<!fir.array<16xi32>> {name = "a"}
|
||||
! CHECK: omp.target_enter_data depend(taskdependinout -> %[[A1]] : !fir.ref<i32>, taskdependinout -> %[[IT]] : !omp.iterated<!llvm.ptr>) map_entries(%[[MAP]] : !fir.ref<!fir.array<16xi32>>)
|
||||
|
||||
!===============================================================================
|
||||
! target exit data
|
||||
!===============================================================================
|
||||
|
||||
subroutine target_exit_data_depend_iterator()
|
||||
integer, parameter :: n = 16
|
||||
integer :: a(n)
|
||||
integer :: i
|
||||
|
||||
!$omp target exit data map(from: a) depend(iterator(i = 1:n), out: a(i))
|
||||
end subroutine
|
||||
|
||||
! CHECK-LABEL: func.func @_QPtarget_exit_data_depend_iterator()
|
||||
! CHECK: %[[A:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) {uniq_name = "_QFtarget_exit_data_depend_iteratorEa"}
|
||||
! CHECK: %[[IT:.*]] = omp.iterator(%[[IV:.*]]: index) = ({{.*}} to {{.*}} step {{.*}}) {
|
||||
! CHECK: %[[IV_I32:.*]] = fir.convert %[[IV]] : (index) -> i32
|
||||
! CHECK: %[[IV_I64:.*]] = fir.convert %[[IV_I32]] : (i32) -> i64
|
||||
! CHECK: %[[SHAPE:.*]] = fir.shape %c16 : (index) -> !fir.shape<1>
|
||||
! CHECK: %[[COOR:.*]] = fir.array_coor %[[A]]#0(%[[SHAPE]]) %[[IV_I64]] : (!fir.ref<!fir.array<16xi32>>, !fir.shape<1>, i64) -> !fir.ref<i32>
|
||||
! CHECK: %[[PTR:.*]] = fir.convert %[[COOR]] : (!fir.ref<i32>) -> !llvm.ptr
|
||||
! CHECK: omp.yield(%[[PTR]] : !llvm.ptr)
|
||||
! CHECK: } -> !omp.iterated<!llvm.ptr>
|
||||
! CHECK: %[[MAP:.*]] = omp.map.info var_ptr(%[[A]]#1 : {{.*}}) map_clauses(from) capture(ByRef) bounds({{.*}}) -> !fir.ref<!fir.array<16xi32>> {name = "a"}
|
||||
! CHECK: omp.target_exit_data depend(taskdependout -> %[[IT]] : !omp.iterated<!llvm.ptr>) map_entries(%[[MAP]] : !fir.ref<!fir.array<16xi32>>)
|
||||
|
||||
subroutine target_exit_data_depend_iterator_multi()
|
||||
integer, parameter :: n = 16
|
||||
integer :: a(n), b(n)
|
||||
integer :: i
|
||||
|
||||
!$omp target exit data map(from: a, b) &
|
||||
!$omp& depend(iterator(i = n:1:-1), out: a(i), b(i))
|
||||
end subroutine
|
||||
|
||||
! CHECK-LABEL: func.func @_QPtarget_exit_data_depend_iterator_multi()
|
||||
! CHECK: %[[A:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) {uniq_name = "_QFtarget_exit_data_depend_iterator_multiEa"}
|
||||
! CHECK: %[[B:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) {uniq_name = "_QFtarget_exit_data_depend_iterator_multiEb"}
|
||||
! CHECK: %[[C16_I32:.*]] = arith.constant 16 : i32
|
||||
! CHECK: %[[C1_I32:.*]] = arith.constant 1 : i32
|
||||
! CHECK: %[[LB:.*]] = fir.convert %[[C16_I32]] : (i32) -> index
|
||||
! CHECK: %[[UB:.*]] = fir.convert %[[C1_I32]] : (i32) -> index
|
||||
! CHECK: %[[CM1_I32:.*]] = arith.constant -1 : i32
|
||||
! CHECK: %[[STEP:.*]] = fir.convert %[[CM1_I32]] : (i32) -> index
|
||||
! CHECK: %[[IT1:.*]] = omp.iterator(%{{.*}}: index) = (%[[LB]] to %[[UB]] step %[[STEP]]) {
|
||||
! CHECK: %[[COOR1:.*]] = fir.array_coor %[[A]]#0(%{{.*}}) %{{.*}} : (!fir.ref<!fir.array<16xi32>>, !fir.shape<1>, i64) -> !fir.ref<i32>
|
||||
! CHECK: omp.yield(%{{.*}} : !llvm.ptr)
|
||||
! CHECK: } -> !omp.iterated<!llvm.ptr>
|
||||
! CHECK: %[[IT2:.*]] = omp.iterator(%{{.*}}: index) = (%[[LB]] to %[[UB]] step %[[STEP]]) {
|
||||
! CHECK: %[[COOR2:.*]] = fir.array_coor %[[B]]#0(%{{.*}}) %{{.*}} : (!fir.ref<!fir.array<16xi32>>, !fir.shape<1>, i64) -> !fir.ref<i32>
|
||||
! CHECK: omp.yield(%{{.*}} : !llvm.ptr)
|
||||
! CHECK: } -> !omp.iterated<!llvm.ptr>
|
||||
! CHECK: %[[MAP_A:.*]] = omp.map.info var_ptr(%[[A]]#1 : {{.*}}) map_clauses(from) capture(ByRef) bounds({{.*}}) -> !fir.ref<!fir.array<16xi32>> {name = "a"}
|
||||
! CHECK: %[[MAP_B:.*]] = omp.map.info var_ptr(%[[B]]#1 : {{.*}}) map_clauses(from) capture(ByRef) bounds({{.*}}) -> !fir.ref<!fir.array<16xi32>> {name = "b"}
|
||||
! CHECK: omp.target_exit_data depend(taskdependout -> %[[IT1]] : !omp.iterated<!llvm.ptr>, taskdependout -> %[[IT2]] : !omp.iterated<!llvm.ptr>) map_entries(%[[MAP_A]], %[[MAP_B]] : !fir.ref<!fir.array<16xi32>>, !fir.ref<!fir.array<16xi32>>)
|
||||
|
||||
!===============================================================================
|
||||
! target update
|
||||
!===============================================================================
|
||||
|
||||
subroutine target_update_depend_iterator()
|
||||
integer, parameter :: n = 16
|
||||
integer :: a(n)
|
||||
integer :: i
|
||||
|
||||
!$omp target update to(a) depend(iterator(i = 1:n), in: a(i))
|
||||
end subroutine
|
||||
|
||||
! CHECK-LABEL: func.func @_QPtarget_update_depend_iterator()
|
||||
! CHECK: %[[A:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) {uniq_name = "_QFtarget_update_depend_iteratorEa"}
|
||||
! CHECK: %[[IT:.*]] = omp.iterator(%[[IV:.*]]: index) = ({{.*}} to {{.*}} step {{.*}}) {
|
||||
! CHECK: %[[IV_I32:.*]] = fir.convert %[[IV]] : (index) -> i32
|
||||
! CHECK: %[[IV_I64:.*]] = fir.convert %[[IV_I32]] : (i32) -> i64
|
||||
! CHECK: %[[SHAPE:.*]] = fir.shape %c16 : (index) -> !fir.shape<1>
|
||||
! CHECK: %[[COOR:.*]] = fir.array_coor %[[A]]#0(%[[SHAPE]]) %[[IV_I64]] : (!fir.ref<!fir.array<16xi32>>, !fir.shape<1>, i64) -> !fir.ref<i32>
|
||||
! CHECK: %[[PTR:.*]] = fir.convert %[[COOR]] : (!fir.ref<i32>) -> !llvm.ptr
|
||||
! CHECK: omp.yield(%[[PTR]] : !llvm.ptr)
|
||||
! CHECK: } -> !omp.iterated<!llvm.ptr>
|
||||
! CHECK: %[[MAP:.*]] = omp.map.info var_ptr(%[[A]]#1 : {{.*}}) map_clauses(to) capture(ByRef) bounds({{.*}}) -> !fir.ref<!fir.array<16xi32>> {name = "a"}
|
||||
! CHECK: omp.target_update depend(taskdependin -> %[[IT]] : !omp.iterated<!llvm.ptr>) map_entries(%[[MAP]] : !fir.ref<!fir.array<16xi32>>)
|
||||
|
||||
! Two separate depend(iterator) clauses with different IVs and depend kinds,
|
||||
! plus a non-iterated depend.
|
||||
subroutine target_update_depend_iterator_multi()
|
||||
integer, parameter :: n = 8
|
||||
integer :: a(n), b(n), x
|
||||
integer :: i, j
|
||||
|
||||
!$omp target update to(a) from(b) &
|
||||
!$omp& depend(iterator(i = 1:n), in: a(i)) &
|
||||
!$omp& depend(iterator(j = 1:n:2), out: b(j)) &
|
||||
!$omp& depend(inout: x)
|
||||
end subroutine
|
||||
|
||||
! CHECK-LABEL: func.func @_QPtarget_update_depend_iterator_multi()
|
||||
! CHECK: %[[A:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) {uniq_name = "_QFtarget_update_depend_iterator_multiEa"}
|
||||
! CHECK: %[[B:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) {uniq_name = "_QFtarget_update_depend_iterator_multiEb"}
|
||||
! CHECK: %[[X:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QFtarget_update_depend_iterator_multiEx"}
|
||||
! CHECK: %[[IT1:.*]] = omp.iterator(%{{.*}}: index) = ({{.*}} to {{.*}} step {{.*}}) {
|
||||
! CHECK: %[[COOR1:.*]] = fir.array_coor %[[A]]#0(%{{.*}}) %{{.*}} : (!fir.ref<!fir.array<8xi32>>, !fir.shape<1>, i64) -> !fir.ref<i32>
|
||||
! CHECK: omp.yield(%{{.*}} : !llvm.ptr)
|
||||
! CHECK: } -> !omp.iterated<!llvm.ptr>
|
||||
! CHECK: %[[IT2:.*]] = omp.iterator(%{{.*}}: index) = ({{.*}} to {{.*}} step {{.*}}) {
|
||||
! CHECK: %[[COOR2:.*]] = fir.array_coor %[[B]]#0(%{{.*}}) %{{.*}} : (!fir.ref<!fir.array<8xi32>>, !fir.shape<1>, i64) -> !fir.ref<i32>
|
||||
! CHECK: omp.yield(%{{.*}} : !llvm.ptr)
|
||||
! CHECK: } -> !omp.iterated<!llvm.ptr>
|
||||
! CHECK: %[[MAP_A:.*]] = omp.map.info var_ptr(%[[A]]#1 : {{.*}}) map_clauses(to) capture(ByRef) bounds({{.*}}) -> !fir.ref<!fir.array<8xi32>> {name = "a"}
|
||||
! CHECK: %[[MAP_B:.*]] = omp.map.info var_ptr(%[[B]]#1 : {{.*}}) map_clauses(from) capture(ByRef) bounds({{.*}}) -> !fir.ref<!fir.array<8xi32>> {name = "b"}
|
||||
! CHECK: omp.target_update depend(taskdependinout -> %[[X]]#0 : !fir.ref<i32>, taskdependin -> %[[IT1]] : !omp.iterated<!llvm.ptr>, taskdependout -> %[[IT2]] : !omp.iterated<!llvm.ptr>) map_entries(%[[MAP_A]], %[[MAP_B]] : !fir.ref<!fir.array<8xi32>>, !fir.ref<!fir.array<8xi32>>)
|
||||
Loading…
x
Reference in New Issue
Block a user