@@ -1211,80 +1211,123 @@ class FirConverter : public Fortran::lower::AbstractConverter {
1211
1211
// / Process a concurrent header for a FORALL. (Concurrent headers for DO
1212
1212
// / CONCURRENT loops are lowered elsewhere.)
1213
1213
void genFIR (const Fortran::parser::ConcurrentHeader &header) {
1214
- // Create our iteration space from the header spec.
1215
- localSymbols.pushScope ();
1216
- auto idxTy = builder->getIndexType ();
1217
- auto loc = toLocation ();
1218
- llvm::SmallVector<fir::DoLoopOp> loops;
1219
- for (auto &ctrl :
1220
- std::get<std::list<Fortran::parser::ConcurrentControl>>(header.t )) {
1221
- const auto *ctrlVar = std::get<Fortran::parser::Name>(ctrl.t ).symbol ;
1222
- const auto *lo = Fortran::semantics::GetExpr (std::get<1 >(ctrl.t ));
1223
- const auto *hi = Fortran::semantics::GetExpr (std::get<2 >(ctrl.t ));
1224
- auto &optStep =
1225
- std::get<std::optional<Fortran::parser::ScalarIntExpr>>(ctrl.t );
1226
- auto lb = builder->createConvert (
1227
- loc, idxTy,
1228
- fir::getBase (genExprValue (*lo, explicitIterSpace.stmtContext ())));
1229
- auto ub = builder->createConvert (
1230
- loc, idxTy,
1231
- fir::getBase (genExprValue (*hi, explicitIterSpace.stmtContext ())));
1232
- auto by = optStep.has_value ()
1233
- ? builder->createConvert (
1234
- loc, idxTy,
1235
- fir::getBase (genExprValue (
1236
- *Fortran::semantics::GetExpr (*optStep),
1237
- explicitIterSpace.stmtContext ())))
1238
- : builder->createIntegerConstant (loc, idxTy, 1 );
1239
- auto lp = builder->create <fir::DoLoopOp>(
1240
- loc, lb, ub, by, /* unordered=*/ true ,
1241
- /* finalCount=*/ false , explicitIterSpace.getInnerArgs ());
1242
- if (!loops.empty ())
1243
- builder->create <fir::ResultOp>(loc, lp.getResults ());
1244
- explicitIterSpace.setInnerArgs (lp.getRegionIterArgs ());
1245
- builder->setInsertionPointToStart (lp.getBody ());
1246
- forceControlVariableBinding (ctrlVar, lp.getInductionVar ());
1247
- loops.push_back (lp);
1248
- }
1249
- explicitIterSpace.setOuterLoop (loops[0 ]);
1250
- if (const auto &mask =
1251
- std::get<std::optional<Fortran::parser::ScalarLogicalExpr>>(
1252
- header.t );
1253
- mask.has_value ()) {
1254
- auto i1Ty = builder->getI1Type ();
1255
- auto maskExv = genExprValue (*Fortran::semantics::GetExpr (mask.value ()),
1256
- explicitIterSpace.stmtContext ());
1257
- auto cond = builder->createConvert (loc, i1Ty, fir::getBase (maskExv));
1258
- auto ifOp = builder->create <fir::IfOp>(
1259
- loc, explicitIterSpace.innerArgTypes (), cond,
1260
- /* withElseRegion=*/ true );
1261
- builder->create <fir::ResultOp>(loc, ifOp.getResults ());
1262
- builder->setInsertionPointToStart (&ifOp.elseRegion ().front ());
1263
- builder->create <fir::ResultOp>(loc, explicitIterSpace.getInnerArgs ());
1264
- builder->setInsertionPointToStart (&ifOp.thenRegion ().front ());
1214
+ llvm::SmallVector<mlir::Value> lows;
1215
+ llvm::SmallVector<mlir::Value> highs;
1216
+ llvm::SmallVector<mlir::Value> steps;
1217
+ if (explicitIterSpace.isOutermostForall ()) {
1218
+ // For the outermost forall, we evaluate the bounds expressions once.
1219
+ // Contrastingly, if this forall is nested, the bounds expressions are
1220
+ // assumed to be pure, possibly dependent on outer concurrent control
1221
+ // variables, possibly variant with respect to arguments, and will be
1222
+ // re-evaluated.
1223
+ auto loc = toLocation ();
1224
+ auto idxTy = builder->getIndexType ();
1225
+ auto &stmtCtx = explicitIterSpace.stmtContext ();
1226
+ auto lowerExpr = [&](auto &e) {
1227
+ return fir::getBase (genExprValue (e, stmtCtx));
1228
+ };
1229
+ for (auto &ctrl :
1230
+ std::get<std::list<Fortran::parser::ConcurrentControl>>(header.t )) {
1231
+ const auto *lo = Fortran::semantics::GetExpr (std::get<1 >(ctrl.t ));
1232
+ const auto *hi = Fortran::semantics::GetExpr (std::get<2 >(ctrl.t ));
1233
+ auto &optStep =
1234
+ std::get<std::optional<Fortran::parser::ScalarIntExpr>>(ctrl.t );
1235
+ lows.push_back (builder->createConvert (loc, idxTy, lowerExpr (*lo)));
1236
+ highs.push_back (builder->createConvert (loc, idxTy, lowerExpr (*hi)));
1237
+ steps.push_back (
1238
+ optStep.has_value ()
1239
+ ? builder->createConvert (
1240
+ loc, idxTy,
1241
+ lowerExpr (*Fortran::semantics::GetExpr (*optStep)))
1242
+ : builder->createIntegerConstant (loc, idxTy, 1 ));
1243
+ }
1265
1244
}
1245
+ auto lambda = [&, lows, highs, steps]() {
1246
+ // Create our iteration space from the header spec.
1247
+ auto loc = toLocation ();
1248
+ auto idxTy = builder->getIndexType ();
1249
+ llvm::SmallVector<fir::DoLoopOp> loops;
1250
+ auto &stmtCtx = explicitIterSpace.stmtContext ();
1251
+ auto lowerExpr = [&](auto &e) {
1252
+ return fir::getBase (genExprValue (e, stmtCtx));
1253
+ };
1254
+ const auto outermost = !lows.empty ();
1255
+ std::size_t headerIndex = 0 ;
1256
+ for (auto &ctrl :
1257
+ std::get<std::list<Fortran::parser::ConcurrentControl>>(header.t )) {
1258
+ const auto *ctrlVar = std::get<Fortran::parser::Name>(ctrl.t ).symbol ;
1259
+ mlir::Value lb;
1260
+ mlir::Value ub;
1261
+ mlir::Value by;
1262
+ if (outermost) {
1263
+ assert (headerIndex < lows.size ());
1264
+ lb = lows[headerIndex];
1265
+ ub = highs[headerIndex];
1266
+ by = steps[headerIndex++];
1267
+ } else {
1268
+ const auto *lo = Fortran::semantics::GetExpr (std::get<1 >(ctrl.t ));
1269
+ const auto *hi = Fortran::semantics::GetExpr (std::get<2 >(ctrl.t ));
1270
+ auto &optStep =
1271
+ std::get<std::optional<Fortran::parser::ScalarIntExpr>>(ctrl.t );
1272
+ lb = builder->createConvert (loc, idxTy, lowerExpr (*lo));
1273
+ ub = builder->createConvert (loc, idxTy, lowerExpr (*hi));
1274
+ by = optStep.has_value ()
1275
+ ? builder->createConvert (
1276
+ loc, idxTy,
1277
+ lowerExpr (*Fortran::semantics::GetExpr (*optStep)))
1278
+ : builder->createIntegerConstant (loc, idxTy, 1 );
1279
+ }
1280
+ auto lp = builder->create <fir::DoLoopOp>(
1281
+ loc, lb, ub, by, /* unordered=*/ true ,
1282
+ /* finalCount=*/ false , explicitIterSpace.getInnerArgs ());
1283
+ if (!loops.empty () || !outermost)
1284
+ builder->create <fir::ResultOp>(loc, lp.getResults ());
1285
+ explicitIterSpace.setInnerArgs (lp.getRegionIterArgs ());
1286
+ builder->setInsertionPointToStart (lp.getBody ());
1287
+ forceControlVariableBinding (ctrlVar, lp.getInductionVar ());
1288
+ loops.push_back (lp);
1289
+ }
1290
+ explicitIterSpace.setOuterLoop (loops[0 ]);
1291
+ if (const auto &mask =
1292
+ std::get<std::optional<Fortran::parser::ScalarLogicalExpr>>(
1293
+ header.t );
1294
+ mask.has_value ()) {
1295
+ auto i1Ty = builder->getI1Type ();
1296
+ auto maskExv =
1297
+ genExprValue (*Fortran::semantics::GetExpr (mask.value ()), stmtCtx);
1298
+ auto cond = builder->createConvert (loc, i1Ty, fir::getBase (maskExv));
1299
+ auto ifOp = builder->create <fir::IfOp>(
1300
+ loc, explicitIterSpace.innerArgTypes (), cond,
1301
+ /* withElseRegion=*/ true );
1302
+ builder->create <fir::ResultOp>(loc, ifOp.getResults ());
1303
+ builder->setInsertionPointToStart (&ifOp.elseRegion ().front ());
1304
+ builder->create <fir::ResultOp>(loc, explicitIterSpace.getInnerArgs ());
1305
+ builder->setInsertionPointToStart (&ifOp.thenRegion ().front ());
1306
+ }
1307
+ };
1308
+ // Push the lambda to gen the loop nest context.
1309
+ explicitIterSpace.pushLoopNest (lambda);
1266
1310
}
1267
1311
1268
1312
void genFIR (const Fortran::parser::ForallAssignmentStmt &stmt) {
1269
1313
std::visit ([&](const auto &x) { genFIR (x); }, stmt.u );
1270
1314
}
1271
1315
1272
1316
void genFIR (const Fortran::parser::EndForallStmt &) {
1273
- explicitIterSpace.finalize ();
1274
1317
cleanupExplicitSpace ();
1275
1318
}
1276
1319
1277
1320
template <typename A>
1278
1321
void prepareExplicitSpace (const A &forall) {
1279
- analyzeExplicitSpace (forall);
1322
+ if (!explicitIterSpace.isActive ())
1323
+ analyzeExplicitSpace (forall);
1324
+ localSymbols.pushScope ();
1280
1325
explicitIterSpace.enter ();
1281
- Fortran::lower::createArrayLoads (*this , explicitIterSpace, localSymbols);
1282
1326
}
1283
1327
1284
1328
// / Cleanup all the FORALL context information when we exit.
1285
1329
void cleanupExplicitSpace () {
1286
- Fortran::lower::createArrayMergeStores (*this , explicitIterSpace);
1287
- explicitIterSpace.conditionalCleanup ();
1330
+ explicitIterSpace.leave ();
1288
1331
localSymbols.popScope ();
1289
1332
}
1290
1333
@@ -1824,6 +1867,10 @@ class FirConverter : public Fortran::lower::AbstractConverter {
1824
1867
void genAssignment (const Fortran::evaluate::Assignment &assign) {
1825
1868
Fortran::lower::StatementContext stmtCtx;
1826
1869
auto loc = toLocation ();
1870
+ if (explicitIterationSpace ()) {
1871
+ Fortran::lower::createArrayLoads (*this , explicitIterSpace, localSymbols);
1872
+ explicitIterSpace.genLoopNest ();
1873
+ }
1827
1874
std::visit (
1828
1875
Fortran::common::visitors{
1829
1876
// [1] Plain old assignment.
@@ -1920,7 +1967,10 @@ class FirConverter : public Fortran::lower::AbstractConverter {
1920
1967
if (implicitIterationSpace ())
1921
1968
TODO (loc, " user defined assignment within WHERE" );
1922
1969
Fortran::semantics::SomeExpr expr{procRef};
1923
- createFIRExpr (toLocation (), &expr, stmtCtx);
1970
+ createFIRExpr (toLocation (), &expr,
1971
+ explicitIterationSpace ()
1972
+ ? explicitIterSpace.stmtContext ()
1973
+ : stmtCtx);
1924
1974
},
1925
1975
1926
1976
// [3] Pointer assignment with possibly empty bounds-spec. R1035: a
@@ -1981,6 +2031,8 @@ class FirConverter : public Fortran::lower::AbstractConverter {
1981
2031
},
1982
2032
},
1983
2033
assign.u );
2034
+ if (explicitIterationSpace ())
2035
+ Fortran::lower::createArrayMergeStores (*this , explicitIterSpace);
1984
2036
}
1985
2037
1986
2038
void genFIR (const Fortran::parser::WhereConstruct &c) {
@@ -2563,6 +2615,7 @@ class FirConverter : public Fortran::lower::AbstractConverter {
2563
2615
void analyzeExplicitSpace (const Fortran::evaluate::Assignment *assign) {
2564
2616
analyzeExplicitSpace</* LHS=*/ true >(assign->lhs );
2565
2617
analyzeExplicitSpace (assign->rhs );
2618
+ explicitIterSpace.endAssign ();
2566
2619
}
2567
2620
void analyzeExplicitSpace (const Fortran::parser::ForallAssignmentStmt &stmt) {
2568
2621
std::visit ([&](const auto &s) { analyzeExplicitSpace (s); }, stmt.u );
@@ -2693,7 +2746,11 @@ class FirConverter : public Fortran::lower::AbstractConverter {
2693
2746
auto var = builder->createTemporary (loc, ty);
2694
2747
auto nil = builder->createNullConstant (loc, ty);
2695
2748
builder->create <fir::StoreOp>(loc, nil, var);
2696
- implicitIterSpace.addMaskVariable (exp, var);
2749
+ auto shTy = fir::HeapType::get (builder->getIndexType ());
2750
+ auto shape = builder->createTemporary (loc, shTy);
2751
+ auto nilSh = builder->createNullConstant (loc, shTy);
2752
+ builder->create <fir::StoreOp>(loc, nilSh, shape);
2753
+ implicitIterSpace.addMaskVariable (exp, var, shape);
2697
2754
explicitIterSpace.outermostContext ().attachCleanup ([=]() {
2698
2755
auto load = builder->create <fir::LoadOp>(loc, var);
2699
2756
auto cmp = builder->genIsNotNull (loc, load);
0 commit comments