Skip to content

Commit de79344

Browse files
authored
[flang][FIRToSCF] Recompute a typed induction variable in closed form (llvm#217051)
Example: ```fortran do i = 1, n a(i) = a(i) + 1 end do ``` In this code, `fir.do_loop` carries `i` in its own integer type, but `fir-to-scf` normalizes the loop to a canonical `index` loop and passes `i` through `iter_args`. Fix: recompute `i` in closed form from the canonical induction variable, for every step sign. No `iter_arg` and no loop result are added; the closed form does not inherit `nsw`. Loops with a final value keep carrying it, since their result is observable after the loop.
1 parent 7678fad commit de79344

4 files changed

Lines changed: 111 additions & 44 deletions

File tree

flang/lib/Optimizer/Transforms/FIRToSCF.cpp

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ struct DoLoopConversion : public mlir::OpRewritePattern<fir::DoLoopOp> {
5454
mlir::Value step = doLoopOp.getStep();
5555
bool hasTypedIV = !low.getType().isIndex();
5656
mlir::SmallVector<mlir::Value> iterArgs;
57-
if (hasTypedIV || hasFinalValue)
57+
if (hasFinalValue)
5858
iterArgs.push_back(low);
5959
iterArgs.append(doLoopOp.getIterOperands().begin(),
6060
doLoopOp.getIterOperands().end());
@@ -104,18 +104,24 @@ struct DoLoopConversion : public mlir::OpRewritePattern<fir::DoLoopOp> {
104104

105105
rewriter.setInsertionPointToStart(&scfLoopBody);
106106
mlir::Value iv;
107-
if (hasTypedIV) {
107+
if (hasTypedIV && hasFinalValue) {
108108
iv = scfLoopLikeOp.getRegionIterArgs().front();
109109
} else {
110-
iv = mlir::arith::MulIOp::create(
111-
rewriter, loc, scfLoopLikeOp.getSingleInductionVar().value(), step);
112-
iv = mlir::arith::AddIOp::create(rewriter, loc, low, iv);
110+
mlir::Value canonicalIV = scfLoopLikeOp.getSingleInductionVar().value();
111+
if (hasTypedIV)
112+
canonicalIV =
113+
fir::ConvertOp::create(rewriter, loc, low.getType(), canonicalIV);
114+
// Keep the no-wrap flags the stepped increment carried, so a narrow IV
115+
// still folds into an affine recurrence.
116+
iv = mlir::arith::MulIOp::create(rewriter, loc, canonicalIV, step,
117+
iofAttr);
118+
iv = mlir::arith::AddIOp::create(rewriter, loc, low, iv, iofAttr);
113119
}
114120
mlir::Value firIV = doLoopOp.getInductionVar();
115121
firIV.replaceAllUsesWith(iv);
116122

117123
mlir::Value finalValue;
118-
if (hasTypedIV) {
124+
if (hasTypedIV && hasFinalValue) {
119125
finalValue =
120126
mlir::arith::AddIOp::create(rewriter, loc, iv, step, iofAttr);
121127
} else if (hasFinalValue) {
@@ -134,23 +140,21 @@ struct DoLoopConversion : public mlir::OpRewritePattern<fir::DoLoopOp> {
134140
mlir::arith::AddIOp::create(rewriter, loc, iv, step, iofAttr);
135141
}
136142

137-
if (hasTypedIV || hasFinalValue || !results.empty()) {
143+
if (hasFinalValue || !results.empty()) {
138144
rewriter.setInsertionPointToEnd(&scfLoopBody);
139145
llvm::SmallVector<mlir::Value> yieldOperands;
140-
if (hasTypedIV || hasFinalValue) {
146+
if (hasFinalValue) {
141147
yieldOperands.push_back(finalValue);
142-
}
143-
if (hasFinalValue)
144148
llvm::append_range(yieldOperands, results.drop_front());
145-
else
149+
} else {
146150
llvm::append_range(yieldOperands, results);
151+
}
147152
mlir::scf::YieldOp::create(rewriter, resultOp->getLoc(), yieldOperands);
148153
}
149154
rewriter.replaceAllUsesWith(
150155
doLoopOp.getRegionIterArgs(),
151-
hasTypedIV || hasFinalValue
152-
? scfLoopLikeOp.getRegionIterArgs().drop_front()
153-
: scfLoopLikeOp.getRegionIterArgs());
156+
hasFinalValue ? scfLoopLikeOp.getRegionIterArgs().drop_front()
157+
: scfLoopLikeOp.getRegionIterArgs());
154158

155159
// Copy loop annotations from the fir.do_loop to scf loop op.
156160
if (auto ann = doLoopOp.getLoopAnnotation())
@@ -161,10 +165,7 @@ struct DoLoopConversion : public mlir::OpRewritePattern<fir::DoLoopOp> {
161165
if (auto parDims = doLoopOp->getAttr(mlir::acc::GPUParallelDimsAttr::name))
162166
scfLoopOp->setAttr(mlir::acc::GPUParallelDimsAttr::name, parDims);
163167

164-
mlir::ValueRange scfResults = scfLoopOp->getResults();
165-
if (hasTypedIV && !hasFinalValue)
166-
scfResults = scfResults.drop_front();
167-
rewriter.replaceOp(doLoopOp, scfResults);
168+
rewriter.replaceOp(doLoopOp, scfLoopOp->getResults());
168169
return mlir::success();
169170
}
170171

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ func.func @implied_do_in_acc_serial(%arg0: !fir.ref<!fir.array<4xi32>> {fir.bind
7272
// CHECK: [[ADD:%[0-9]+]] = arith.addi [[SUB]], %c1 : index
7373
// CHECK: [[DIV:%[0-9]+]] = arith.divsi [[ADD]], %c1 : index
7474
// CHECK: [[FOR:%[0-9]+]] = scf.for %{{.*}} = %{{.*}} to [[DIV]] step %{{.*}} iter_args(%{{.*}} = %c1) -> (index) {
75-
// CHECK: [[IV:%[0-9]+]] = arith.addi %c1, {{.*}} : index
75+
// CHECK: [[IV:%[0-9]+]] = arith.addi %c1, {{.*}} overflow<nsw> : index
7676
// CHECK: fir.convert [[IV]] : (index) -> i32
7777
// CHECK: scf.yield
7878

@@ -135,8 +135,8 @@ func.func @mv_(%arg0: !fir.ref<!fir.array<3xi32>> {fir.bindc_name = "a", llvm.no
135135
// CHECK: %[[C0:.*]] = arith.constant 0 : index
136136
// CHECK: %[[C1:.*]] = arith.constant 1 : index
137137
// CHECK: scf.for %{{.*}} = %[[C0]] to %[[VAL_2]] step %[[C1]] iter_args(%{{.*}} = %[[ARG0]]) -> (index) {
138-
// CHECK: %[[MUL:.*]] = arith.muli %{{.*}}, %[[ARG2]] : index
139-
// CHECK: %[[ADD0:.*]] = arith.addi %[[ARG0]], %[[MUL]] : index
138+
// CHECK: %[[MUL:.*]] = arith.muli %{{.*}}, %[[ARG2]] overflow<nsw> : index
139+
// CHECK: %[[ADD0:.*]] = arith.addi %[[ARG0]], %[[MUL]] overflow<nsw> : index
140140
// CHECK: %[[ADD1:.*]] = arith.addi %[[ADD0]], %[[ARG2]] overflow<nsw> : index
141141
// CHECK: scf.yield %[[ADD1]] : index
142142
// CHECK: }

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

Lines changed: 85 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313
// CHECK: %[[VAL_7:.*]] = arith.constant 0 : index
1414
// CHECK: %[[VAL_8:.*]] = arith.constant 1 : index
1515
// CHECK: scf.for %[[VAL_9:.*]] = %[[VAL_7]] to %[[VAL_6]] step %[[VAL_8]] {
16-
// CHECK: %[[VAL_10:.*]] = arith.muli %[[VAL_9]], %[[VAL_0]] : index
17-
// CHECK: %[[VAL_11:.*]] = arith.addi %[[VAL_0]], %[[VAL_10]] : index
16+
// CHECK: %[[VAL_10:.*]] = arith.muli %[[VAL_9]], %[[VAL_0]] overflow<nsw> : index
17+
// CHECK: %[[VAL_11:.*]] = arith.addi %[[VAL_0]], %[[VAL_10]] overflow<nsw> : index
1818
// CHECK: %[[VAL_12:.*]] = fir.array_coor %[[ARG0]](%[[VAL_2]]) %[[VAL_11]] : (!fir.ref<!fir.array<100xi32>>, !fir.shape<1>, index) -> !fir.ref<i32>
1919
// CHECK: fir.store %[[VAL_3]] to %[[VAL_12]] : !fir.ref<i32>
2020
// CHECK: }
@@ -34,6 +34,8 @@ func.func @simple_loop(%arg0: !fir.ref<!fir.array<100xi32>>) {
3434

3535
// -----
3636

37+
// A typed induction variable is recomputed in closed form from the canonical
38+
// induction variable, so it adds neither an iter_arg nor a loop result.
3739
// CHECK-LABEL: func.func @typed_loop(
3840
// CHECK-SAME: %[[LB:.*]]: i32, %[[UB:.*]]: i32, %[[STEP:.*]]: i32,
3941
// CHECK-SAME: %[[ADDR:.*]]: !fir.ref<i32>) {
@@ -45,11 +47,13 @@ func.func @simple_loop(%arg0: !fir.ref<!fir.array<100xi32>>) {
4547
// CHECK: %[[TRIP:.*]] = arith.divsi %[[DISTANCE]], %[[STEP_IDX]] : index
4648
// CHECK: %[[C0:.*]] = arith.constant 0 : index
4749
// CHECK: %[[C1:.*]] = arith.constant 1 : index
48-
// CHECK: scf.for %{{.*}} = %[[C0]] to %[[TRIP]] step %[[C1]] iter_args(%[[IV:.*]] = %[[LB]]) -> (i32) {
49-
// CHECK: %[[NEXT:.*]] = arith.addi %[[IV]], %[[STEP]] overflow<nsw> : i32
50+
// CHECK: scf.for %[[I:.*]] = %[[C0]] to %[[TRIP]] step %[[C1]] {
51+
// CHECK: %[[I_TYPED:.*]] = fir.convert %[[I]] : (index) -> i32
52+
// CHECK: %[[SCALED:.*]] = arith.muli %[[I_TYPED]], %[[STEP]] overflow<nsw> : i32
53+
// CHECK: %[[IV:.*]] = arith.addi %[[LB]], %[[SCALED]] overflow<nsw> : i32
5054
// CHECK: fir.store %[[IV]] to %[[ADDR]] : !fir.ref<i32>
51-
// CHECK: scf.yield %[[NEXT]] : i32
5255
// CHECK: }
56+
// CHECK-NOT: iter_args
5357
func.func @typed_loop(%lb: i32, %ub: i32, %step: i32,
5458
%addr: !fir.ref<i32>) {
5559
fir.do_loop %iv = %lb to %ub step %step : i32 {
@@ -60,6 +64,68 @@ func.func @typed_loop(%lb: i32, %ub: i32, %step: i32,
6064

6165
// -----
6266

67+
// Only the loop's own iter_args survive; the typed IV does not add one.
68+
// CHECK-LABEL: func.func @typed_loop_iter_args(
69+
// CHECK: %[[C0:.*]] = arith.constant 0 : i32
70+
// CHECK: %[[C1:.*]] = arith.constant 1 : i32
71+
// CHECK: %[[TRIP:.*]] = arith.divsi
72+
// CHECK: %[[C0_IDX:.*]] = arith.constant 0 : index
73+
// CHECK: %[[C1_IDX:.*]] = arith.constant 1 : index
74+
// CHECK: %[[RES:.*]] = scf.for %[[I:.*]] = %[[C0_IDX]] to %[[TRIP]] step %[[C1_IDX]] iter_args(%[[ACC:.*]] = %[[C0]]) -> (i32) {
75+
// CHECK: %[[I_TYPED:.*]] = fir.convert %[[I]] : (index) -> i32
76+
// CHECK: %[[SCALED:.*]] = arith.muli %[[I_TYPED]], %[[C1]] overflow<nsw> : i32
77+
// CHECK: %[[IV:.*]] = arith.addi %[[C1]], %[[SCALED]] overflow<nsw> : i32
78+
// CHECK: %[[SUM:.*]] = arith.addi %[[ACC]], %[[IV]] : i32
79+
// CHECK: scf.yield %[[SUM]] : i32
80+
// CHECK: }
81+
// CHECK: return %[[RES]] : i32
82+
func.func @typed_loop_iter_args(%addr: !fir.ref<i32>) -> i32 {
83+
%c0_i32 = arith.constant 0 : i32
84+
%c1_i32 = arith.constant 1 : i32
85+
%c10_i32 = arith.constant 10 : i32
86+
%r = fir.do_loop %iv = %c1_i32 to %c10_i32 step %c1_i32 iter_args(%acc = %c0_i32) -> (i32) : i32 {
87+
%v = arith.addi %acc, %iv : i32
88+
fir.result %v : i32
89+
}
90+
return %r : i32
91+
}
92+
93+
// -----
94+
95+
// A negative step is handled by the same closed form, so it does not need an
96+
// iter_arg either.
97+
// CHECK-LABEL: func.func @typed_loop_negative_step(
98+
// CHECK-SAME: %[[ADDR:.*]]: !fir.ref<i32>) {
99+
// CHECK: %[[C1:.*]] = arith.constant 1 : i32
100+
// CHECK: %[[C10:.*]] = arith.constant 10 : i32
101+
// CHECK: %[[CM1:.*]] = arith.constant -1 : i32
102+
// CHECK: %[[LB_IDX:.*]] = fir.convert %[[C10]] : (i32) -> index
103+
// CHECK: %[[UB_IDX:.*]] = fir.convert %[[C1]] : (i32) -> index
104+
// CHECK: %[[STEP_IDX:.*]] = fir.convert %[[CM1]] : (i32) -> index
105+
// CHECK: %[[DIFF:.*]] = arith.subi %[[UB_IDX]], %[[LB_IDX]] : index
106+
// CHECK: %[[DISTANCE:.*]] = arith.addi %[[DIFF]], %[[STEP_IDX]] : index
107+
// CHECK: %[[TRIP:.*]] = arith.divsi %[[DISTANCE]], %[[STEP_IDX]] : index
108+
// CHECK: %[[C0:.*]] = arith.constant 0 : index
109+
// CHECK: %[[C1_IDX:.*]] = arith.constant 1 : index
110+
// CHECK: scf.for %[[I:.*]] = %[[C0]] to %[[TRIP]] step %[[C1_IDX]] {
111+
// CHECK: %[[I_TYPED:.*]] = fir.convert %[[I]] : (index) -> i32
112+
// CHECK: %[[SCALED:.*]] = arith.muli %[[I_TYPED]], %[[CM1]] overflow<nsw> : i32
113+
// CHECK: %[[IV:.*]] = arith.addi %[[C10]], %[[SCALED]] overflow<nsw> : i32
114+
// CHECK: fir.store %[[IV]] to %[[ADDR]] : !fir.ref<i32>
115+
// CHECK: }
116+
// CHECK-NOT: iter_args
117+
func.func @typed_loop_negative_step(%addr: !fir.ref<i32>) {
118+
%c1_i32 = arith.constant 1 : i32
119+
%c10_i32 = arith.constant 10 : i32
120+
%cm1_i32 = arith.constant -1 : i32
121+
fir.do_loop %iv = %c10_i32 to %c1_i32 step %cm1_i32 : i32 {
122+
fir.store %iv to %addr : !fir.ref<i32>
123+
}
124+
return
125+
}
126+
127+
// -----
128+
63129
// CHECK-LABEL: func.func @loop_with_negtive_step(
64130
// CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.array<100xi32>>) {
65131
// CHECK: %[[VAL_0:.*]] = arith.constant 100 : index
@@ -73,8 +139,8 @@ func.func @typed_loop(%lb: i32, %ub: i32, %step: i32,
73139
// CHECK: %[[VAL_8:.*]] = arith.constant 0 : index
74140
// CHECK: %[[VAL_9:.*]] = arith.constant 1 : index
75141
// CHECK: scf.for %[[VAL_10:.*]] = %[[VAL_8]] to %[[VAL_7]] step %[[VAL_9]] {
76-
// CHECK: %[[VAL_11:.*]] = arith.muli %[[VAL_10]], %[[VAL_2]] : index
77-
// CHECK: %[[VAL_12:.*]] = arith.addi %[[VAL_0]], %[[VAL_11]] : index
142+
// CHECK: %[[VAL_11:.*]] = arith.muli %[[VAL_10]], %[[VAL_2]] overflow<nsw> : index
143+
// CHECK: %[[VAL_12:.*]] = arith.addi %[[VAL_0]], %[[VAL_11]] overflow<nsw> : index
78144
// CHECK: %[[VAL_13:.*]] = fir.array_coor %[[ARG0]](%[[VAL_3]]) %[[VAL_12]] : (!fir.ref<!fir.array<100xi32>>, !fir.shape<1>, index) -> !fir.ref<i32>
79145
// CHECK: fir.store %[[VAL_4]] to %[[VAL_13]] : !fir.ref<i32>
80146
// CHECK: }
@@ -108,8 +174,8 @@ func.func @loop_with_negtive_step(%arg0: !fir.ref<!fir.array<100xi32>>) {
108174
// CHECK: %[[VAL_7:.*]] = arith.constant 0 : index
109175
// CHECK: %[[VAL_8:.*]] = arith.constant 1 : index
110176
// CHECK: %[[VAL_9:.*]] = scf.for %[[VAL_10:.*]] = %[[VAL_7]] to %[[VAL_6]] step %[[VAL_8]] iter_args(%[[VAL_11:.*]] = %[[VAL_1]]) -> (i32) {
111-
// CHECK: %[[VAL_12:.*]] = arith.muli %[[VAL_10]], %[[VAL_0]] : index
112-
// CHECK: %[[VAL_13:.*]] = arith.addi %[[VAL_0]], %[[VAL_12]] : index
177+
// CHECK: %[[VAL_12:.*]] = arith.muli %[[VAL_10]], %[[VAL_0]] overflow<nsw> : index
178+
// CHECK: %[[VAL_13:.*]] = arith.addi %[[VAL_0]], %[[VAL_12]] overflow<nsw> : index
113179
// CHECK: %[[VAL_14:.*]] = fir.array_coor %[[ARG0]](%[[VAL_3]]) %[[VAL_13]] : (!fir.ref<!fir.array<100xi32>>, !fir.shape<1>, index) -> !fir.ref<i32>
114180
// CHECK: %[[VAL_15:.*]] = fir.load %[[VAL_14]] : !fir.ref<i32>
115181
// CHECK: %[[VAL_16:.*]] = arith.addi %[[VAL_11]], %[[VAL_15]] : i32
@@ -149,8 +215,8 @@ func.func @loop_with_results(%arg0: !fir.ref<!fir.array<100xi32>>, %arg1: !fir.r
149215
// CHECK: %[[VAL_8:.*]] = arith.constant 0 : index
150216
// CHECK: %[[VAL_9:.*]] = arith.constant 1 : index
151217
// CHECK: %[[VAL_10:.*]]:2 = scf.for %[[VAL_11:.*]] = %[[VAL_8]] to %[[VAL_7]] step %[[VAL_9]] iter_args(%[[VAL_12:.*]] = %[[VAL_0]], %[[VAL_13:.*]] = %[[VAL_1]]) -> (index, i32) {
152-
// CHECK: %[[VAL_14:.*]] = arith.muli %[[VAL_11]], %[[VAL_0]] : index
153-
// CHECK: %[[VAL_15:.*]] = arith.addi %[[VAL_0]], %[[VAL_14]] : index
218+
// CHECK: %[[VAL_14:.*]] = arith.muli %[[VAL_11]], %[[VAL_0]] overflow<nsw> : index
219+
// CHECK: %[[VAL_15:.*]] = arith.addi %[[VAL_0]], %[[VAL_14]] overflow<nsw> : index
154220
// CHECK: %[[VAL_16:.*]] = fir.array_coor %[[ARG0]](%[[VAL_4]]) %[[VAL_15]] : (!fir.ref<!fir.array<100xi32>>, !fir.shape<1>, index) -> !fir.ref<i32>
155221
// CHECK: %[[VAL_17:.*]] = fir.load %[[VAL_16]] : !fir.ref<i32>
156222
// CHECK: %[[VAL_18:.*]] = arith.addi %[[VAL_15]], %[[VAL_0]] overflow<nsw> : index
@@ -244,8 +310,8 @@ func.func @loop_with_final_value_and_result() {
244310
// CHECK: %[[CONSTANT_4:.*]] = arith.constant 1 : index
245311
// PARALLEL: scf.parallel (%[[VAL_0:.*]]) = (%[[CONSTANT_3]]) to (%[[DIVSI_0]]) step (%[[CONSTANT_4]]) {
246312
// NO-PARALLEL: scf.for %[[VAL_0:.*]] = %[[CONSTANT_3]] to %[[DIVSI_0]] step %[[CONSTANT_4]] {
247-
// CHECK: %[[MULI_0:.*]] = arith.muli %[[VAL_0]], %[[CONSTANT_0]] : index
248-
// CHECK: %[[ADDI_1:.*]] = arith.addi %[[CONSTANT_0]], %[[MULI_0]] : index
313+
// CHECK: %[[MULI_0:.*]] = arith.muli %[[VAL_0]], %[[CONSTANT_0]] overflow<nsw> : index
314+
// CHECK: %[[ADDI_1:.*]] = arith.addi %[[CONSTANT_0]], %[[MULI_0]] overflow<nsw> : index
249315
// CHECK: %[[ARRAY_COOR_0:.*]] = fir.array_coor %[[ARG0]](%[[SHAPE_0]]) %[[ADDI_1]] : (!fir.ref<!fir.array<100xi32>>, !fir.shape<1>, index) -> !fir.ref<i32>
250316
// CHECK: fir.store %[[CONSTANT_2]] to %[[ARRAY_COOR_0]] : !fir.ref<i32>
251317
// PARALLEL: scf.reduce
@@ -282,8 +348,8 @@ func.func @loop_with_unordered_attr(%arg0: !fir.ref<!fir.array<100xi32>>) {
282348
// CHECK: %[[VAL_8:.*]] = arith.constant 0 : index
283349
// CHECK: %[[VAL_9:.*]] = arith.constant 1 : index
284350
// CHECK: scf.for %[[VAL_10:.*]] = %[[VAL_8]] to %[[VAL_7]] step %[[VAL_9]] {
285-
// CHECK: %[[VAL_11:.*]] = arith.muli %[[VAL_10]], %[[VAL_0]] : index
286-
// CHECK: %[[VAL_12:.*]] = arith.addi %[[VAL_0]], %[[VAL_11]] : index
351+
// CHECK: %[[VAL_11:.*]] = arith.muli %[[VAL_10]], %[[VAL_0]] overflow<nsw> : index
352+
// CHECK: %[[VAL_12:.*]] = arith.addi %[[VAL_0]], %[[VAL_11]] overflow<nsw> : index
287353
// CHECK: %[[VAL_13:.*]] = fir.array_coor %[[ARG0]](%[[VAL_4]]) %[[VAL_12]] : (!fir.ref<!fir.array<100xi32>>, !fir.shape<1>, index) -> !fir.ref<i32>
288354
// CHECK: %[[VAL_14:.*]] = fir.load %[[VAL_13]] : !fir.ref<i32>
289355
// CHECK: %[[VAL_15:.*]] = fir.load %[[VAL_3]] : !fir.ref<i32>
@@ -326,16 +392,16 @@ func.func @loop_with_attribute(%arg0: !fir.ref<!fir.array<100xi32>>, %arg1: !fir
326392
// CHECK: %[[VAL_7:.*]] = arith.constant 0 : index
327393
// CHECK: %[[VAL_8:.*]] = arith.constant 1 : index
328394
// CHECK: scf.for %[[VAL_9:.*]] = %[[VAL_7]] to %[[VAL_6]] step %[[VAL_8]] {
329-
// CHECK: %[[VAL_10:.*]] = arith.muli %[[VAL_9]], %[[VAL_0]] : index
330-
// CHECK: %[[VAL_11:.*]] = arith.addi %[[VAL_0]], %[[VAL_10]] : index
395+
// CHECK: %[[VAL_10:.*]] = arith.muli %[[VAL_9]], %[[VAL_0]] overflow<nsw> : index
396+
// CHECK: %[[VAL_11:.*]] = arith.addi %[[VAL_0]], %[[VAL_10]] overflow<nsw> : index
331397
// CHECK: %[[VAL_12:.*]] = arith.subi %[[VAL_2]], %[[VAL_0]] : index
332398
// CHECK: %[[VAL_13:.*]] = arith.addi %[[VAL_12]], %[[VAL_0]] : index
333399
// CHECK: %[[VAL_14:.*]] = arith.divsi %[[VAL_13]], %[[VAL_0]] : index
334400
// CHECK: %[[VAL_15:.*]] = arith.constant 0 : index
335401
// CHECK: %[[VAL_16:.*]] = arith.constant 1 : index
336402
// CHECK: scf.for %[[VAL_17:.*]] = %[[VAL_15]] to %[[VAL_14]] step %[[VAL_16]] {
337-
// CHECK: %[[VAL_18:.*]] = arith.muli %[[VAL_17]], %[[VAL_0]] : index
338-
// CHECK: %[[VAL_19:.*]] = arith.addi %[[VAL_0]], %[[VAL_18]] : index
403+
// CHECK: %[[VAL_18:.*]] = arith.muli %[[VAL_17]], %[[VAL_0]] overflow<nsw> : index
404+
// CHECK: %[[VAL_19:.*]] = arith.addi %[[VAL_0]], %[[VAL_18]] overflow<nsw> : index
339405
// CHECK: %[[VAL_20:.*]] = fir.array_coor %[[ARG0]](%[[VAL_3]]) %[[VAL_19]], %[[VAL_11]] : (!fir.ref<!fir.array<100x100xi32>>, !fir.shape<2>, index, index) -> !fir.ref<i32>
340406
// CHECK: fir.store %[[VAL_1]] to %[[VAL_20]] : !fir.ref<i32>
341407
// CHECK: }

flang/test/Fir/FirToSCF/normalize.fir

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@
2020
// CHECK-NEXT: [[ADD:%[0-9]+]] = arith.addi [[SUB]], [[STEP]] : index
2121
// CHECK-NEXT: [[DIV:%[0-9]+]] = arith.divsi [[ADD]], [[STEP]] : index
2222
// CHECK: scf.for %arg4 = %c0{{.*}} to [[DIV]] step %c1{{.*}}
23-
// CHECK-NEXT: [[IVMUL:%[0-9]+]] = arith.muli %arg4, [[STEP]] : index
24-
// CHECK-NEXT: [[IVADD:%[0-9]+]] = arith.addi [[LB]], [[IVMUL]] : index
23+
// CHECK-NEXT: [[IVMUL:%[0-9]+]] = arith.muli %arg4, [[STEP]] overflow<nsw> : index
24+
// CHECK-NEXT: [[IVADD:%[0-9]+]] = arith.addi [[LB]], [[IVMUL]] overflow<nsw> : index
2525
// CHECK-NEXT: memref.store [[IVADD]], %arg3[]
2626

2727
func.func @unknown_step_(%arg0: i64, %arg1: i64, %arg2: i64, %arg3: memref<index>) {
@@ -52,8 +52,8 @@ func.func @unknown_step_(%arg0: i64, %arg1: i64, %arg2: i64, %arg3: memref<index
5252
// CHECK-NEXT: [[ADD:%[0-9]+]] = arith.addi [[SUB]], [[STEP]] : index
5353
// CHECK-NEXT: [[DIV:%[0-9]+]] = arith.divsi [[ADD]], [[STEP]] : index
5454
// CHECK: scf.for %arg1 = %c0{{.*}} to [[DIV]] step %c1{{.*}}
55-
// CHECK-NEXT: [[IVMUL:%[0-9]+]] = arith.muli %arg1, [[STEP]] : index
56-
// CHECK-NEXT: [[IVADD:%[0-9]+]] = arith.addi [[LB]], [[IVMUL]] : index
55+
// CHECK-NEXT: [[IVMUL:%[0-9]+]] = arith.muli %arg1, [[STEP]] overflow<nsw> : index
56+
// CHECK-NEXT: [[IVADD:%[0-9]+]] = arith.addi [[LB]], [[IVMUL]] overflow<nsw> : index
5757
// CHECK-NEXT: memref.store [[IVADD]], %arg0[]
5858

5959
func.func @negative_step_(%arg0: memref<index>) {

0 commit comments

Comments
 (0)