forked from OSchip/llvm-project
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:
parent
75b316929a
commit
d694dd0f0d
|
@ -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.
|
||||
///
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue