Skip to content

Commit 0287a1e

Browse files
committed
SILOptimizer: Use BasicBlockData in the InfiniteRecursionAnalysis
1 parent cf17fd4 commit 0287a1e

File tree

1 file changed

+30
-39
lines changed

1 file changed

+30
-39
lines changed

lib/SILOptimizer/Mandatory/DiagnoseInfiniteRecursion.cpp

Lines changed: 30 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
#include "swift/SIL/SILInstruction.h"
4444
#include "swift/SIL/ApplySite.h"
4545
#include "swift/SIL/MemAccessUtils.h"
46+
#include "swift/SIL/BasicBlockData.h"
4647
#include "swift/SILOptimizer/PassManager/Transforms.h"
4748
#include "swift/SILOptimizer/Utils/InstOptUtils.h"
4849
#include "swift/SILOptimizer/Utils/Devirtualize.h"
@@ -302,11 +303,6 @@ struct BlockInfo {
302303
/// recursive call.
303304
bool reachableFromEntry;
304305

305-
// Make DenseMap<...,BlockInfo> compilable.
306-
BlockInfo() {
307-
llvm_unreachable("DenseMap should not construct an empty BlockInfo");
308-
}
309-
310306
/// Get block information with expected \p invariants.
311307
BlockInfo(SILBasicBlock *block, Invariants invariants) :
312308
recursiveCall(nullptr),
@@ -380,35 +376,31 @@ struct BlockInfo {
380376
/// }
381377
///
382378
class InfiniteRecursionAnalysis {
383-
SILFunction *function;
384-
llvm::DenseMap<SILBasicBlock *, BlockInfo> blockInfos;
385-
386-
InfiniteRecursionAnalysis(SILFunction *function) :
387-
function(function),
388-
// Reserve enough space in the map. Though, SILFunction::size() iterates
389-
// over all blocks. But this is still better than to risk multiple mallocs.
390-
blockInfos(function->size()) { }
379+
Invariants invariants;
380+
BasicBlockData<BlockInfo> blockInfos;
391381

392-
BlockInfo &info(SILBasicBlock *block) { return blockInfos[block]; }
382+
InfiniteRecursionAnalysis(SILFunction *function, Invariants invariants) :
383+
invariants(invariants), blockInfos(function,
384+
[&](SILBasicBlock *block) -> BlockInfo {
385+
return BlockInfo(block, invariants);
386+
}) { }
393387

394388
/// Propagates the `reachesReturn` flags up the control flow and returns true
395389
/// if the flag reaches the entry block.
396-
bool isEntryReachableFromReturn(Invariants invariants) {
390+
bool isEntryReachableFromReturn() {
397391
// Contains blocks for which the `reachesReturn` flag is set.
398392
SmallVector<SILBasicBlock *, 32> workList;
399393

400-
// First, initialize the block infos.
401-
for (SILBasicBlock &block : *function) {
402-
BlockInfo blockInfo(&block, invariants);
403-
blockInfos.insert({&block, blockInfo});
404-
if (blockInfo.reachesReturn)
405-
workList.push_back(&block);
394+
// Initialize the workList with all function-return blocks.
395+
for (auto bd : blockInfos) {
396+
if (bd.data.reachesReturn)
397+
workList.push_back(&bd.block);
406398
}
407399

408400
while (!workList.empty()) {
409401
SILBasicBlock *block = workList.pop_back_val();
410402
for (auto *pred : block->getPredecessorBlocks()) {
411-
BlockInfo &predInfo = info(pred);
403+
BlockInfo &predInfo = blockInfos[pred];
412404
if (predInfo.reachesReturn ||
413405
// Recursive calls block the flag propagation.
414406
predInfo.recursiveCall != nullptr)
@@ -432,30 +424,30 @@ class InfiniteRecursionAnalysis {
432424
workList.push_back(pred);
433425
}
434426
}
435-
return info(function->getEntryBlock()).reachesReturn;
427+
return blockInfos.entry().data.reachesReturn;
436428
}
437429

438430
/// Propagates the `reachableFromEntry` flags down the control flow and
439431
/// issues a warning if it reaches a recursive call.
440432
/// Returns true, if at least one recursive call is found.
441433
bool findRecursiveCallsAndDiagnose() {
442434
SmallVector<SILBasicBlock *, 32> workList;
443-
SILBasicBlock *entryBlock = function->getEntryBlock();
444-
info(entryBlock).reachableFromEntry = true;
445-
workList.push_back(entryBlock);
435+
auto entry = blockInfos.entry();
436+
entry.data.reachableFromEntry = true;
437+
workList.push_back(&entry.block);
446438

447439
bool foundInfiniteRecursion = false;
448440
while (!workList.empty()) {
449441
SILBasicBlock *block = workList.pop_back_val();
450-
if (auto *recursiveCall = info(block).recursiveCall) {
451-
function->getModule().getASTContext().Diags.diagnose(
442+
if (auto *recursiveCall = blockInfos[block].recursiveCall) {
443+
blockInfos.getFunction()->getModule().getASTContext().Diags.diagnose(
452444
recursiveCall->getLoc().getSourceLoc(),
453445
diag::warn_infinite_recursive_call);
454446
foundInfiniteRecursion = true;
455447
continue;
456448
}
457449
for (auto *succ : block->getSuccessorBlocks()) {
458-
BlockInfo &succInfo = info(succ);
450+
BlockInfo &succInfo = blockInfos[succ];
459451
if (!succInfo.reachesReturn && !succInfo.reachableFromEntry) {
460452
succInfo.reachableFromEntry = true;
461453
workList.push_back(succ);
@@ -468,17 +460,16 @@ class InfiniteRecursionAnalysis {
468460
public:
469461

470462
LLVM_ATTRIBUTE_USED void dump() {
471-
for (SILBasicBlock &block : *function) {
472-
BlockInfo &blockInfo = info(&block);
473-
llvm::dbgs() << "bb" << block.getDebugID()
474-
<< ": numSuccs= " << blockInfo.numSuccsNotReachingReturn;
475-
if (blockInfo.recursiveCall)
463+
for (auto bd : blockInfos) {
464+
llvm::dbgs() << "bb" << bd.block.getDebugID()
465+
<< ": numSuccs= " << bd.data.numSuccsNotReachingReturn;
466+
if (bd.data.recursiveCall)
476467
llvm::dbgs() << " hasRecursiveCall";
477-
if (blockInfo.hasInvariantCondition)
468+
if (bd.data.hasInvariantCondition)
478469
llvm::dbgs() << " hasInvariantCondition";
479-
if (blockInfo.reachesReturn)
470+
if (bd.data.reachesReturn)
480471
llvm::dbgs() << " reachesReturn";
481-
if (blockInfo.reachableFromEntry)
472+
if (bd.data.reachableFromEntry)
482473
llvm::dbgs() << " reachesRecursiveCall";
483474
llvm::dbgs() << '\n';
484475
}
@@ -487,8 +478,8 @@ class InfiniteRecursionAnalysis {
487478
/// Performs the analysis and issues a warnings for recursive calls.
488479
/// Returns true, if at least one recursive call is found.
489480
static bool analyzeAndDiagnose(SILFunction *function, Invariants invariants) {
490-
InfiniteRecursionAnalysis analysis(function);
491-
if (analysis.isEntryReachableFromReturn(invariants))
481+
InfiniteRecursionAnalysis analysis(function, invariants);
482+
if (analysis.isEntryReachableFromReturn())
492483
return false;
493484

494485
// Now we know that the function never returns.

0 commit comments

Comments
 (0)