Skip to content

Commit 30990c0

Browse files
authored
Revert "[flang][fir] Lower do concurrent loop nests to fir.do_concurrent (#132904)" (#135904)
This reverts commit 04b87e1. The reasons for reverting is that the following: 1. I still need need to upstream some part of the do concurrent to OpenMP pass from our downstream implementation and taking this in downstream will make things more difficult. 2. I still need to work on a solution for modeling locality specifiers on `hlfir.do_concurrent` ops. I would prefer to do that and merge the entire stack together instead of having a partial solution. After merging the revert I will reopen the origianl PR and keep it updated against main until I finish the above.
1 parent 616613c commit 30990c0

File tree

13 files changed

+130
-208
lines changed

13 files changed

+130
-208
lines changed

flang/lib/Lower/Bridge.cpp

Lines changed: 92 additions & 136 deletions
Original file line numberDiff line numberDiff line change
@@ -94,11 +94,10 @@ struct IncrementLoopInfo {
9494
template <typename T>
9595
explicit IncrementLoopInfo(Fortran::semantics::Symbol &sym, const T &lower,
9696
const T &upper, const std::optional<T> &step,
97-
bool isConcurrent = false)
97+
bool isUnordered = false)
9898
: loopVariableSym{&sym}, lowerExpr{Fortran::semantics::GetExpr(lower)},
9999
upperExpr{Fortran::semantics::GetExpr(upper)},
100-
stepExpr{Fortran::semantics::GetExpr(step)},
101-
isConcurrent{isConcurrent} {}
100+
stepExpr{Fortran::semantics::GetExpr(step)}, isUnordered{isUnordered} {}
102101

103102
IncrementLoopInfo(IncrementLoopInfo &&) = default;
104103
IncrementLoopInfo &operator=(IncrementLoopInfo &&x) = default;
@@ -121,7 +120,7 @@ struct IncrementLoopInfo {
121120
const Fortran::lower::SomeExpr *upperExpr;
122121
const Fortran::lower::SomeExpr *stepExpr;
123122
const Fortran::lower::SomeExpr *maskExpr = nullptr;
124-
bool isConcurrent;
123+
bool isUnordered; // do concurrent, forall
125124
llvm::SmallVector<const Fortran::semantics::Symbol *> localSymList;
126125
llvm::SmallVector<const Fortran::semantics::Symbol *> localInitSymList;
127126
llvm::SmallVector<
@@ -131,7 +130,7 @@ struct IncrementLoopInfo {
131130
mlir::Value loopVariable = nullptr;
132131

133132
// Data members for structured loops.
134-
mlir::Operation *loopOp = nullptr;
133+
fir::DoLoopOp doLoop = nullptr;
135134

136135
// Data members for unstructured loops.
137136
bool hasRealControl = false;
@@ -1981,7 +1980,7 @@ class FirConverter : public Fortran::lower::AbstractConverter {
19811980
llvm_unreachable("illegal reduction operator");
19821981
}
19831982

1984-
/// Collect DO CONCURRENT loop control information.
1983+
/// Collect DO CONCURRENT or FORALL loop control information.
19851984
IncrementLoopNestInfo getConcurrentControl(
19861985
const Fortran::parser::ConcurrentHeader &header,
19871986
const std::list<Fortran::parser::LocalitySpec> &localityList = {}) {
@@ -2292,14 +2291,8 @@ class FirConverter : public Fortran::lower::AbstractConverter {
22922291
mlir::LLVM::LoopAnnotationAttr la = mlir::LLVM::LoopAnnotationAttr::get(
22932292
builder->getContext(), {}, /*vectorize=*/va, {}, /*unroll*/ ua,
22942293
/*unroll_and_jam*/ uja, {}, {}, {}, {}, {}, {}, {}, {}, {}, {});
2295-
if (has_attrs) {
2296-
if (auto loopOp = mlir::dyn_cast<fir::DoLoopOp>(info.loopOp))
2297-
loopOp.setLoopAnnotationAttr(la);
2298-
2299-
if (auto doConcurrentOp =
2300-
mlir::dyn_cast<fir::DoConcurrentLoopOp>(info.loopOp))
2301-
doConcurrentOp.setLoopAnnotationAttr(la);
2302-
}
2294+
if (has_attrs)
2295+
info.doLoop.setLoopAnnotationAttr(la);
23032296
}
23042297

23052298
/// Generate FIR to begin a structured or unstructured increment loop nest.
@@ -2308,77 +2301,96 @@ class FirConverter : public Fortran::lower::AbstractConverter {
23082301
llvm::SmallVectorImpl<const Fortran::parser::CompilerDirective *> &dirs) {
23092302
assert(!incrementLoopNestInfo.empty() && "empty loop nest");
23102303
mlir::Location loc = toLocation();
2304+
mlir::Operation *boundsAndStepIP = nullptr;
23112305
mlir::arith::IntegerOverflowFlags iofBackup{};
23122306

2313-
llvm::SmallVector<mlir::Value> nestLBs;
2314-
llvm::SmallVector<mlir::Value> nestUBs;
2315-
llvm::SmallVector<mlir::Value> nestSts;
2316-
llvm::SmallVector<mlir::Value> nestReduceOperands;
2317-
llvm::SmallVector<mlir::Attribute> nestReduceAttrs;
2318-
bool genDoConcurrent = false;
2319-
23202307
for (IncrementLoopInfo &info : incrementLoopNestInfo) {
2321-
genDoConcurrent = info.isStructured() && info.isConcurrent;
2322-
2323-
if (!genDoConcurrent)
2324-
info.loopVariable = genLoopVariableAddress(loc, *info.loopVariableSym,
2325-
info.isConcurrent);
2326-
2327-
if (!getLoweringOptions().getIntegerWrapAround()) {
2328-
iofBackup = builder->getIntegerOverflowFlags();
2329-
builder->setIntegerOverflowFlags(
2330-
mlir::arith::IntegerOverflowFlags::nsw);
2331-
}
2308+
mlir::Value lowerValue;
2309+
mlir::Value upperValue;
2310+
mlir::Value stepValue;
23322311

2333-
nestLBs.push_back(genControlValue(info.lowerExpr, info));
2334-
nestUBs.push_back(genControlValue(info.upperExpr, info));
2335-
bool isConst = true;
2336-
nestSts.push_back(genControlValue(
2337-
info.stepExpr, info, info.isStructured() ? nullptr : &isConst));
2312+
{
2313+
mlir::OpBuilder::InsertionGuard guard(*builder);
23382314

2339-
if (!getLoweringOptions().getIntegerWrapAround())
2340-
builder->setIntegerOverflowFlags(iofBackup);
2315+
// Set the IP before the first loop in the nest so that all nest bounds
2316+
// and step values are created outside the nest.
2317+
if (boundsAndStepIP)
2318+
builder->setInsertionPointAfter(boundsAndStepIP);
23412319

2342-
// Use a temp variable for unstructured loops with non-const step.
2343-
if (!isConst) {
2344-
mlir::Value stepValue = nestSts.back();
2345-
info.stepVariable = builder->createTemporary(loc, stepValue.getType());
2346-
builder->create<fir::StoreOp>(loc, stepValue, info.stepVariable);
2347-
}
2348-
2349-
if (genDoConcurrent && nestReduceOperands.empty()) {
2350-
// Create DO CONCURRENT reduce operands and attributes
2351-
for (const auto &reduceSym : info.reduceSymList) {
2352-
const fir::ReduceOperationEnum reduceOperation = reduceSym.first;
2353-
const Fortran::semantics::Symbol *sym = reduceSym.second;
2354-
fir::ExtendedValue exv = getSymbolExtendedValue(*sym, nullptr);
2355-
nestReduceOperands.push_back(fir::getBase(exv));
2356-
auto reduceAttr =
2357-
fir::ReduceAttr::get(builder->getContext(), reduceOperation);
2358-
nestReduceAttrs.push_back(reduceAttr);
2320+
info.loopVariable = genLoopVariableAddress(loc, *info.loopVariableSym,
2321+
info.isUnordered);
2322+
if (!getLoweringOptions().getIntegerWrapAround()) {
2323+
iofBackup = builder->getIntegerOverflowFlags();
2324+
builder->setIntegerOverflowFlags(
2325+
mlir::arith::IntegerOverflowFlags::nsw);
2326+
}
2327+
lowerValue = genControlValue(info.lowerExpr, info);
2328+
upperValue = genControlValue(info.upperExpr, info);
2329+
bool isConst = true;
2330+
stepValue = genControlValue(info.stepExpr, info,
2331+
info.isStructured() ? nullptr : &isConst);
2332+
if (!getLoweringOptions().getIntegerWrapAround())
2333+
builder->setIntegerOverflowFlags(iofBackup);
2334+
boundsAndStepIP = stepValue.getDefiningOp();
2335+
2336+
// Use a temp variable for unstructured loops with non-const step.
2337+
if (!isConst) {
2338+
info.stepVariable =
2339+
builder->createTemporary(loc, stepValue.getType());
2340+
boundsAndStepIP =
2341+
builder->create<fir::StoreOp>(loc, stepValue, info.stepVariable);
23592342
}
23602343
}
2361-
}
23622344

2363-
for (auto [info, lowerValue, upperValue, stepValue] :
2364-
llvm::zip_equal(incrementLoopNestInfo, nestLBs, nestUBs, nestSts)) {
23652345
// Structured loop - generate fir.do_loop.
23662346
if (info.isStructured()) {
2367-
if (genDoConcurrent)
2368-
continue;
2369-
2370-
// The loop variable is a doLoop op argument.
23712347
mlir::Type loopVarType = info.getLoopVariableType();
2372-
auto loopOp = builder->create<fir::DoLoopOp>(
2373-
loc, lowerValue, upperValue, stepValue, /*unordered=*/false,
2374-
/*finalCountValue=*/true,
2375-
builder->createConvert(loc, loopVarType, lowerValue));
2376-
info.loopOp = loopOp;
2377-
builder->setInsertionPointToStart(loopOp.getBody());
2378-
mlir::Value loopValue = loopOp.getRegionIterArgs()[0];
2379-
2348+
mlir::Value loopValue;
2349+
if (info.isUnordered) {
2350+
llvm::SmallVector<mlir::Value> reduceOperands;
2351+
llvm::SmallVector<mlir::Attribute> reduceAttrs;
2352+
// Create DO CONCURRENT reduce operands and attributes
2353+
for (const auto &reduceSym : info.reduceSymList) {
2354+
const fir::ReduceOperationEnum reduce_operation = reduceSym.first;
2355+
const Fortran::semantics::Symbol *sym = reduceSym.second;
2356+
fir::ExtendedValue exv = getSymbolExtendedValue(*sym, nullptr);
2357+
reduceOperands.push_back(fir::getBase(exv));
2358+
auto reduce_attr =
2359+
fir::ReduceAttr::get(builder->getContext(), reduce_operation);
2360+
reduceAttrs.push_back(reduce_attr);
2361+
}
2362+
// The loop variable value is explicitly updated.
2363+
info.doLoop = builder->create<fir::DoLoopOp>(
2364+
loc, lowerValue, upperValue, stepValue, /*unordered=*/true,
2365+
/*finalCountValue=*/false, /*iterArgs=*/std::nullopt,
2366+
llvm::ArrayRef<mlir::Value>(reduceOperands), reduceAttrs);
2367+
builder->setInsertionPointToStart(info.doLoop.getBody());
2368+
loopValue = builder->createConvert(loc, loopVarType,
2369+
info.doLoop.getInductionVar());
2370+
} else {
2371+
// The loop variable is a doLoop op argument.
2372+
info.doLoop = builder->create<fir::DoLoopOp>(
2373+
loc, lowerValue, upperValue, stepValue, /*unordered=*/false,
2374+
/*finalCountValue=*/true,
2375+
builder->createConvert(loc, loopVarType, lowerValue));
2376+
builder->setInsertionPointToStart(info.doLoop.getBody());
2377+
loopValue = info.doLoop.getRegionIterArgs()[0];
2378+
}
23802379
// Update the loop variable value in case it has non-index references.
23812380
builder->create<fir::StoreOp>(loc, loopValue, info.loopVariable);
2381+
if (info.maskExpr) {
2382+
Fortran::lower::StatementContext stmtCtx;
2383+
mlir::Value maskCond = createFIRExpr(loc, info.maskExpr, stmtCtx);
2384+
stmtCtx.finalizeAndReset();
2385+
mlir::Value maskCondCast =
2386+
builder->createConvert(loc, builder->getI1Type(), maskCond);
2387+
auto ifOp = builder->create<fir::IfOp>(loc, maskCondCast,
2388+
/*withElseRegion=*/false);
2389+
builder->setInsertionPointToStart(&ifOp.getThenRegion().front());
2390+
}
2391+
if (info.hasLocalitySpecs())
2392+
handleLocalitySpecs(info);
2393+
23822394
addLoopAnnotationAttr(info, dirs);
23832395
continue;
23842396
}
@@ -2442,60 +2454,6 @@ class FirConverter : public Fortran::lower::AbstractConverter {
24422454
builder->restoreInsertionPoint(insertPt);
24432455
}
24442456
}
2445-
2446-
if (genDoConcurrent) {
2447-
auto loopWrapperOp = builder->create<fir::DoConcurrentOp>(loc);
2448-
builder->setInsertionPointToStart(
2449-
builder->createBlock(&loopWrapperOp.getRegion()));
2450-
2451-
for (IncrementLoopInfo &info : llvm::reverse(incrementLoopNestInfo)) {
2452-
info.loopVariable = genLoopVariableAddress(loc, *info.loopVariableSym,
2453-
info.isConcurrent);
2454-
}
2455-
2456-
builder->setInsertionPointToEnd(loopWrapperOp.getBody());
2457-
auto loopOp = builder->create<fir::DoConcurrentLoopOp>(
2458-
loc, nestLBs, nestUBs, nestSts, nestReduceOperands,
2459-
nestReduceAttrs.empty()
2460-
? nullptr
2461-
: mlir::ArrayAttr::get(builder->getContext(), nestReduceAttrs),
2462-
nullptr);
2463-
2464-
llvm::SmallVector<mlir::Type> loopBlockArgTypes(
2465-
incrementLoopNestInfo.size(), builder->getIndexType());
2466-
llvm::SmallVector<mlir::Location> loopBlockArgLocs(
2467-
incrementLoopNestInfo.size(), loc);
2468-
mlir::Region &loopRegion = loopOp.getRegion();
2469-
mlir::Block *loopBlock = builder->createBlock(
2470-
&loopRegion, loopRegion.begin(), loopBlockArgTypes, loopBlockArgLocs);
2471-
builder->setInsertionPointToStart(loopBlock);
2472-
2473-
for (auto [info, blockArg] :
2474-
llvm::zip_equal(incrementLoopNestInfo, loopBlock->getArguments())) {
2475-
info.loopOp = loopOp;
2476-
mlir::Value loopValue =
2477-
builder->createConvert(loc, info.getLoopVariableType(), blockArg);
2478-
builder->create<fir::StoreOp>(loc, loopValue, info.loopVariable);
2479-
2480-
if (info.maskExpr) {
2481-
Fortran::lower::StatementContext stmtCtx;
2482-
mlir::Value maskCond = createFIRExpr(loc, info.maskExpr, stmtCtx);
2483-
stmtCtx.finalizeAndReset();
2484-
mlir::Value maskCondCast =
2485-
builder->createConvert(loc, builder->getI1Type(), maskCond);
2486-
auto ifOp = builder->create<fir::IfOp>(loc, maskCondCast,
2487-
/*withElseRegion=*/false);
2488-
builder->setInsertionPointToStart(&ifOp.getThenRegion().front());
2489-
}
2490-
}
2491-
2492-
IncrementLoopInfo &innermostInfo = incrementLoopNestInfo.back();
2493-
2494-
if (innermostInfo.hasLocalitySpecs())
2495-
handleLocalitySpecs(innermostInfo);
2496-
2497-
addLoopAnnotationAttr(innermostInfo, dirs);
2498-
}
24992457
}
25002458

25012459
/// Generate FIR to end a structured or unstructured increment loop nest.
@@ -2512,31 +2470,29 @@ class FirConverter : public Fortran::lower::AbstractConverter {
25122470
it != rend; ++it) {
25132471
IncrementLoopInfo &info = *it;
25142472
if (info.isStructured()) {
2515-
// End fir.do_concurent.loop.
2516-
if (info.isConcurrent) {
2517-
builder->setInsertionPointAfter(info.loopOp->getParentOp());
2473+
// End fir.do_loop.
2474+
if (info.isUnordered) {
2475+
builder->setInsertionPointAfter(info.doLoop);
25182476
continue;
25192477
}
2520-
2521-
// End fir.do_loop.
25222478
// Decrement tripVariable.
2523-
auto doLoopOp = mlir::cast<fir::DoLoopOp>(info.loopOp);
2524-
builder->setInsertionPointToEnd(doLoopOp.getBody());
2479+
builder->setInsertionPointToEnd(info.doLoop.getBody());
25252480
llvm::SmallVector<mlir::Value, 2> results;
25262481
results.push_back(builder->create<mlir::arith::AddIOp>(
2527-
loc, doLoopOp.getInductionVar(), doLoopOp.getStep(), iofAttr));
2482+
loc, info.doLoop.getInductionVar(), info.doLoop.getStep(),
2483+
iofAttr));
25282484
// Step loopVariable to help optimizations such as vectorization.
25292485
// Induction variable elimination will clean up as necessary.
25302486
mlir::Value step = builder->createConvert(
2531-
loc, info.getLoopVariableType(), doLoopOp.getStep());
2487+
loc, info.getLoopVariableType(), info.doLoop.getStep());
25322488
mlir::Value loopVar =
25332489
builder->create<fir::LoadOp>(loc, info.loopVariable);
25342490
results.push_back(
25352491
builder->create<mlir::arith::AddIOp>(loc, loopVar, step, iofAttr));
25362492
builder->create<fir::ResultOp>(loc, results);
2537-
builder->setInsertionPointAfter(doLoopOp);
2493+
builder->setInsertionPointAfter(info.doLoop);
25382494
// The loop control variable may be used after the loop.
2539-
builder->create<fir::StoreOp>(loc, doLoopOp.getResult(1),
2495+
builder->create<fir::StoreOp>(loc, info.doLoop.getResult(1),
25402496
info.loopVariable);
25412497
continue;
25422498
}

flang/lib/Optimizer/Builder/FIRBuilder.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -280,9 +280,6 @@ mlir::Block *fir::FirOpBuilder::getAllocaBlock() {
280280
if (auto cufKernelOp = getRegion().getParentOfType<cuf::KernelOp>())
281281
return &cufKernelOp.getRegion().front();
282282

283-
if (auto doConcurentOp = getRegion().getParentOfType<fir::DoConcurrentOp>())
284-
return doConcurentOp.getBody();
285-
286283
return getEntryBlock();
287284
}
288285

flang/test/Lower/do_concurrent.f90

Lines changed: 7 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,6 @@ subroutine sub1(n)
1414
implicit none
1515
integer :: n, m, i, j, k
1616
integer, dimension(n) :: a
17-
!CHECK: %[[N_DECL:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %{{.*}} {uniq_name = "_QFsub1En"}
18-
!CHECK: %[[A_DECL:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) {uniq_name = "_QFsub1Ea"}
19-
2017
!CHECK: %[[LB1:.*]] = arith.constant 1 : i32
2118
!CHECK: %[[LB1_CVT:.*]] = fir.convert %[[LB1]] : (i32) -> index
2219
!CHECK: %[[UB1:.*]] = fir.load %{{.*}}#0 : !fir.ref<i32>
@@ -32,30 +29,10 @@ subroutine sub1(n)
3229
!CHECK: %[[UB3:.*]] = arith.constant 10 : i32
3330
!CHECK: %[[UB3_CVT:.*]] = fir.convert %[[UB3]] : (i32) -> index
3431

35-
!CHECK: fir.do_concurrent
36-
!CHECK: %[[I:.*]] = fir.alloca i32 {bindc_name = "i"}
37-
!CHECK: %[[I_DECL:.*]]:2 = hlfir.declare %[[I]]
38-
!CHECK: %[[J:.*]] = fir.alloca i32 {bindc_name = "j"}
39-
!CHECK: %[[J_DECL:.*]]:2 = hlfir.declare %[[J]]
40-
!CHECK: %[[K:.*]] = fir.alloca i32 {bindc_name = "k"}
41-
!CHECK: %[[K_DECL:.*]]:2 = hlfir.declare %[[K]]
42-
43-
!CHECK: fir.do_concurrent.loop (%[[I_IV:.*]], %[[J_IV:.*]], %[[K_IV:.*]]) =
44-
!CHECK-SAME: (%[[LB1_CVT]], %[[LB2_CVT]], %[[LB3_CVT]]) to
45-
!CHECK-SAME: (%[[UB1_CVT]], %[[UB2_CVT]], %[[UB3_CVT]]) step
46-
!CHECK-SAME: (%{{.*}}, %{{.*}}, %{{.*}}) {
47-
!CHECK: %[[I_IV_CVT:.*]] = fir.convert %[[I_IV]] : (index) -> i32
48-
!CHECK: fir.store %[[I_IV_CVT]] to %[[I_DECL]]#0 : !fir.ref<i32>
49-
!CHECK: %[[J_IV_CVT:.*]] = fir.convert %[[J_IV]] : (index) -> i32
50-
!CHECK: fir.store %[[J_IV_CVT]] to %[[J_DECL]]#0 : !fir.ref<i32>
51-
!CHECK: %[[K_IV_CVT:.*]] = fir.convert %[[K_IV]] : (index) -> i32
52-
!CHECK: fir.store %[[K_IV_CVT]] to %[[K_DECL]]#0 : !fir.ref<i32>
32+
!CHECK: fir.do_loop %{{.*}} = %[[LB1_CVT]] to %[[UB1_CVT]] step %{{.*}} unordered
33+
!CHECK: fir.do_loop %{{.*}} = %[[LB2_CVT]] to %[[UB2_CVT]] step %{{.*}} unordered
34+
!CHECK: fir.do_loop %{{.*}} = %[[LB3_CVT]] to %[[UB3_CVT]] step %{{.*}} unordered
5335

54-
!CHECK: %[[N_VAL:.*]] = fir.load %[[N_DECL]]#0 : !fir.ref<i32>
55-
!CHECK: %[[I_VAL:.*]] = fir.load %[[I_DECL]]#0 : !fir.ref<i32>
56-
!CHECK: %[[I_VAL_CVT:.*]] = fir.convert %[[I_VAL]] : (i32) -> i64
57-
!CHECK: %[[A_ELEM:.*]] = hlfir.designate %[[A_DECL]]#0 (%[[I_VAL_CVT]])
58-
!CHECK: hlfir.assign %[[N_VAL]] to %[[A_ELEM]] : i32, !fir.ref<i32>
5936
do concurrent(i=1:n, j=1:bar(n*m, n/m), k=5:10)
6037
a(i) = n
6138
end do
@@ -68,24 +45,22 @@ subroutine sub2(n)
6845
integer, dimension(n) :: a
6946
!CHECK: %[[LB1:.*]] = arith.constant 1 : i32
7047
!CHECK: %[[LB1_CVT:.*]] = fir.convert %[[LB1]] : (i32) -> index
71-
!CHECK: %[[UB1:.*]] = fir.load %{{.*}}#0 : !fir.ref<i32>
48+
!CHECK: %[[UB1:.*]] = fir.load %5#0 : !fir.ref<i32>
7249
!CHECK: %[[UB1_CVT:.*]] = fir.convert %[[UB1]] : (i32) -> index
73-
!CHECK: fir.do_concurrent
74-
!CHECK: fir.do_concurrent.loop (%{{.*}}) = (%[[LB1_CVT]]) to (%[[UB1_CVT]]) step (%{{.*}})
75-
50+
!CHECK: fir.do_loop %{{.*}} = %[[LB1_CVT]] to %[[UB1_CVT]] step %{{.*}} unordered
7651
!CHECK: %[[LB2:.*]] = arith.constant 1 : i32
7752
!CHECK: %[[LB2_CVT:.*]] = fir.convert %[[LB2]] : (i32) -> index
7853
!CHECK: %[[UB2:.*]] = fir.call @_QPbar(%{{.*}}, %{{.*}}) proc_attrs<pure> fastmath<contract> : (!fir.ref<i32>, !fir.ref<i32>) -> i32
7954
!CHECK: %[[UB2_CVT:.*]] = fir.convert %[[UB2]] : (i32) -> index
80-
!CHECK: fir.do_concurrent
81-
!CHECK: fir.do_concurrent.loop (%{{.*}}) = (%[[LB2_CVT]]) to (%[[UB2_CVT]]) step (%{{.*}})
55+
!CHECK: fir.do_loop %{{.*}} = %[[LB2_CVT]] to %[[UB2_CVT]] step %{{.*}} unordered
8256
do concurrent(i=1:n)
8357
do concurrent(j=1:bar(n*m, n/m))
8458
a(i) = n
8559
end do
8660
end do
8761
end subroutine
8862

63+
8964
!CHECK-LABEL: unstructured
9065
subroutine unstructured(inner_step)
9166
integer(4) :: i, j, inner_step

0 commit comments

Comments
 (0)