Skip to content

Commit 316714c

Browse files
committed
[flang][fir] Convert fir.do_loop with the unordered attribute to scf.parallel.
1 parent b3c5491 commit 316714c

File tree

2 files changed

+58
-15
lines changed

2 files changed

+58
-15
lines changed

flang/lib/Optimizer/Transforms/FIRToSCF.cpp

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ struct DoLoopConversion : public mlir::OpRewritePattern<fir::DoLoopOp> {
3030
mlir::PatternRewriter &rewriter) const override {
3131
mlir::Location loc = doLoopOp.getLoc();
3232
bool hasFinalValue = doLoopOp.getFinalValue().has_value();
33+
bool isUnordered = doLoopOp.getUnordered().has_value();
3334

3435
// Get loop values from the DoLoopOp
3536
mlir::Value low = doLoopOp.getLowerBound();
@@ -53,37 +54,47 @@ struct DoLoopConversion : public mlir::OpRewritePattern<fir::DoLoopOp> {
5354
mlir::arith::DivSIOp::create(rewriter, loc, distance, step);
5455
auto zero = mlir::arith::ConstantIndexOp::create(rewriter, loc, 0);
5556
auto one = mlir::arith::ConstantIndexOp::create(rewriter, loc, 1);
56-
auto scfForOp =
57-
mlir::scf::ForOp::create(rewriter, loc, zero, tripCount, one, iterArgs);
5857

58+
// Create the scf.for or scf.parallel operation
59+
mlir::Operation *scfLoopOp = nullptr;
60+
if (isUnordered) {
61+
scfLoopOp = mlir::scf::ParallelOp::create(rewriter, loc, {zero},
62+
{tripCount}, {one}, iterArgs);
63+
} else {
64+
scfLoopOp = mlir::scf::ForOp::create(rewriter, loc, zero, tripCount, one,
65+
iterArgs);
66+
}
67+
68+
// Move the body of the fir.do_loop to the scf.for or scf.parallel
5969
auto &loopOps = doLoopOp.getBody()->getOperations();
6070
auto resultOp =
6171
mlir::cast<fir::ResultOp>(doLoopOp.getBody()->getTerminator());
6272
auto results = resultOp.getOperands();
63-
mlir::Block *loweredBody = scfForOp.getBody();
73+
auto scfLoopLikeOp = mlir::cast<mlir::LoopLikeOpInterface>(scfLoopOp);
74+
mlir::Block &scfLoopBody = scfLoopLikeOp.getLoopRegions().front()->front();
6475

65-
loweredBody->getOperations().splice(loweredBody->begin(), loopOps,
66-
loopOps.begin(),
67-
std::prev(loopOps.end()));
76+
scfLoopBody.getOperations().splice(scfLoopBody.begin(), loopOps,
77+
loopOps.begin(),
78+
std::prev(loopOps.end()));
6879

69-
rewriter.setInsertionPointToStart(loweredBody);
80+
rewriter.setInsertionPointToStart(&scfLoopBody);
7081
mlir::Value iv = mlir::arith::MulIOp::create(
71-
rewriter, loc, scfForOp.getInductionVar(), step);
82+
rewriter, loc, scfLoopLikeOp.getSingleInductionVar().value(), step);
7283
iv = mlir::arith::AddIOp::create(rewriter, loc, low, iv);
7384

7485
if (!results.empty()) {
75-
rewriter.setInsertionPointToEnd(loweredBody);
86+
rewriter.setInsertionPointToEnd(&scfLoopBody);
7687
mlir::scf::YieldOp::create(rewriter, resultOp->getLoc(), results);
7788
}
7889
doLoopOp.getInductionVar().replaceAllUsesWith(iv);
79-
rewriter.replaceAllUsesWith(doLoopOp.getRegionIterArgs(),
80-
hasFinalValue
81-
? scfForOp.getRegionIterArgs().drop_front()
82-
: scfForOp.getRegionIterArgs());
90+
rewriter.replaceAllUsesWith(
91+
doLoopOp.getRegionIterArgs(),
92+
hasFinalValue ? scfLoopLikeOp.getRegionIterArgs().drop_front()
93+
: scfLoopLikeOp.getRegionIterArgs());
8394

8495
// Copy all the attributes from the old to new op.
85-
scfForOp->setAttrs(doLoopOp->getAttrs());
86-
rewriter.replaceOp(doLoopOp, scfForOp);
96+
scfLoopOp->setAttrs(doLoopOp->getAttrs());
97+
rewriter.replaceOp(doLoopOp, scfLoopOp);
8798
return mlir::success();
8899
}
89100
};

