Add iterator range variants of isGuaranteedToTransferExecutionToSuccessor [mostly-nfc]

This factors out utilities for scanning a bounded block of instructions since we have this code repeated in a bunch of places.  The change to InlineFunction isn't strictly NFC as the limit mechanism there didn't handle debug instructions correctly.
This commit is contained in:
Philip Reames 2021-10-08 08:58:03 -07:00
parent 75b316929a
commit d694dd0f0d
4 changed files with 44 additions and 37 deletions

View File

@ -574,6 +574,18 @@ constexpr unsigned MaxAnalysisRecursionDepth = 6;
/// instruction variant of this function.
bool isGuaranteedToTransferExecutionToSuccessor(const BasicBlock *BB);
/// Return true if every instruction in the range (Begin, End) is
/// guaranteed to transfer execution to its static successor. \p ScanLimit
/// bounds the search to avoid scanning huge blocks.
bool isGuaranteedToTransferExecutionToSuccessor(
BasicBlock::const_iterator Begin, BasicBlock::const_iterator End,
unsigned ScanLimit = 32);
/// Same as previous, but with range expressed via iterator_range.
bool isGuaranteedToTransferExecutionToSuccessor(
iterator_range<BasicBlock::const_iterator> Range,
unsigned ScanLimit = 32);
/// Return true if this function can prove that the instruction I
/// is executed for every iteration of the loop L.
///

View File

@ -6631,39 +6631,20 @@ ScalarEvolution::getDefiningScopeBound(ArrayRef<const SCEV *> Ops) {
return Bound ? Bound : &*F.getEntryBlock().begin();
}
static bool
isGuaranteedToTransferExecutionToSuccessor(BasicBlock::const_iterator Begin,
BasicBlock::const_iterator End) {
// Limit number of instructions we look at, to avoid scanning through large
// blocks. The current limit is chosen arbitrarily.
unsigned ScanLimit = 32;
for (const Instruction &I : make_range(Begin, End)) {
if (isa<DbgInfoIntrinsic>(I))
continue;
if (--ScanLimit == 0)
return false;
if (!isGuaranteedToTransferExecutionToSuccessor(&I))
return false;
}
return true;
}
bool ScalarEvolution::isGuaranteedToTransferExecutionTo(const Instruction *A,
const Instruction *B) {
if (A->getParent() == B->getParent() &&
::isGuaranteedToTransferExecutionToSuccessor(A->getIterator(),
B->getIterator()))
isGuaranteedToTransferExecutionToSuccessor(A->getIterator(),
B->getIterator()))
return true;
auto *BLoop = LI.getLoopFor(B->getParent());
if (BLoop && BLoop->getHeader() == B->getParent() &&
BLoop->getLoopPreheader() == A->getParent() &&
::isGuaranteedToTransferExecutionToSuccessor(A->getIterator(),
A->getParent()->end()) &&
::isGuaranteedToTransferExecutionToSuccessor(B->getParent()->begin(),
B->getIterator()))
isGuaranteedToTransferExecutionToSuccessor(A->getIterator(),
A->getParent()->end()) &&
isGuaranteedToTransferExecutionToSuccessor(B->getParent()->begin(),
B->getIterator()))
return true;
return false;
}

View File

@ -542,10 +542,9 @@ bool llvm::isValidAssumeForContext(const Instruction *Inv,
// We limit the scan distance between the assume and its context instruction
// to avoid a compile-time explosion. This limit is chosen arbitrarily, so
// it can be adjusted if needed (could be turned into a cl::opt).
unsigned ScanLimit = 15;
for (BasicBlock::const_iterator I(CxtI), IE(Inv); I != IE; ++I)
if (!isGuaranteedToTransferExecutionToSuccessor(&*I) || --ScanLimit == 0)
return false;
auto Range = make_range(CxtI->getIterator(), Inv->getIterator());
if (!isGuaranteedToTransferExecutionToSuccessor(Range, 15))
return false;
return !isEphemeralValueOf(Inv, CxtI);
}
@ -5331,6 +5330,27 @@ bool llvm::isGuaranteedToTransferExecutionToSuccessor(const BasicBlock *BB) {
return true;
}
bool llvm::isGuaranteedToTransferExecutionToSuccessor(
BasicBlock::const_iterator Begin, BasicBlock::const_iterator End,
unsigned ScanLimit) {
return isGuaranteedToTransferExecutionToSuccessor(make_range(Begin, End),
ScanLimit);
}
bool llvm::isGuaranteedToTransferExecutionToSuccessor(
iterator_range<BasicBlock::const_iterator> Range, unsigned ScanLimit) {
assert(ScanLimit && "scan limit must be non-zero");
for (const Instruction &I : Range) {
if (isa<DbgInfoIntrinsic>(I))
continue;
if (--ScanLimit == 0)
return false;
if (!isGuaranteedToTransferExecutionToSuccessor(&I))
return false;
}
return true;
}
bool llvm::isGuaranteedToExecuteForEveryIteration(const Instruction *I,
const Loop *L) {
// The loop header is guaranteed to be executed for every iteration.

View File

@ -1177,14 +1177,8 @@ static bool MayContainThrowingOrExitingCall(Instruction *Begin,
assert(Begin->getParent() == End->getParent() &&
"Expected to be in same basic block!");
unsigned NumInstChecked = 0;
// Check that all instructions in the range [Begin, End) are guaranteed to
// transfer execution to successor.
for (auto &I : make_range(Begin->getIterator(), End->getIterator()))
if (NumInstChecked++ > InlinerAttributeWindow ||
!isGuaranteedToTransferExecutionToSuccessor(&I))
return true;
return false;
return !llvm::isGuaranteedToTransferExecutionToSuccessor(
Begin->getIterator(), End->getIterator(), InlinerAttributeWindow + 1);
}
static AttrBuilder IdentifyValidAttributes(CallBase &CB) {