@@ -410,8 +410,9 @@ class PFTBuilder {
410
410
evaluationListStack.pop_back ();
411
411
}
412
412
413
- // / Rewrite IfConstructs containing a GotoStmt to eliminate an unstructured
414
- // / branch and a trivial basic block. The pre-branch-analysis code:
413
+ // / Rewrite IfConstructs containing a GotoStmt or CycleStmt to eliminate an
414
+ // / unstructured branch and a trivial basic block. The pre-branch-analysis
415
+ // / code:
415
416
// /
416
417
// / <<IfConstruct>>
417
418
// / 1 If[Then]Stmt: if(cond) goto L
@@ -433,8 +434,8 @@ class PFTBuilder {
433
434
// / 6 Statement: L ...
434
435
// /
435
436
// / The If[Then]Stmt condition is implicitly negated. It is not modified
436
- // / in the PFT. It must be negated when generating FIR. The GotoStmt is
437
- // / deleted.
437
+ // / in the PFT. It must be negated when generating FIR. The GotoStmt or
438
+ // / CycleStmt is deleted.
438
439
// /
439
440
// / The transformation is only valid for forward branch targets at the same
440
441
// / construct nesting level as the IfConstruct. The result must not violate
@@ -452,30 +453,49 @@ class PFTBuilder {
452
453
using T = struct {
453
454
lower::pft::EvaluationList::iterator ifConstructIt;
454
455
parser::Label ifTargetLabel;
456
+ bool isCycleStmt = false ;
455
457
};
456
- llvm::SmallVector<T> ifExpansionStack ;
458
+ llvm::SmallVector<T> ifCandidateStack ;
457
459
auto &evaluationList = *evaluationListStack.back ();
458
460
for (auto it = evaluationList.begin (), end = evaluationList.end ();
459
461
it != end; ++it) {
460
462
auto &eval = *it;
461
463
if (eval.isA <parser::EntryStmt>()) {
462
- ifExpansionStack .clear ();
464
+ ifCandidateStack .clear ();
463
465
continue ;
464
466
}
465
467
auto firstStmt = [](lower::pft::Evaluation *e) {
466
468
return e->isConstruct () ? &*e->evaluationList ->begin () : e;
467
469
};
468
470
auto &targetEval = *firstStmt (&eval);
469
- if (targetEval.label ) {
470
- while (!ifExpansionStack.empty () &&
471
- ifExpansionStack.back ().ifTargetLabel == *targetEval.label ) {
472
- auto ifConstructIt = ifExpansionStack.back ().ifConstructIt ;
471
+ bool targetEvalIsEndDoStmt = targetEval.isA <parser::EndDoStmt>();
472
+ auto branchTargetMatch = [&]() {
473
+ if (auto targetLabel = ifCandidateStack.back ().ifTargetLabel )
474
+ if (targetLabel == *targetEval.label )
475
+ return true ; // goto target match
476
+ if (targetEvalIsEndDoStmt && ifCandidateStack.back ().isCycleStmt ) {
477
+ auto cycleName = ifCandidateStack.back ().ifConstructIt ->visit (
478
+ [&](const auto &stmt) { return getConstructName (stmt); });
479
+ if (cycleName.empty ())
480
+ return true ; // anonymous cycle target match
481
+ auto doName = eval.visit (
482
+ [&](const auto &stmt) { return getConstructName (stmt); });
483
+ if (cycleName == doName)
484
+ return true ; // named cycle target match
485
+ }
486
+ return false ;
487
+ };
488
+ if (targetEval.label || targetEvalIsEndDoStmt) {
489
+ while (!ifCandidateStack.empty () && branchTargetMatch ()) {
490
+ auto ifConstructIt = ifCandidateStack.back ().ifConstructIt ;
473
491
auto successorIt = std::next (ifConstructIt);
474
492
if (successorIt != it) {
475
493
auto &ifBodyList = *ifConstructIt->evaluationList ;
476
- auto gotoStmtIt = std::next (ifBodyList.begin ());
477
- assert (gotoStmtIt->isA <parser::GotoStmt>() && " expected GotoStmt" );
478
- ifBodyList.erase (gotoStmtIt);
494
+ auto branchStmtIt = std::next (ifBodyList.begin ());
495
+ assert ((branchStmtIt->isA <parser::GotoStmt>() ||
496
+ branchStmtIt->isA <parser::CycleStmt>()) &&
497
+ " expected goto or cycle statement" );
498
+ ifBodyList.erase (branchStmtIt);
479
499
auto &ifStmt = *ifBodyList.begin ();
480
500
ifStmt.negateCondition = true ;
481
501
ifStmt.lexicalSuccessor = firstStmt (&*successorIt);
@@ -486,13 +506,16 @@ class PFTBuilder {
486
506
for (; successorIt != endIfStmtIt; ++successorIt)
487
507
successorIt->parentConstruct = &*ifConstructIt;
488
508
}
489
- ifExpansionStack .pop_back ();
509
+ ifCandidateStack .pop_back ();
490
510
}
491
511
}
492
512
if (eval.isA <parser::IfConstruct>() && eval.evaluationList ->size () == 3 ) {
493
513
if (auto *gotoStmt = std::next (eval.evaluationList ->begin ())
494
514
->getIf <parser::GotoStmt>())
495
- ifExpansionStack.push_back ({it, gotoStmt->v });
515
+ ifCandidateStack.push_back ({it, gotoStmt->v });
516
+ else if (std::next (eval.evaluationList ->begin ())
517
+ ->isA <parser::CycleStmt>())
518
+ ifCandidateStack.push_back ({it, {}, true });
496
519
}
497
520
}
498
521
}
0 commit comments