@@ -1302,6 +1302,43 @@ class FirConverter : public Fortran::lower::AbstractConverter {
1302
1302
genBranch (targetEval.block );
1303
1303
}
1304
1304
1305
+ // / A construct contains nested evaluations. Some of these evaluations
1306
+ // / may start a new basic block, others will add code to an existing
1307
+ // / block.
1308
+ // / Collect the list of nested evaluations that are last in their block,
1309
+ // / organize them into two sets:
1310
+ // / 1. Exiting evaluations: they may need a branch exiting from their
1311
+ // / parent construct,
1312
+ // / 2. Fall-through evaluations: they will continue to the following
1313
+ // / evaluation. They may still need a branch, but they do not exit
1314
+ // / the construct. They appear in cases where the following evaluation
1315
+ // / is a target of some branch.
1316
+ void collectFinalEvaluations (
1317
+ Fortran::lower::pft::Evaluation &construct,
1318
+ llvm::SmallVector<Fortran::lower::pft::Evaluation *> &exits,
1319
+ llvm::SmallVector<Fortran::lower::pft::Evaluation *> &fallThroughs) {
1320
+ Fortran::lower::pft::EvaluationList &nested =
1321
+ construct.getNestedEvaluations ();
1322
+ if (nested.empty ())
1323
+ return ;
1324
+
1325
+ Fortran::lower::pft::Evaluation *exit = construct.constructExit ;
1326
+ Fortran::lower::pft::Evaluation *previous = &nested.front ();
1327
+
1328
+ for (auto it = ++nested.begin (), end = nested.end (); it != end;
1329
+ previous = &*it++) {
1330
+ if (it->block == nullptr )
1331
+ continue ;
1332
+ // "*it" starts a new block, check what to do with "previous"
1333
+ if (it->isIntermediateConstructStmt () && previous != exit)
1334
+ exits.push_back (previous);
1335
+ else if (previous->lexicalSuccessor && previous->lexicalSuccessor ->block )
1336
+ fallThroughs.push_back (previous);
1337
+ }
1338
+ if (previous != exit)
1339
+ exits.push_back (previous);
1340
+ }
1341
+
1305
1342
// / Generate a SelectOp or branch sequence that compares \p selector against
1306
1343
// / values in \p valueList and targets corresponding labels in \p labelList.
1307
1344
// / If no value matches the selector, branch to \p defaultEval.
@@ -2109,6 +2146,9 @@ class FirConverter : public Fortran::lower::AbstractConverter {
2109
2146
}
2110
2147
2111
2148
// Unstructured branch sequence.
2149
+ llvm::SmallVector<Fortran::lower::pft::Evaluation *> exits, fallThroughs;
2150
+ collectFinalEvaluations (eval, exits, fallThroughs);
2151
+
2112
2152
for (Fortran::lower::pft::Evaluation &e : eval.getNestedEvaluations ()) {
2113
2153
auto genIfBranch = [&](mlir::Value cond) {
2114
2154
if (e.lexicalSuccessor == e.controlSuccessor ) // empty block -> exit
@@ -2129,6 +2169,12 @@ class FirConverter : public Fortran::lower::AbstractConverter {
2129
2169
genIfBranch (genIfCondition (s));
2130
2170
} else {
2131
2171
genFIR (e);
2172
+ if (blockIsUnterminated ()) {
2173
+ if (llvm::is_contained (exits, &e))
2174
+ genConstructExitBranch (*eval.constructExit );
2175
+ else if (llvm::is_contained (fallThroughs, &e))
2176
+ genBranch (e.lexicalSuccessor ->block );
2177
+ }
2132
2178
}
2133
2179
}
2134
2180
}
@@ -2137,11 +2183,21 @@ class FirConverter : public Fortran::lower::AbstractConverter {
2137
2183
Fortran::lower::pft::Evaluation &eval = getEval ();
2138
2184
Fortran::lower::StatementContext stmtCtx;
2139
2185
pushActiveConstruct (eval, stmtCtx);
2186
+
2187
+ llvm::SmallVector<Fortran::lower::pft::Evaluation *> exits, fallThroughs;
2188
+ collectFinalEvaluations (eval, exits, fallThroughs);
2189
+
2140
2190
for (Fortran::lower::pft::Evaluation &e : eval.getNestedEvaluations ()) {
2141
2191
if (e.getIf <Fortran::parser::EndSelectStmt>())
2142
2192
maybeStartBlock (e.block );
2143
2193
else
2144
2194
genFIR (e);
2195
+ if (blockIsUnterminated ()) {
2196
+ if (llvm::is_contained (exits, &e))
2197
+ genConstructExitBranch (*eval.constructExit );
2198
+ else if (llvm::is_contained (fallThroughs, &e))
2199
+ genBranch (e.lexicalSuccessor ->block );
2200
+ }
2145
2201
}
2146
2202
popActiveConstruct ();
2147
2203
}
@@ -3007,6 +3063,10 @@ class FirConverter : public Fortran::lower::AbstractConverter {
3007
3063
}
3008
3064
3009
3065
pushActiveConstruct (getEval (), stmtCtx);
3066
+ llvm::SmallVector<Fortran::lower::pft::Evaluation *> exits, fallThroughs;
3067
+ collectFinalEvaluations (getEval (), exits, fallThroughs);
3068
+ Fortran::lower::pft::Evaluation &constructExit = *getEval ().constructExit ;
3069
+
3010
3070
for (Fortran::lower::pft::Evaluation &eval :
3011
3071
getEval ().getNestedEvaluations ()) {
3012
3072
setCurrentPosition (eval.position );
@@ -3203,6 +3263,12 @@ class FirConverter : public Fortran::lower::AbstractConverter {
3203
3263
} else {
3204
3264
genFIR (eval);
3205
3265
}
3266
+ if (blockIsUnterminated ()) {
3267
+ if (llvm::is_contained (exits, &eval))
3268
+ genConstructExitBranch (constructExit);
3269
+ else if (llvm::is_contained (fallThroughs, &eval))
3270
+ genBranch (eval.lexicalSuccessor ->block );
3271
+ }
3206
3272
}
3207
3273
popActiveConstruct ();
3208
3274
}
@@ -4535,28 +4601,6 @@ class FirConverter : public Fortran::lower::AbstractConverter {
4535
4601
setCurrentEval (eval);
4536
4602
setCurrentPosition (eval.position );
4537
4603
eval.visit ([&](const auto &stmt) { genFIR (stmt); });
4538
-
4539
- // Generate an end-of-block branch for several special cases. For
4540
- // constructs, this can be done for either the end construct statement,
4541
- // or for the construct itself, which will skip this code if the
4542
- // end statement was visited first and generated a branch.
4543
- Fortran::lower::pft::Evaluation *successor = [&]() {
4544
- if (eval.isConstruct () ||
4545
- (eval.isDirective () && eval.hasNestedEvaluations ()))
4546
- return eval.getLastNestedEvaluation ().lexicalSuccessor ;
4547
- return eval.lexicalSuccessor ;
4548
- }();
4549
-
4550
- if (successor && blockIsUnterminated ()) {
4551
- if (successor->isIntermediateConstructStmt () &&
4552
- successor->parentConstruct ->lowerAsUnstructured ())
4553
- // Exit from an intermediate unstructured IF or SELECT construct block.
4554
- genBranch (successor->parentConstruct ->constructExit ->block );
4555
- else if (unstructuredContext && eval.isConstructStmt () &&
4556
- successor == eval.controlSuccessor )
4557
- // Exit from a degenerate, empty construct block.
4558
- genBranch (eval.parentConstruct ->constructExit ->block );
4559
- }
4560
4604
}
4561
4605
4562
4606
// / Map mlir function block arguments to the corresponding Fortran dummy
0 commit comments