flang/test/Fir/FirToSCF/do-loop.fir

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,38 @@ func.func @loop_with_final_value(%arg0: !fir.ref<!fir.array<100xi32>>, %arg1: !f
146146
return
147147
}
148148

149+
// CHECK-LABEL: func.func @loop_with_unordered_attr(
150+
// CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.array<100xi32>>) {
151+
// CHECK: %[[CONSTANT_0:.*]] = arith.constant 1 : index
152+
// CHECK: %[[CONSTANT_1:.*]] = arith.constant 100 : index
153+
// CHECK: %[[SHAPE_0:.*]] = fir.shape %[[CONSTANT_1]] : (index) -> !fir.shape<1>
154+
// CHECK: %[[CONSTANT_2:.*]] = arith.constant 1 : i32
155+
// CHECK: %[[SUBI_0:.*]] = arith.subi %[[CONSTANT_1]], %[[CONSTANT_0]] : index
156+
// CHECK: %[[ADDI_0:.*]] = arith.addi %[[SUBI_0]], %[[CONSTANT_0]] : index
157+
// CHECK: %[[DIVSI_0:.*]] = arith.divsi %[[ADDI_0]], %[[CONSTANT_0]] : index
158+
// CHECK: %[[CONSTANT_3:.*]] = arith.constant 0 : index
159+
// CHECK: %[[CONSTANT_4:.*]] = arith.constant 1 : index
160+
// CHECK: scf.parallel (%[[VAL_0:.*]]) = (%[[CONSTANT_3]]) to (%[[DIVSI_0]]) step (%[[CONSTANT_4]]) {
161+
// CHECK: %[[MULI_0:.*]] = arith.muli %[[VAL_0]], %[[CONSTANT_0]] : index
162+
// CHECK: %[[ADDI_1:.*]] = arith.addi %[[CONSTANT_0]], %[[MULI_0]] : index
163+
// CHECK: %[[ARRAY_COOR_0:.*]] = fir.array_coor %[[ARG0]](%[[SHAPE_0]]) %[[ADDI_1]] : (!fir.ref<!fir.array<100xi32>>, !fir.shape<1>, index) -> !fir.ref<i32>
164+
// CHECK: fir.store %[[CONSTANT_2]] to %[[ARRAY_COOR_0]] : !fir.ref<i32>
165+
// CHECK: scf.reduce
166+
// CHECK: } {unordered}
167+
// CHECK: return
168+
// CHECK: }
169+
func.func @loop_with_unordered_attr(%arg0: !fir.ref<!fir.array<100xi32>>) {
170+
%c1 = arith.constant 1 : index
171+
%c100 = arith.constant 100 : index
172+
%0 = fir.shape %c100 : (index) -> !fir.shape<1>
173+
%c1_i32 = arith.constant 1 : i32
174+
fir.do_loop %arg1 = %c1 to %c100 step %c1 unordered {
175+
%1 = fir.array_coor %arg0(%0) %arg1 : (!fir.ref<!fir.array<100xi32>>, !fir.shape<1>, index) -> !fir.ref<i32>
176+
fir.store %c1_i32 to %1 : !fir.ref<i32>
177+
}
178+
return
179+
}
180+
149181
// CHECK-LABEL: func.func @loop_with_attribute(
150182
// CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.array<100xi32>>,
151183
// CHECK-SAME: %[[ARG1:.*]]: !fir.ref<i32>) {

0 commit comments

Comments
 (0)