[flang-commits] [flang] 129267e - [Flang][OpenMP] Add nsw flags to OMPIRBuilder loop IV arithmetic (#214165)
via flang-commits
flang-commits at lists.llvm.org
Sun Aug 9 23:41:00 PDT 2026
Author: Kaviya Rajendiran
Date: 2026-08-10T12:10:53+05:30
New Revision: 129267e8fcfca0bc68509817f944eea6b6910ac5
URL: https://github.com/llvm/llvm-project/commit/129267e8fcfca0bc68509817f944eea6b6910ac5
DIFF: https://github.com/llvm/llvm-project/commit/129267e8fcfca0bc68509817f944eea6b6910ac5.diff
LOG: [Flang][OpenMP] Add nsw flags to OMPIRBuilder loop IV arithmetic (#214165)
- Extended the support of `-fno-wrapv` flag setting from frontend to the
OMPIRBuilder via `omp.integer_wrap_around` module attribute.
- When this attribute `omp.integer_wrap_around` is false (-fno-wrapv),
the OMPIRBuilder attaches `nsw` to all loop IV arithmetic.
- This enables SCEV to form proper `AddRec` expressions for the loop IV,
allowing `IndVarSimplify pass` to widen it from i32 to i64 and eliminate
the in-loop sext instruction which helps some backend optimizations and
also producing IR similar to Clang.
Fixes https://github.com/llvm/llvm-project/issues/213718
Added:
flang/test/Lower/OpenMP/integer-wrap-around.f90
mlir/test/Target/LLVMIR/openmp-integer-wrap-around.mlir
mlir/test/Target/LLVMIR/openmp-nsw-collapsed.mlir
Modified:
flang/include/flang/Tools/CrossToolHelpers.h
flang/lib/Frontend/FrontendActions.cpp
flang/test/Integration/OpenMP/host-ir-flag.f90
flang/tools/bbc/bbc.cpp
llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
mlir/include/mlir/Dialect/OpenMP/OpenMPAttrDefs.td
mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
Removed:
################################################################################
diff --git a/flang/include/flang/Tools/CrossToolHelpers.h b/flang/include/flang/Tools/CrossToolHelpers.h
index 6569d34e0f255..fb8007637b114 100644
--- a/flang/include/flang/Tools/CrossToolHelpers.h
+++ b/flang/include/flang/Tools/CrossToolHelpers.h
@@ -206,4 +206,10 @@ struct MLIRToLLVMPassPipelineConfig : public FlangEPCallBacks {
Opts.NoGPULib);
}
+[[maybe_unused]] static void setOpenMPIntegerWrapAround(
+ mlir::ModuleOp module, bool value) {
+ module.getOperation()->setAttr("omp.integer_wrap_around",
+ mlir::omp::IntegerWrapAroundAttr::get(module.getContext(), value));
+}
+
#endif // FORTRAN_TOOLS_CROSS_TOOL_HELPERS_H
diff --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp
index 8955a8f61e513..e21590cc9fa7f 100644
--- a/flang/lib/Frontend/FrontendActions.cpp
+++ b/flang/lib/Frontend/FrontendActions.cpp
@@ -277,6 +277,8 @@ bool CodeGenAction::beginSourceFileAction() {
makeOffloadModuleOpts(ci.getInvocation().getLangOpts()));
mlir::omp::setOpenMPVersionAttribute(
lb.getModule(), ci.getInvocation().getLangOpts().OpenMPVersion);
+ if (!ci.getInvocation().getLoweringOpts().getIntegerWrapAround())
+ setOpenMPIntegerWrapAround(lb.getModule(), false);
}
if (ci.getInvocation().getLangOpts().FastRealMod) {
diff --git a/flang/test/Integration/OpenMP/host-ir-flag.f90 b/flang/test/Integration/OpenMP/host-ir-flag.f90
index 734b446fcccd4..db06b773d39f6 100644
--- a/flang/test/Integration/OpenMP/host-ir-flag.f90
+++ b/flang/test/Integration/OpenMP/host-ir-flag.f90
@@ -9,6 +9,6 @@
!RUN: %flang_fc1 -emit-llvm-bc -fopenmp -o %t.bc %s 2>&1
!RUN: %flang_fc1 -emit-mlir -fopenmp -fopenmp-is-target-device -fopenmp-host-ir-file-path %t.bc -o - %s 2>&1 | FileCheck %s
-!CHECK: module attributes {{{.*}}, omp.host_ir_filepath = "{{.*}}.bc", omp.is_gpu = false, omp.is_target_device = true{{.*}}}
+!CHECK: module attributes {{{.*}}, omp.host_ir_filepath = "{{.*}}.bc",{{.*}}omp.is_gpu = false, omp.is_target_device = true{{.*}}}
subroutine omp_subroutine()
end subroutine omp_subroutine
diff --git a/flang/test/Lower/OpenMP/integer-wrap-around.f90 b/flang/test/Lower/OpenMP/integer-wrap-around.f90
new file mode 100644
index 0000000000000..9e7c847096197
--- /dev/null
+++ b/flang/test/Lower/OpenMP/integer-wrap-around.f90
@@ -0,0 +1,16 @@
+! Tests that the omp.integer_wrap_around module attribute is set when -fno-wrapv (default) is active with OpenMP enabled and absent when -fwrapv is specified.
+
+! RUN: %flang_fc1 -emit-fir -fopenmp %s -o - | FileCheck %s --check-prefix=NOWRAPV
+! RUN: %flang_fc1 -emit-fir -fopenmp -fwrapv %s -o - | FileCheck %s --check-prefix=WRAPV
+
+! NOWRAPV: module attributes {{{.*}}omp.integer_wrap_around = #omp.integer_wrap_around<integer_wrap_around = false>{{.*}}}
+! WRAPV-NOT: omp.integer_wrap_around
+
+subroutine omp_loop(a, b, n)
+ integer :: n, i
+ real(8) :: a(n), b(n)
+ !$omp parallel do
+ do i = 1, n
+ a(i) = b(i)
+ end do
+end subroutine
diff --git a/flang/tools/bbc/bbc.cpp b/flang/tools/bbc/bbc.cpp
index cfb3d20be6955..4d6b0a22f426e 100644
--- a/flang/tools/bbc/bbc.cpp
+++ b/flang/tools/bbc/bbc.cpp
@@ -541,6 +541,8 @@ static llvm::LogicalResult convertFortranSourceToMLIR(
mlir::omp::setOffloadModuleInterfaceAttributes(mlirModule,
offloadModuleOpts);
mlir::omp::setOpenMPVersionAttribute(mlirModule, setOpenMPVersion);
+ if (!integerWrapAround)
+ setOpenMPIntegerWrapAround(mlirModule, false);
}
burnside.lower(parseTree, semanticsContext);
std::error_code ec;
diff --git a/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h b/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
index 1965f7b983805..38a56e975a807 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
+++ b/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
@@ -132,6 +132,11 @@ class OpenMPIRBuilderConfig {
/// Separator used between all of the rest consecutive parts of s name.
std::optional<StringRef> Separator;
+ /// Flag for specifying whether the no-signed-wrap (nsw) flag should be added
+ /// to loop induction variable arithmetic. Set when the frontend guarantees
+ /// that signed integer overflow is undefined (with -fno-wrapv).
+ std::optional<bool> NoSignedWrap;
+
// Grid Value for the GPU target.
std::optional<omp::GV> GridValue;
@@ -176,6 +181,9 @@ class OpenMPIRBuilderConfig {
unsigned getDefaultTargetAS() const { return DefaultTargetAS; }
+ bool hasNoSignedWrap() const { return NoSignedWrap.value_or(false); }
+ void setNoSignedWrap(bool Value) { NoSignedWrap = Value; }
+
CallingConv::ID getRuntimeCC() const { return RuntimeCC; }
bool hasRequiresFlags() const { return RequiresFlags; }
@@ -4198,13 +4206,13 @@ class OpenMPIRBuilder {
/// \param PostInsertBefore Where to insert BBs that execute after the body.
/// \param Name Base name used to derive BB
/// and instruction names.
+ /// \param IsCollapsed Whether this is a collapsed loop.
///
/// \returns The CanonicalLoopInfo that represents the emitted loop.
- LLVM_ABI CanonicalLoopInfo *createLoopSkeleton(DebugLoc DL, Value *TripCount,
- Function *F,
- BasicBlock *PreInsertBefore,
- BasicBlock *PostInsertBefore,
- const Twine &Name = {});
+ LLVM_ABI CanonicalLoopInfo *
+ createLoopSkeleton(DebugLoc DL, Value *TripCount, Function *F,
+ BasicBlock *PreInsertBefore, BasicBlock *PostInsertBefore,
+ const Twine &Name = {}, bool IsCollapsed = false);
/// OMP Offload Info Metadata name string
const std::string ompOffloadInfoName = "omp_offload.info";
diff --git a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
index 5a363d0ac3dbd..63eab978b1db0 100644
--- a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
+++ b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
@@ -5766,7 +5766,7 @@ void OpenMPIRBuilder::createScanBBs(ScanInfo *ScanRedInfo) {
}
CanonicalLoopInfo *OpenMPIRBuilder::createLoopSkeleton(
DebugLoc DL, Value *TripCount, Function *F, BasicBlock *PreInsertBefore,
- BasicBlock *PostInsertBefore, const Twine &Name) {
+ BasicBlock *PostInsertBefore, const Twine &Name, bool IsCollapsed) {
Module *M = F->getParent();
LLVMContext &Ctx = M->getContext();
Type *IndVarTy = TripCount->getType();
@@ -5807,8 +5807,29 @@ CanonicalLoopInfo *OpenMPIRBuilder::createLoopSkeleton(
Builder.CreateBr(Latch);
Builder.SetInsertPoint(Latch);
- Value *Next = Builder.CreateAdd(IndVarPHI, ConstantInt::get(IndVarTy, 1),
- "omp_" + Name + ".next", /*HasNUW=*/true);
+ // Decide whether the induction variable increment can carry nsw.
+ //
+ // Single loops: nsw is always kept (matching Clang). Any Fortran program
+ // whose trip count overflows i32 is non-conforming per F2018 11.1.7.4.1, so
+ // for valid programs 0 <= count <= INT_MAX always holds.
+ //
+ // Collapsed loops: the trip count is a product that can overflow i32 even for
+ // a conforming program, so nsw is kept only when the product is a constant
+ // that provably fits, dropped otherwise.
+ bool HasNSW = Config.hasNoSignedWrap();
+ if (HasNSW) {
+ if (auto *CI = dyn_cast<ConstantInt>(TripCount)) {
+ unsigned BitWidth = CI->getType()->getIntegerBitWidth();
+ APInt SignedMax = APInt::getSignedMaxValue(BitWidth);
+ if (CI->getValue().ugt(SignedMax))
+ HasNSW = false;
+ } else if (IsCollapsed) {
+ HasNSW = false;
+ }
+ }
+ Value *Next =
+ Builder.CreateAdd(IndVarPHI, ConstantInt::get(IndVarTy, 1),
+ "omp_" + Name + ".next", /*HasNUW=*/true, HasNSW);
Builder.CreateBr(Header);
IndVarPHI->addIncoming(Next, Latch);
@@ -6004,8 +6025,10 @@ Expected<CanonicalLoopInfo *> OpenMPIRBuilder::createCanonicalLoop(
auto BodyGen = [=](InsertPointTy CodeGenIP, Value *IV) {
Builder.restoreIP(CodeGenIP);
- Value *Span = Builder.CreateMul(IV, Step);
- Value *IndVar = Builder.CreateAdd(Span, Start);
+ Value *Span = Builder.CreateMul(IV, Step, "", /*HasNUW=*/false,
+ /*HasNSW=*/Config.hasNoSignedWrap());
+ Value *IndVar = Builder.CreateAdd(Span, Start, "", /*HasNUW=*/false,
+ /*HasNSW=*/Config.hasNoSignedWrap());
if (InScan)
ScanRedInfo->IV = IndVar;
return BodyGenCB(Builder.saveIP(), IndVar);
@@ -6160,7 +6183,8 @@ OpenMPIRBuilder::InsertPointOrErrorTy OpenMPIRBuilder::applyStaticWorkshareLoop(
Builder.SetInsertPoint(CLI->getBody(),
CLI->getBody()->getFirstInsertionPt());
Builder.SetCurrentDebugLocation(DL);
- return Builder.CreateAdd(OldIV, LowerBound);
+ return Builder.CreateAdd(OldIV, LowerBound, "", /*HasNUW=*/false,
+ /*HasNSW=*/Config.hasNoSignedWrap());
});
// In the "exit" block, call the "fini" function.
@@ -7005,7 +7029,8 @@ OpenMPIRBuilder::collapseLoops(DebugLoc DL, ArrayRef<CanonicalLoopInfo *> Loops,
// Create the collapsed loop control flow.
CanonicalLoopInfo *Result =
createLoopSkeleton(DL, CollapsedTripCount, F,
- OrigPreheader->getNextNode(), OrigAfter, "collapsed");
+ OrigPreheader->getNextNode(), OrigAfter, "collapsed",
+ /*IsCollapsed=*/true);
// Build the collapsed loop body code.
// Start with deriving the input loop induction variables from the collapsed
diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPAttrDefs.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPAttrDefs.td
index f6bc8f11ccccb..8d8fcf9e381e8 100644
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPAttrDefs.td
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPAttrDefs.td
@@ -101,4 +101,15 @@ def VersionAttr : OpenMP_Attr<"Version", "version"> {
let assemblyFormat = "`<` struct(params) `>`";
}
+//===----------------------------------------------------------------------===//
+// IntegerWrapAroundAttr
+//===----------------------------------------------------------------------===//
+
+def IntegerWrapAroundAttr
+ : OpenMP_Attr<"IntegerWrapAround", "integer_wrap_around"> {
+ let parameters = (ins "bool":$integer_wrap_around);
+
+ let assemblyFormat = "`<` struct(params) `>`";
+}
+
#endif // OPENMP_ATTR_DEFS
diff --git a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
index 2c81c9231a9b7..4c4f8ba9bce3d 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
@@ -9512,6 +9512,16 @@ LogicalResult OpenMPDialectLLVMIRTranslationInterface::amendOperation(
}
return failure();
})
+ .Case("omp.integer_wrap_around",
+ [&](Attribute attr) {
+ if (auto wrapAttr = dyn_cast<omp::IntegerWrapAroundAttr>(attr)) {
+ llvm::OpenMPIRBuilderConfig &config =
+ moduleTranslation.getOpenMPBuilder()->Config;
+ config.setNoSignedWrap(!wrapAttr.getIntegerWrapAround());
+ return success();
+ }
+ return failure();
+ })
.Default([](Attribute) {
// Fall through for omp attributes that do not require lowering.
return success();
diff --git a/mlir/test/Target/LLVMIR/openmp-integer-wrap-around.mlir b/mlir/test/Target/LLVMIR/openmp-integer-wrap-around.mlir
new file mode 100644
index 0000000000000..a2f42aa1f7bd9
--- /dev/null
+++ b/mlir/test/Target/LLVMIR/openmp-integer-wrap-around.mlir
@@ -0,0 +1,77 @@
+// Tests how the omp.integer_wrap_around module attribute controls nsw flags on IV arithmetic in the generated LLVM IR:
+// - <omp.integer_wrap_around = absent> -> default behaviour, no nsw
+// - <omp.integer_wrap_around = true> -> wrap around allowed (-fwrapv), no nsw
+// - <omp.integer_wrap_around = false> -> wrap around disallowed, nsw emitted
+
+// RUN: mlir-translate -mlir-to-llvmir -split-input-file %s | FileCheck %s
+
+//-------------------------------------------------------------------------//
+// Default behaviour: without the attribute, IV increment should NOT have nsw.
+//-------------------------------------------------------------------------//
+
+// CHECK-LABEL: define void @wsloop_default_no_nsw
+// CHECK: omp_loop.header:
+// CHECK: %omp_loop.iv = phi i32 [ 0, %omp_loop.preheader ], [ %omp_loop.next, %omp_loop.inc ]
+// CHECK: omp_loop.body:
+// CHECK-NOT: add nsw
+// CHECK: omp_loop.inc:
+// CHECK: %omp_loop.next = add nuw i32 %omp_loop.iv, 1
+llvm.func @wsloop_default_no_nsw(%lb : i32, %ub : i32, %step : i32) {
+ omp.wsloop {
+ omp.loop_nest (%iv) : i32 = (%lb) to (%ub) step (%step) {
+ omp.yield
+ }
+ }
+ llvm.return
+}
+
+// -----
+
+//-----------------------------------------------------------------------------------//
+// With omp.integer_wrap_around = true (-fwrapv), IV increment should NOT have nsw.
+//----------------------------------------------------------------------------------//
+
+// CHECK-LABEL: define void @wsloop_wrapv_no_nsw
+// CHECK: omp_loop.header:
+// CHECK: %omp_loop.iv = phi i32 [ 0, %omp_loop.preheader ], [ %omp_loop.next, %omp_loop.inc ]
+// CHECK: omp_loop.body:
+// CHECK-NOT: add nsw
+// CHECK: omp_loop.inc:
+// CHECK: %omp_loop.next = add nuw i32 %omp_loop.iv, 1
+module attributes {omp.integer_wrap_around = #omp.integer_wrap_around<integer_wrap_around = true>} {
+ llvm.func @wsloop_wrapv_no_nsw(%lb : i32, %ub : i32, %step : i32) {
+ omp.wsloop {
+ omp.loop_nest (%iv) : i32 = (%lb) to (%ub) step (%step) {
+ omp.yield
+ }
+ }
+ llvm.return
+ }
+}
+
+// -----
+
+//-----------------------------------------------------------------------//
+// With omp.integer_wrap_around = false, IV increment should have nsw.
+//-----------------------------------------------------------------------//
+// CHECK-LABEL: define void @wsloop_nsw_iv
+// CHECK: omp_loop.header:
+// CHECK: %omp_loop.iv = phi i32 [ 0, %omp_loop.preheader ], [ %omp_loop.next, %omp_loop.inc ]
+
+// CHECK: omp_loop.body:
+// CHECK: %[[IV_ADD:[0-9]+]] = add nsw i32 %omp_loop.iv, %{{[0-9]+}}
+// CHECK: %[[MUL:[0-9]+]] = mul nsw i32 %[[IV_ADD]], %{{[0-9]+}}
+// CHECK: %{{[0-9]+}} = add nsw i32 %[[MUL]], %{{[0-9]+}}
+
+// CHECK: omp_loop.inc:
+// CHECK: %omp_loop.next = add nuw nsw i32 %omp_loop.iv, 1
+module attributes {omp.integer_wrap_around = #omp.integer_wrap_around<integer_wrap_around = false>} {
+ llvm.func @wsloop_nsw_iv(%lb : i32, %ub : i32, %step : i32) {
+ omp.wsloop {
+ omp.loop_nest (%iv) : i32 = (%lb) to (%ub) step (%step) {
+ omp.yield
+ }
+ }
+ llvm.return
+ }
+}
diff --git a/mlir/test/Target/LLVMIR/openmp-nsw-collapsed.mlir b/mlir/test/Target/LLVMIR/openmp-nsw-collapsed.mlir
new file mode 100644
index 0000000000000..3a801951c4be4
--- /dev/null
+++ b/mlir/test/Target/LLVMIR/openmp-nsw-collapsed.mlir
@@ -0,0 +1,90 @@
+// Test the behavior of nsw on loop IV increment for collapsed loops.
+
+// RUN: mlir-translate -mlir-to-llvmir -split-input-file %s | FileCheck %s
+
+//-------------------------------------------------------------------------//
+// Case 1: Collapsed loop with trip count > INT_MAX (46341*46341)
+//-------------------------------------------------------------------------//
+
+// CHECK-LABEL: define void @collapsed_overflow_no_nsw
+// CHECK: omp_collapsed.inc:
+// CHECK: %omp_collapsed.next = add nuw i32 %omp_collapsed.iv, 1
+// CHECK-NOT: nsw
+module attributes {omp.integer_wrap_around = #omp.integer_wrap_around<integer_wrap_around = false>} {
+ llvm.func @collapsed_overflow_no_nsw() {
+ %lb = llvm.mlir.constant(0 : i32) : i32
+ %ub1 = llvm.mlir.constant(46340 : i32) : i32
+ %ub2 = llvm.mlir.constant(46340 : i32) : i32
+ %step = llvm.mlir.constant(1 : i32) : i32
+ omp.wsloop {
+ omp.loop_nest (%iv1, %iv2) : i32 = (%lb, %lb) to (%ub1, %ub2) inclusive step (%step, %step) collapse(2) {
+ omp.yield
+ }
+ }
+ llvm.return
+ }
+}
+
+// -----
+
+//-------------------------------------------------------------------------//
+// Case 2: Collapsed loop with trip count <= INT_MAX (99*99)
+//-------------------------------------------------------------------------//
+
+// CHECK-LABEL: define void @collapsed_small_with_nsw
+// CHECK: omp_collapsed.inc:
+// CHECK: %omp_collapsed.next = add nuw nsw i32 %omp_collapsed.iv, 1
+module attributes {omp.integer_wrap_around = #omp.integer_wrap_around<integer_wrap_around = false>} {
+ llvm.func @collapsed_small_with_nsw() {
+ %lb = llvm.mlir.constant(0 : i32) : i32
+ %ub = llvm.mlir.constant(99 : i32) : i32
+ %step = llvm.mlir.constant(1 : i32) : i32
+ omp.wsloop {
+ omp.loop_nest (%iv1, %iv2) : i32 = (%lb, %lb) to (%ub, %ub) inclusive step (%step, %step) collapse(2) {
+ omp.yield
+ }
+ }
+ llvm.return
+ }
+}
+
+// -----
+
+//-------------------------------------------------------------------------//
+// Case 3: Collapsed loop with dynamic trip count
+//-------------------------------------------------------------------------//
+
+// CHECK-LABEL: define void @collapsed_dynamic_no_nsw
+// CHECK: omp_collapsed.inc:
+// CHECK: %omp_collapsed.next = add nuw i32 %omp_collapsed.iv, 1
+// CHECK-NOT: nsw
+module attributes {omp.integer_wrap_around = #omp.integer_wrap_around<integer_wrap_around = false>} {
+ llvm.func @collapsed_dynamic_no_nsw(%lb : i32, %ub1 : i32, %ub2 : i32, %step : i32) {
+ omp.wsloop {
+ omp.loop_nest (%iv1, %iv2) : i32 = (%lb, %lb) to (%ub1, %ub2) step (%step, %step) collapse(2) {
+ omp.yield
+ }
+ }
+ llvm.return
+ }
+}
+
+// -----
+
+//-------------------------------------------------------------------------//
+// Case 4: Single loop with dynamic trip count
+//-------------------------------------------------------------------------//
+
+// CHECK-LABEL: define void @single_loop_with_nsw
+// CHECK: omp_loop.inc:
+// CHECK: %omp_loop.next = add nuw nsw i32 %omp_loop.iv, 1
+module attributes {omp.integer_wrap_around = #omp.integer_wrap_around<integer_wrap_around = false>} {
+ llvm.func @single_loop_with_nsw(%lb : i32, %ub : i32, %step : i32) {
+ omp.wsloop {
+ omp.loop_nest (%iv) : i32 = (%lb) to (%ub) step (%step) {
+ omp.yield
+ }
+ }
+ llvm.return
+ }
+}
More information about the flang-commits
mailing list