[flang-commits] [flang] [llvm] [mlir] [OpenMP] Honor barrier and last iteration flags in loop lowering (PR #224040)
via flang-commits
flang-commits at lists.llvm.org
Wed Sep 16 08:00:10 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-mlir-llvm
@llvm/pr-subscribers-flang-openmp
Author: Nicole Aschenbrenner (nicebert)
<details>
<summary>Changes</summary>
Emitting loop-free kernels for no-loop target regions in Clang requires
the shared OpenMP lowering to honor flags that reach it today and are
then discarded.
applyWorkshareLoop takes a NeedsBarrier flag, but the device path drops
it, so a worksharing loop without nowait emits no barrier at its exit.
The device path also never sets the canonical loop's last iteration
variable, which the linear clause finalization reads. Forward the flag
to applyWorkshareLoopTarget and compute the last iteration in the loop
body, mirroring how the host runtime reports it.
Auditing the surrounding lowering for the same class of problem turned
up one more. The barrier that follows privatization is emitted as part
of the firstprivate copy region, so a construct with lastprivate and no
firstprivate never gets one. Emit it independently of the copy region.
Flang skips it for taskloop, where the write-back already happens after
the reads.
Split out of #<!-- -->205325.
---
Patch is 22.20 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/224040.diff
7 Files Affected:
- (modified) flang/lib/Lower/OpenMP/DataSharingProcessor.cpp (+7)
- (added) flang/test/Integration/OpenMP/privatization-barrier.f90 (+38)
- (modified) flang/test/Lower/OpenMP/taskloop.f90 (+15)
- (modified) llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h (+10-6)
- (modified) llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp (+38-4)
- (modified) mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp (+53-43)
- (modified) mlir/test/Target/LLVMIR/omptarget-wsloop.mlir (+40)
``````````diff
diff --git a/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp b/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp
index 8d0d191058cfb..3e63c068e1cdb 100644
--- a/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp
+++ b/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp
@@ -372,6 +372,13 @@ bool DataSharingProcessor::needBarrier() {
// initialization of firstprivate variables and post-update of lastprivate
// variables.
// Emit implicit barrier for linear clause in the OpenMPIRBuilder.
+ // Skip for taskloop: the write-back only happens after the reads are done.
+
+ const auto *ompEval = eval.getIf<parser::OpenMPConstruct>();
+ if (ompEval && llvm::omp::allTaskloopSet.test(
+ parser::omp::GetOmpDirectiveName(*ompEval).v))
+ return false;
+
for (const semantics::Symbol *sym : allPrivatizedSymbols) {
if (sym->test(semantics::Symbol::Flag::OmpLastPrivate) &&
(sym->test(semantics::Symbol::Flag::OmpFirstPrivate) ||
diff --git a/flang/test/Integration/OpenMP/privatization-barrier.f90 b/flang/test/Integration/OpenMP/privatization-barrier.f90
new file mode 100644
index 0000000000000..06ab26df2521e
--- /dev/null
+++ b/flang/test/Integration/OpenMP/privatization-barrier.f90
@@ -0,0 +1,38 @@
+!===----------------------------------------------------------------------===!
+! This directory can be used to add Integration tests involving multiple
+! stages of the compiler (for eg. from Fortran to LLVM IR). It should not
+! contain executable tests. We should only add tests here sparingly and only
+! if there is no other way to test. Repeat this message in each test that is
+! added to this directory and sub-directories.
+!===----------------------------------------------------------------------===!
+
+! RUN: %flang_fc1 -fopenmp -emit-llvm %s -o - | FileCheck %s
+! RUN: %if amdgpu-registered-target %{ %flang_fc1 -triple amdgcn-amd-amdhsa -emit-llvm -fopenmp -fopenmp-is-target-device %s -o - | FileCheck %s %}
+
+subroutine lastprivate_allocatable_barrier_host
+ integer, allocatable :: a
+ integer :: i
+ !$omp parallel do lastprivate(a)
+ do i = 1, 10
+ a = i
+ end do
+ !$omp end parallel do
+end subroutine
+
+subroutine lastprivate_allocatable_barrier_device
+ integer, allocatable :: a
+ integer :: i
+ allocate(a)
+ !$omp target parallel do lastprivate(a)
+ do i = 1, 10
+ a = i
+ end do
+ !$omp end target parallel do
+end subroutine
+
+! CHECK-LABEL: define internal void @{{.*}}lastprivate_allocatable_barrier_{{(host|device)}}
+! CHECK: call void @__kmpc_barrier
+! CHECK-NEXT: br label %omp.wsloop.region
+! CHECK: call void @__kmpc_barrier
+! CHECK-NEXT: br label %omp_loop.after
+! CHECK-LABEL: define{{.*}}void @{{.*}}lastprivate_allocatable_barrier_device
diff --git a/flang/test/Lower/OpenMP/taskloop.f90 b/flang/test/Lower/OpenMP/taskloop.f90
index 94e4e2947fa71..c9ce984db7e8e 100644
--- a/flang/test/Lower/OpenMP/taskloop.f90
+++ b/flang/test/Lower/OpenMP/taskloop.f90
@@ -2,6 +2,9 @@
! RUN: bbc -emit-hlfir %openmp_flags -fopenmp-version=50 -o - %s 2>&1 | FileCheck %s
! RUN: %flang_fc1 -emit-hlfir %openmp_flags -fopenmp-version=50 -o - %s 2>&1 | FileCheck %s
+! CHECK-LABEL: omp.private {type = firstprivate}
+! CHECK-SAME: @[[FIRST_LAST_PRIVATE_X:.*]] : i32
+
! CHECK-LABEL: omp.private
! CHECK-SAME: {type = private} @[[LAST_PRIVATE_I:.*]] : i32
@@ -260,3 +263,15 @@ subroutine omp_taskloop_lastprivate()
! CHECK: omp.terminator
!$omp end taskloop
end subroutine omp_taskloop_lastprivate
+
+! CHECK-LABEL: func @_QPomp_taskloop_first_and_lastprivate()
+subroutine omp_taskloop_first_and_lastprivate()
+ integer x
+ x = 0
+ ! CHECK: omp.taskloop.context private(@[[FIRST_LAST_PRIVATE_X]] {{.*}}) {
+ !$omp taskloop firstprivate(x) lastprivate(x)
+ do i = 1, 100
+ x = x + 1
+ end do
+ !$omp end taskloop
+end subroutine omp_taskloop_first_and_lastprivate
diff --git a/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h b/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
index a13832d69b6a0..90a91e98b4863 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
+++ b/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
@@ -1177,15 +1177,19 @@ class OpenMPIRBuilder {
/// \param CLI A descriptor of the canonical loop to workshare.
/// \param AllocaIP An insertion point for Alloca instructions usable in the
/// preheader of the loop.
+ /// \param NeedsBarrier Indicates whether a barrier must be inserted after
+ /// the loop.
/// \param LoopType Information about type of loop worksharing.
/// It corresponds to type of loop workshare OpenMP pragma.
/// \param NoLoop If true, no-loop code is generated.
+ /// \param NeedsLastIter If true, the last iteration variable is emitted.
///
/// \returns Point where to insert code after the workshare construct.
- InsertPointTy applyWorkshareLoopTarget(DebugLoc DL, CanonicalLoopInfo *CLI,
- InsertPointTy AllocaIP,
- omp::WorksharingLoopType LoopType,
- bool NoLoop);
+ InsertPointOrErrorTy
+ applyWorkshareLoopTarget(DebugLoc DL, CanonicalLoopInfo *CLI,
+ InsertPointTy AllocaIP, bool NeedsBarrier,
+ omp::WorksharingLoopType LoopType, bool NoLoop,
+ bool NeedsLastIter);
/// Modifies the canonical loop to be a statically-scheduled workshare loop.
///
@@ -1343,8 +1347,8 @@ class OpenMPIRBuilder {
/// \param NoLoop If true, no-loop code is generated.
/// \param HasDistSchedule Defines if the clause being lowered is
/// dist_schedule as this is handled slightly differently
- ///
/// \param DistScheduleChunkSize The chunk size for dist_schedule loop
+ /// \param NeedsLastIter If true, the last iteration variable is emitted.
///
/// \returns Point where to insert code after the workshare construct.
LLVM_ABI InsertPointOrErrorTy applyWorkshareLoop(
@@ -1357,7 +1361,7 @@ class OpenMPIRBuilder {
omp::WorksharingLoopType LoopType =
omp::WorksharingLoopType::ForStaticLoop,
bool NoLoop = false, bool HasDistSchedule = false,
- Value *DistScheduleChunkSize = nullptr);
+ Value *DistScheduleChunkSize = nullptr, bool NeedsLastIter = false);
/// Tile a loop nest.
///
diff --git a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
index 0747b943d1ba4..8741ccba37d08 100644
--- a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
+++ b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
@@ -6612,11 +6612,32 @@ static void workshareLoopTargetCallback(
CLI->invalidate();
}
-OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::applyWorkshareLoopTarget(
+OpenMPIRBuilder::InsertPointOrErrorTy OpenMPIRBuilder::applyWorkshareLoopTarget(
DebugLoc DL, CanonicalLoopInfo *CLI, InsertPointTy AllocaIP,
- WorksharingLoopType LoopType, bool NoLoop) {
+ bool NeedsBarrier, WorksharingLoopType LoopType, bool NoLoop,
+ bool NeedsLastIter) {
uint32_t SrcLocStrSize;
Constant *SrcLocStr = getOrCreateSrcLocStr(DL, SrcLocStrSize);
+
+ // Mirrors host runtime reporting of last iteration by in-body computation.
+ if (NeedsLastIter) {
+ Type *I32Type = Type::getInt32Ty(M.getContext());
+ Builder.restoreIP(AllocaIP);
+ AllocaInst *PLastIter =
+ Builder.CreateAlloca(I32Type, nullptr, "p.lastiter");
+ Builder.CreateStore(ConstantInt::get(I32Type, 0), PLastIter);
+ CLI->setLastIter(PLastIter);
+
+ Builder.SetInsertPoint(CLI->getBody(),
+ CLI->getBody()->getFirstInsertionPt());
+ Value *TripCount = CLI->getTripCount();
+ Value *LastIter =
+ Builder.CreateSub(TripCount, ConstantInt::get(TripCount->getType(), 1));
+ Value *IsLast =
+ Builder.CreateICmpEQ(CLI->getIndVar(), LastIter, "omp.is_last_iter");
+ Builder.CreateStore(Builder.CreateZExt(IsLast, I32Type), PLastIter);
+ }
+
IdentFlag Flag = IdentFlag(0);
switch (LoopType) {
case WorksharingLoopType::ForStaticLoop:
@@ -6713,6 +6734,18 @@ OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::applyWorkshareLoopTarget(
LoopType, NoLoop);
};
addOutlineInfo(std::move(OI));
+
+ if (NeedsBarrier) {
+ Builder.SetInsertPoint(CLI->getExit(),
+ CLI->getExit()->getTerminator()->getIterator());
+ InsertPointOrErrorTy BarrierIP =
+ createBarrier(LocationDescription(Builder.saveIP(), DL),
+ omp::Directive::OMPD_for, /* ForceSimpleCall */ false,
+ /* CheckCancelFlag*/ false);
+ if (!BarrierIP)
+ return BarrierIP.takeError();
+ }
+
return CLI->getAfterIP();
}
@@ -6722,9 +6755,10 @@ OpenMPIRBuilder::InsertPointOrErrorTy OpenMPIRBuilder::applyWorkshareLoop(
bool HasSimdModifier, bool HasMonotonicModifier,
bool HasNonmonotonicModifier, bool HasOrderedClause,
WorksharingLoopType LoopType, bool NoLoop, bool HasDistSchedule,
- Value *DistScheduleChunkSize) {
+ Value *DistScheduleChunkSize, bool NeedsLastIter) {
if (Config.isTargetDevice())
- return applyWorkshareLoopTarget(DL, CLI, AllocaIP, LoopType, NoLoop);
+ return applyWorkshareLoopTarget(DL, CLI, AllocaIP, NeedsBarrier, LoopType,
+ NoLoop, NeedsLastIter);
OMPScheduleType EffectiveScheduleType = computeOpenMPScheduleType(
SchedKind, ChunkSize, HasSimdModifier, HasMonotonicModifier,
HasNonmonotonicModifier, HasOrderedClause, DistScheduleChunkSize);
diff --git a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
index e5e3e0cc6d944..f6a4b4c5d7f3f 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
@@ -2083,13 +2083,27 @@ static bool opIsInSingleThread(mlir::Operation *op) {
return false;
}
-static LogicalResult copyFirstPrivateVars(
- mlir::Operation *op, llvm::IRBuilderBase &builder,
- LLVM::ModuleTranslation &moduleTranslation,
- SmallVectorImpl<llvm::Value *> &moldVars,
- ArrayRef<llvm::Value *> llvmPrivateVars,
- SmallVectorImpl<omp::PrivateClauseOp> &privateDecls, bool insertBarrier,
- llvm::DenseMap<Value, Value> *mappedPrivateVars = nullptr) {
+static LogicalResult
+emitPrivatizationBarrier(mlir::Operation *op, llvm::IRBuilderBase &builder,
+ LLVM::ModuleTranslation &moduleTranslation,
+ bool insertBarrier) {
+ if (!insertBarrier || opIsInSingleThread(op))
+ return success();
+
+ llvm::OpenMPIRBuilder *ompBuilder = moduleTranslation.getOpenMPBuilder();
+ llvm::OpenMPIRBuilder::InsertPointOrErrorTy res =
+ ompBuilder->createBarrier(builder, llvm::omp::OMPD_barrier);
+ return handleError(res, *op);
+}
+
+static LogicalResult
+completePrivateVars(mlir::Operation *op, llvm::IRBuilderBase &builder,
+ LLVM::ModuleTranslation &moduleTranslation,
+ SmallVectorImpl<llvm::Value *> &moldVars,
+ ArrayRef<llvm::Value *> llvmPrivateVars,
+ SmallVectorImpl<omp::PrivateClauseOp> &privateDecls,
+ bool insertBarrier,
+ llvm::DenseMap<Value, Value> *mappedPrivateVars = nullptr) {
// Apply copy region for firstprivate.
bool needsFirstprivate =
llvm::any_of(privateDecls, [](omp::PrivateClauseOp &privOp) {
@@ -2098,7 +2112,8 @@ static LogicalResult copyFirstPrivateVars(
});
if (!needsFirstprivate)
- return success();
+ return emitPrivatizationBarrier(op, builder, moduleTranslation,
+ insertBarrier);
llvm::BasicBlock *copyBlock =
splitBB(builder, /*CreateBranch=*/true, "omp.private.copy");
@@ -2137,24 +2152,18 @@ static LogicalResult copyFirstPrivateVars(
moduleTranslation.forgetMapping(copyRegion);
}
- if (insertBarrier && !opIsInSingleThread(op)) {
- llvm::OpenMPIRBuilder *ompBuilder = moduleTranslation.getOpenMPBuilder();
- llvm::OpenMPIRBuilder::InsertPointOrErrorTy res =
- ompBuilder->createBarrier(builder, llvm::omp::OMPD_barrier);
- if (failed(handleError(res, *op)))
- return failure();
- }
-
- return success();
+ return emitPrivatizationBarrier(op, builder, moduleTranslation,
+ insertBarrier);
}
-static LogicalResult copyFirstPrivateVars(
- mlir::Operation *op, llvm::IRBuilderBase &builder,
- LLVM::ModuleTranslation &moduleTranslation,
- SmallVectorImpl<mlir::Value> &mlirPrivateVars,
- ArrayRef<llvm::Value *> llvmPrivateVars,
- SmallVectorImpl<omp::PrivateClauseOp> &privateDecls, bool insertBarrier,
- llvm::DenseMap<Value, Value> *mappedPrivateVars = nullptr) {
+static LogicalResult
+completePrivateVars(mlir::Operation *op, llvm::IRBuilderBase &builder,
+ LLVM::ModuleTranslation &moduleTranslation,
+ SmallVectorImpl<mlir::Value> &mlirPrivateVars,
+ ArrayRef<llvm::Value *> llvmPrivateVars,
+ SmallVectorImpl<omp::PrivateClauseOp> &privateDecls,
+ bool insertBarrier,
+ llvm::DenseMap<Value, Value> *mappedPrivateVars = nullptr) {
llvm::SmallVector<llvm::Value *> moldVars(mlirPrivateVars.size());
llvm::transform(mlirPrivateVars, moldVars.begin(), [&](mlir::Value mlirVar) {
// map copyRegion rhs arg
@@ -2163,9 +2172,9 @@ static LogicalResult copyFirstPrivateVars(
assert(moldVar);
return moldVar;
});
- return copyFirstPrivateVars(op, builder, moduleTranslation, moldVars,
- llvmPrivateVars, privateDecls, insertBarrier,
- mappedPrivateVars);
+ return completePrivateVars(op, builder, moduleTranslation, moldVars,
+ llvmPrivateVars, privateDecls, insertBarrier,
+ mappedPrivateVars);
}
template <typename T>
@@ -2419,7 +2428,7 @@ convertOmpScope(omp::ScopeOp &scopeOp, llvm::IRBuilderBase &builder,
.failed())
return llvm::make_error<PreviouslyReportedError>();
- if (failed(copyFirstPrivateVars(
+ if (failed(completePrivateVars(
scopeOp, builder, moduleTranslation, privateVarsInfo.mlirVars,
privateVarsInfo.llvmVars, privateVarsInfo.privatizers,
scopeOp.getPrivateNeedsBarrier())))
@@ -3340,7 +3349,7 @@ convertOmpTaskOp(omp::TaskOp taskOp, llvm::IRBuilderBase &builder,
// firstprivate copy region
setInsertPointForPossiblyEmptyBlock(builder, copyBlock);
- if (failed(copyFirstPrivateVars(
+ if (failed(completePrivateVars(
taskOp, builder, moduleTranslation, privateVarsInfo.mlirVars,
taskStructMgr.getLLVMPrivateVarGEPs(), privateVarsInfo.privatizers,
taskOp.getPrivateNeedsBarrier())))
@@ -3811,7 +3820,7 @@ convertOmpTaskloopContextOp(omp::TaskloopContextOp contextOp,
// firstprivate copy region
setInsertPointForPossiblyEmptyBlock(builder, copyBlock);
- if (failed(copyFirstPrivateVars(
+ if (failed(completePrivateVars(
contextOp, builder, moduleTranslation, privateVarsInfo.mlirVars,
taskStructMgr.getLLVMPrivateVarGEPs(), privateVarsInfo.privatizers,
contextOp.getPrivateNeedsBarrier())))
@@ -4110,10 +4119,10 @@ convertOmpTaskloopContextOp(omp::TaskloopContextOp contextOp,
// through a stack allocated structure.
}
- if (failed(copyFirstPrivateVars(contextOp.getOperation(), builder,
- moduleTranslation, srcGEPs, destGEPs,
- privateVarsInfo.privatizers,
- contextOp.getPrivateNeedsBarrier())))
+ if (failed(completePrivateVars(contextOp.getOperation(), builder,
+ moduleTranslation, srcGEPs, destGEPs,
+ privateVarsInfo.privatizers,
+ contextOp.getPrivateNeedsBarrier())))
return llvm::make_error<PreviouslyReportedError>();
return builder.saveIP();
@@ -4707,7 +4716,7 @@ convertOmpWsloop(Operation &opInst, llvm::IRBuilderBase &builder,
.failed())
return failure();
- if (failed(copyFirstPrivateVars(
+ if (failed(completePrivateVars(
wsloopOp, builder, moduleTranslation, privateVarsInfo.mlirVars,
privateVarsInfo.llvmVars, privateVarsInfo.privatizers,
wsloopOp.getPrivateNeedsBarrier())))
@@ -4820,7 +4829,8 @@ convertOmpWsloop(Operation &opInst, llvm::IRBuilderBase &builder,
convertToScheduleKind(schedule), chunk, isSimd,
scheduleMod == omp::ScheduleModifier::monotonic,
scheduleMod == omp::ScheduleModifier::nonmonotonic, isOrdered,
- workshareLoopType, noLoopMode, hasDistSchedule, distScheduleChunk);
+ workshareLoopType, noLoopMode, hasDistSchedule, distScheduleChunk,
+ !wsloopOp.getLinearVars().empty());
if (failed(handleError(wsloopIP, opInst)))
return failure();
@@ -4938,7 +4948,7 @@ convertOmpParallel(omp::ParallelOp opInst, llvm::IRBuilderBase &builder,
.failed())
return llvm::make_error<PreviouslyReportedError>();
- if (failed(copyFirstPrivateVars(
+ if (failed(completePrivateVars(
opInst, builder, moduleTranslation, privateVarsInfo.mlirVars,
privateVarsInfo.llvmVars, privateVarsInfo.privatizers,
opInst.getPrivateNeedsBarrier())))
@@ -5177,7 +5187,7 @@ convertOmpSimd(Operation &opInst, llvm::IRBuilderBase &builder,
.failed())
return failure();
- // No call to copyFirstPrivateVars because FIRSTPRIVATE is not allowed for
+ // No call to completePrivateVars because FIRSTPRIVATE is not allowed for
// SIMD.
assert(afterAllocas.get()->getSinglePredecessor());
@@ -8717,10 +8727,10 @@ convertOmpDistribute(Operation &opInst, llvm::IRBuilderBase &builder,
.failed())
return llvm::make_error<PreviouslyReportedError>();
- if (failed(copyFirstPrivateVars(
- distributeOp, builder, moduleTranslation, privVarsInfo.mlirVars,
- privVarsInfo.llvmVars, privVarsInfo.privatizers,
- distributeOp.getPrivateNeedsBarrier())))
+ if (failed(completePrivateVars(distributeOp, builder, moduleTranslation,
+ privVarsInfo.mlirVars, privVarsInfo.llvmVars,
+ privVarsInfo.privatizers,
+ distributeOp.getPrivateNeedsBarrier())))
return llvm::make_error<PreviouslyReportedError>();
llvm::OpenMPIRBuilder *ompBuilder = moduleTranslation.getOpenMPBuilder();
@@ -9601,7 +9611,7 @@ convertOmpTarget(Operation &opInst, llvm::IRBuilderBase &builder,
.failed())
return llvm::make_error<PreviouslyReportedError>();
- if (failed(copyFirstPrivateVars(
+ if (failed(completePrivateVars(
targetOp, builder, moduleTranslation, privateVarsInfo.mlirVars,
privateVarsInfo.llvmVars, privateVarsInfo.privatizers,
targetOp.getPrivateNeedsBarrier(), &mappedPrivateVars)))
diff --git a/mlir/test/Target/LLVMIR/omptarget-wsloop.mlir b/mlir/test/Target/LLVMIR/omptarget-wsloop.mlir
index acbb3ec916113..a14efc9ae84f8 100644
--- a/mlir/test/Target/LLVMIR/omptarget-wsloop.mlir
+++ b/mlir/test/Target/LLVMIR/omptarget-wsloop.mlir
@@ -29,6 +29,32 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<"dlti.alloca_memo
}
llvm.return
}
+
+ llvm.func @target_wsloop_nowait(%arg0: !llvm.ptr) attributes {omp.declare_target = #omp.declaretarget<device_type = any, capture_clause = to>} {
+ %loop_ub = llvm.mlir.constant(9 : i32) : i32
+ %loop_lb = llvm.mlir.constant(0 : i32) : i32
+ %loop_step = llvm.mlir.constant(1 : i32) : i32
+ omp.wsloop nowait {
+ omp.loop_nest (%loop_cnt) : i32 = (%loop_lb) to (%loop_ub) inclusive step (%loop_step) {
+ %gep = llvm.getelementptr %arg0[0, %loop_cnt] : (!llvm.ptr, i32) -> !llvm.ptr, !llvm.array<10 x i32>
+ llvm.store %loop_cnt, %gep : i32, !llvm.ptr
+ omp.yield
+ }
+ }
+ llvm.return
+ }
+
+ llvm.fun...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/224040
More information about the flang-commits
mailing list