mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-10-21 20:12:56 +02:00
Move isGuaranteedToExecute out of LICM.
Also rename LICMSafetyInfo to LoopSafetyInfo. Both will be used in LoopUnswitch in a separate change. llvm-svn: 272420
This commit is contained in:
parent
4faf864f2c
commit
212faec920
@ -38,13 +38,13 @@ class TargetLibraryInfo;
|
|||||||
|
|
||||||
/// \brief Captures loop safety information.
|
/// \brief Captures loop safety information.
|
||||||
/// It keep information for loop & its header may throw exception.
|
/// It keep information for loop & its header may throw exception.
|
||||||
struct LICMSafetyInfo {
|
struct LoopSafetyInfo {
|
||||||
bool MayThrow; // The current loop contains an instruction which
|
bool MayThrow; // The current loop contains an instruction which
|
||||||
// may throw.
|
// may throw.
|
||||||
bool HeaderMayThrow; // Same as previous, but specific to loop header
|
bool HeaderMayThrow; // Same as previous, but specific to loop header
|
||||||
// Used to update funclet bundle operands.
|
// Used to update funclet bundle operands.
|
||||||
DenseMap<BasicBlock *, ColorVector> BlockColors;
|
DenseMap<BasicBlock *, ColorVector> BlockColors;
|
||||||
LICMSafetyInfo() : MayThrow(false), HeaderMayThrow(false) {}
|
LoopSafetyInfo() : MayThrow(false), HeaderMayThrow(false) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The RecurrenceDescriptor is used to identify recurrences variables in a
|
/// The RecurrenceDescriptor is used to identify recurrences variables in a
|
||||||
@ -366,7 +366,7 @@ bool formLCSSARecursively(Loop &L, DominatorTree &DT, LoopInfo *LI,
|
|||||||
/// It returns changed status.
|
/// It returns changed status.
|
||||||
bool sinkRegion(DomTreeNode *, AliasAnalysis *, LoopInfo *, DominatorTree *,
|
bool sinkRegion(DomTreeNode *, AliasAnalysis *, LoopInfo *, DominatorTree *,
|
||||||
TargetLibraryInfo *, Loop *, AliasSetTracker *,
|
TargetLibraryInfo *, Loop *, AliasSetTracker *,
|
||||||
LICMSafetyInfo *);
|
LoopSafetyInfo *);
|
||||||
|
|
||||||
/// \brief Walk the specified region of the CFG (defined by all blocks
|
/// \brief Walk the specified region of the CFG (defined by all blocks
|
||||||
/// dominated by the specified block, and that are in the current loop) in depth
|
/// dominated by the specified block, and that are in the current loop) in depth
|
||||||
@ -377,7 +377,7 @@ bool sinkRegion(DomTreeNode *, AliasAnalysis *, LoopInfo *, DominatorTree *,
|
|||||||
/// loop and loop safety information as arguments. It returns changed status.
|
/// loop and loop safety information as arguments. It returns changed status.
|
||||||
bool hoistRegion(DomTreeNode *, AliasAnalysis *, LoopInfo *, DominatorTree *,
|
bool hoistRegion(DomTreeNode *, AliasAnalysis *, LoopInfo *, DominatorTree *,
|
||||||
TargetLibraryInfo *, Loop *, AliasSetTracker *,
|
TargetLibraryInfo *, Loop *, AliasSetTracker *,
|
||||||
LICMSafetyInfo *);
|
LoopSafetyInfo *);
|
||||||
|
|
||||||
/// \brief Try to promote memory values to scalars by sinking stores out of
|
/// \brief Try to promote memory values to scalars by sinking stores out of
|
||||||
/// the loop and moving loads to before the loop. We do this by looping over
|
/// the loop and moving loads to before the loop. We do this by looping over
|
||||||
@ -390,13 +390,19 @@ bool promoteLoopAccessesToScalars(AliasSet &, SmallVectorImpl<BasicBlock *> &,
|
|||||||
SmallVectorImpl<Instruction *> &,
|
SmallVectorImpl<Instruction *> &,
|
||||||
PredIteratorCache &, LoopInfo *,
|
PredIteratorCache &, LoopInfo *,
|
||||||
DominatorTree *, const TargetLibraryInfo *,
|
DominatorTree *, const TargetLibraryInfo *,
|
||||||
Loop *, AliasSetTracker *, LICMSafetyInfo *);
|
Loop *, AliasSetTracker *, LoopSafetyInfo *);
|
||||||
|
|
||||||
/// \brief Computes safety information for a loop
|
/// \brief Computes safety information for a loop
|
||||||
/// checks loop body & header for the possibility of may throw
|
/// checks loop body & header for the possibility of may throw
|
||||||
/// exception, it takes LICMSafetyInfo and loop as argument.
|
/// exception, it takes LoopSafetyInfo and loop as argument.
|
||||||
/// Updates safety information in LICMSafetyInfo argument.
|
/// Updates safety information in LoopSafetyInfo argument.
|
||||||
void computeLICMSafetyInfo(LICMSafetyInfo *, Loop *);
|
void computeLoopSafetyInfo(LoopSafetyInfo *, Loop *);
|
||||||
|
|
||||||
|
/// Returns true if the instruction in a loop is guaranteed to execute at least
|
||||||
|
/// once.
|
||||||
|
bool isGuaranteedToExecute(const Instruction &Inst, const DominatorTree *DT,
|
||||||
|
const Loop *CurLoop,
|
||||||
|
const LoopSafetyInfo *SafetyInfo);
|
||||||
|
|
||||||
/// \brief Returns the instructions that use values defined in the loop.
|
/// \brief Returns the instructions that use values defined in the loop.
|
||||||
SmallVector<Instruction *, 8> findDefsUsedOutsideOfLoop(Loop *L);
|
SmallVector<Instruction *, 8> findDefsUsedOutsideOfLoop(Loop *L);
|
||||||
|
@ -80,20 +80,17 @@ static cl::opt<bool>
|
|||||||
|
|
||||||
static bool inSubLoop(BasicBlock *BB, Loop *CurLoop, LoopInfo *LI);
|
static bool inSubLoop(BasicBlock *BB, Loop *CurLoop, LoopInfo *LI);
|
||||||
static bool isNotUsedInLoop(const Instruction &I, const Loop *CurLoop,
|
static bool isNotUsedInLoop(const Instruction &I, const Loop *CurLoop,
|
||||||
const LICMSafetyInfo *SafetyInfo);
|
const LoopSafetyInfo *SafetyInfo);
|
||||||
static bool hoist(Instruction &I, const DominatorTree *DT, const Loop *CurLoop,
|
static bool hoist(Instruction &I, const DominatorTree *DT, const Loop *CurLoop,
|
||||||
const LICMSafetyInfo *SafetyInfo);
|
const LoopSafetyInfo *SafetyInfo);
|
||||||
static bool sink(Instruction &I, const LoopInfo *LI, const DominatorTree *DT,
|
static bool sink(Instruction &I, const LoopInfo *LI, const DominatorTree *DT,
|
||||||
const Loop *CurLoop, AliasSetTracker *CurAST,
|
const Loop *CurLoop, AliasSetTracker *CurAST,
|
||||||
const LICMSafetyInfo *SafetyInfo);
|
const LoopSafetyInfo *SafetyInfo);
|
||||||
static bool isGuaranteedToExecute(const Instruction &Inst,
|
|
||||||
const DominatorTree *DT, const Loop *CurLoop,
|
|
||||||
const LICMSafetyInfo *SafetyInfo);
|
|
||||||
static bool isSafeToExecuteUnconditionally(const Instruction &Inst,
|
static bool isSafeToExecuteUnconditionally(const Instruction &Inst,
|
||||||
const DominatorTree *DT,
|
const DominatorTree *DT,
|
||||||
const TargetLibraryInfo *TLI,
|
const TargetLibraryInfo *TLI,
|
||||||
const Loop *CurLoop,
|
const Loop *CurLoop,
|
||||||
const LICMSafetyInfo *SafetyInfo,
|
const LoopSafetyInfo *SafetyInfo,
|
||||||
const Instruction *CtxI = nullptr);
|
const Instruction *CtxI = nullptr);
|
||||||
static bool pointerInvalidatedByLoop(Value *V, uint64_t Size,
|
static bool pointerInvalidatedByLoop(Value *V, uint64_t Size,
|
||||||
const AAMDNodes &AAInfo,
|
const AAMDNodes &AAInfo,
|
||||||
@ -101,11 +98,11 @@ static bool pointerInvalidatedByLoop(Value *V, uint64_t Size,
|
|||||||
static Instruction *
|
static Instruction *
|
||||||
CloneInstructionInExitBlock(Instruction &I, BasicBlock &ExitBlock, PHINode &PN,
|
CloneInstructionInExitBlock(Instruction &I, BasicBlock &ExitBlock, PHINode &PN,
|
||||||
const LoopInfo *LI,
|
const LoopInfo *LI,
|
||||||
const LICMSafetyInfo *SafetyInfo);
|
const LoopSafetyInfo *SafetyInfo);
|
||||||
static bool canSinkOrHoistInst(Instruction &I, AliasAnalysis *AA,
|
static bool canSinkOrHoistInst(Instruction &I, AliasAnalysis *AA,
|
||||||
DominatorTree *DT, TargetLibraryInfo *TLI,
|
DominatorTree *DT, TargetLibraryInfo *TLI,
|
||||||
Loop *CurLoop, AliasSetTracker *CurAST,
|
Loop *CurLoop, AliasSetTracker *CurAST,
|
||||||
LICMSafetyInfo *SafetyInfo);
|
LoopSafetyInfo *SafetyInfo);
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
struct LICM : public LoopPass {
|
struct LICM : public LoopPass {
|
||||||
@ -196,8 +193,8 @@ bool LICM::runOnLoop(Loop *L, LPPassManager &LPM) {
|
|||||||
Preheader = L->getLoopPreheader();
|
Preheader = L->getLoopPreheader();
|
||||||
|
|
||||||
// Compute loop safety information.
|
// Compute loop safety information.
|
||||||
LICMSafetyInfo SafetyInfo;
|
LoopSafetyInfo SafetyInfo;
|
||||||
computeLICMSafetyInfo(&SafetyInfo, CurLoop);
|
computeLoopSafetyInfo(&SafetyInfo, CurLoop);
|
||||||
|
|
||||||
// We want to visit all of the instructions in this loop... that are not parts
|
// We want to visit all of the instructions in this loop... that are not parts
|
||||||
// of our subloops (they have already had their invariants hoisted out of
|
// of our subloops (they have already had their invariants hoisted out of
|
||||||
@ -272,7 +269,7 @@ bool LICM::runOnLoop(Loop *L, LPPassManager &LPM) {
|
|||||||
///
|
///
|
||||||
bool llvm::sinkRegion(DomTreeNode *N, AliasAnalysis *AA, LoopInfo *LI,
|
bool llvm::sinkRegion(DomTreeNode *N, AliasAnalysis *AA, LoopInfo *LI,
|
||||||
DominatorTree *DT, TargetLibraryInfo *TLI, Loop *CurLoop,
|
DominatorTree *DT, TargetLibraryInfo *TLI, Loop *CurLoop,
|
||||||
AliasSetTracker *CurAST, LICMSafetyInfo *SafetyInfo) {
|
AliasSetTracker *CurAST, LoopSafetyInfo *SafetyInfo) {
|
||||||
|
|
||||||
// Verify inputs.
|
// Verify inputs.
|
||||||
assert(N != nullptr && AA != nullptr && LI != nullptr && DT != nullptr &&
|
assert(N != nullptr && AA != nullptr && LI != nullptr && DT != nullptr &&
|
||||||
@ -330,7 +327,7 @@ bool llvm::sinkRegion(DomTreeNode *N, AliasAnalysis *AA, LoopInfo *LI,
|
|||||||
///
|
///
|
||||||
bool llvm::hoistRegion(DomTreeNode *N, AliasAnalysis *AA, LoopInfo *LI,
|
bool llvm::hoistRegion(DomTreeNode *N, AliasAnalysis *AA, LoopInfo *LI,
|
||||||
DominatorTree *DT, TargetLibraryInfo *TLI, Loop *CurLoop,
|
DominatorTree *DT, TargetLibraryInfo *TLI, Loop *CurLoop,
|
||||||
AliasSetTracker *CurAST, LICMSafetyInfo *SafetyInfo) {
|
AliasSetTracker *CurAST, LoopSafetyInfo *SafetyInfo) {
|
||||||
// Verify inputs.
|
// Verify inputs.
|
||||||
assert(N != nullptr && AA != nullptr && LI != nullptr && DT != nullptr &&
|
assert(N != nullptr && AA != nullptr && LI != nullptr && DT != nullptr &&
|
||||||
CurLoop != nullptr && CurAST != nullptr && SafetyInfo != nullptr &&
|
CurLoop != nullptr && CurAST != nullptr && SafetyInfo != nullptr &&
|
||||||
@ -382,7 +379,7 @@ bool llvm::hoistRegion(DomTreeNode *N, AliasAnalysis *AA, LoopInfo *LI,
|
|||||||
/// Computes loop safety information, checks loop body & header
|
/// Computes loop safety information, checks loop body & header
|
||||||
/// for the possibility of may throw exception.
|
/// for the possibility of may throw exception.
|
||||||
///
|
///
|
||||||
void llvm::computeLICMSafetyInfo(LICMSafetyInfo *SafetyInfo, Loop *CurLoop) {
|
void llvm::computeLoopSafetyInfo(LoopSafetyInfo *SafetyInfo, Loop *CurLoop) {
|
||||||
assert(CurLoop != nullptr && "CurLoop cant be null");
|
assert(CurLoop != nullptr && "CurLoop cant be null");
|
||||||
BasicBlock *Header = CurLoop->getHeader();
|
BasicBlock *Header = CurLoop->getHeader();
|
||||||
// Setting default safety values.
|
// Setting default safety values.
|
||||||
@ -416,7 +413,7 @@ void llvm::computeLICMSafetyInfo(LICMSafetyInfo *SafetyInfo, Loop *CurLoop) {
|
|||||||
///
|
///
|
||||||
bool canSinkOrHoistInst(Instruction &I, AliasAnalysis *AA, DominatorTree *DT,
|
bool canSinkOrHoistInst(Instruction &I, AliasAnalysis *AA, DominatorTree *DT,
|
||||||
TargetLibraryInfo *TLI, Loop *CurLoop,
|
TargetLibraryInfo *TLI, Loop *CurLoop,
|
||||||
AliasSetTracker *CurAST, LICMSafetyInfo *SafetyInfo) {
|
AliasSetTracker *CurAST, LoopSafetyInfo *SafetyInfo) {
|
||||||
// Loads have extra constraints we have to verify before we can hoist them.
|
// Loads have extra constraints we have to verify before we can hoist them.
|
||||||
if (LoadInst *LI = dyn_cast<LoadInst>(&I)) {
|
if (LoadInst *LI = dyn_cast<LoadInst>(&I)) {
|
||||||
if (!LI->isUnordered())
|
if (!LI->isUnordered())
|
||||||
@ -515,7 +512,7 @@ static bool isTriviallyReplacablePHI(const PHINode &PN, const Instruction &I) {
|
|||||||
/// blocks of the loop.
|
/// blocks of the loop.
|
||||||
///
|
///
|
||||||
static bool isNotUsedInLoop(const Instruction &I, const Loop *CurLoop,
|
static bool isNotUsedInLoop(const Instruction &I, const Loop *CurLoop,
|
||||||
const LICMSafetyInfo *SafetyInfo) {
|
const LoopSafetyInfo *SafetyInfo) {
|
||||||
const auto &BlockColors = SafetyInfo->BlockColors;
|
const auto &BlockColors = SafetyInfo->BlockColors;
|
||||||
for (const User *U : I.users()) {
|
for (const User *U : I.users()) {
|
||||||
const Instruction *UI = cast<Instruction>(U);
|
const Instruction *UI = cast<Instruction>(U);
|
||||||
@ -562,7 +559,7 @@ static bool isNotUsedInLoop(const Instruction &I, const Loop *CurLoop,
|
|||||||
static Instruction *
|
static Instruction *
|
||||||
CloneInstructionInExitBlock(Instruction &I, BasicBlock &ExitBlock, PHINode &PN,
|
CloneInstructionInExitBlock(Instruction &I, BasicBlock &ExitBlock, PHINode &PN,
|
||||||
const LoopInfo *LI,
|
const LoopInfo *LI,
|
||||||
const LICMSafetyInfo *SafetyInfo) {
|
const LoopSafetyInfo *SafetyInfo) {
|
||||||
Instruction *New;
|
Instruction *New;
|
||||||
if (auto *CI = dyn_cast<CallInst>(&I)) {
|
if (auto *CI = dyn_cast<CallInst>(&I)) {
|
||||||
const auto &BlockColors = SafetyInfo->BlockColors;
|
const auto &BlockColors = SafetyInfo->BlockColors;
|
||||||
@ -627,7 +624,7 @@ CloneInstructionInExitBlock(Instruction &I, BasicBlock &ExitBlock, PHINode &PN,
|
|||||||
///
|
///
|
||||||
static bool sink(Instruction &I, const LoopInfo *LI, const DominatorTree *DT,
|
static bool sink(Instruction &I, const LoopInfo *LI, const DominatorTree *DT,
|
||||||
const Loop *CurLoop, AliasSetTracker *CurAST,
|
const Loop *CurLoop, AliasSetTracker *CurAST,
|
||||||
const LICMSafetyInfo *SafetyInfo) {
|
const LoopSafetyInfo *SafetyInfo) {
|
||||||
DEBUG(dbgs() << "LICM sinking instruction: " << I << "\n");
|
DEBUG(dbgs() << "LICM sinking instruction: " << I << "\n");
|
||||||
bool Changed = false;
|
bool Changed = false;
|
||||||
if (isa<LoadInst>(I))
|
if (isa<LoadInst>(I))
|
||||||
@ -695,7 +692,7 @@ static bool sink(Instruction &I, const LoopInfo *LI, const DominatorTree *DT,
|
|||||||
/// is safe to hoist, this instruction is called to do the dirty work.
|
/// is safe to hoist, this instruction is called to do the dirty work.
|
||||||
///
|
///
|
||||||
static bool hoist(Instruction &I, const DominatorTree *DT, const Loop *CurLoop,
|
static bool hoist(Instruction &I, const DominatorTree *DT, const Loop *CurLoop,
|
||||||
const LICMSafetyInfo *SafetyInfo) {
|
const LoopSafetyInfo *SafetyInfo) {
|
||||||
auto *Preheader = CurLoop->getLoopPreheader();
|
auto *Preheader = CurLoop->getLoopPreheader();
|
||||||
DEBUG(dbgs() << "LICM hoisting to " << Preheader->getName() << ": " << I
|
DEBUG(dbgs() << "LICM hoisting to " << Preheader->getName() << ": " << I
|
||||||
<< "\n");
|
<< "\n");
|
||||||
@ -729,7 +726,7 @@ static bool isSafeToExecuteUnconditionally(const Instruction &Inst,
|
|||||||
const DominatorTree *DT,
|
const DominatorTree *DT,
|
||||||
const TargetLibraryInfo *TLI,
|
const TargetLibraryInfo *TLI,
|
||||||
const Loop *CurLoop,
|
const Loop *CurLoop,
|
||||||
const LICMSafetyInfo *SafetyInfo,
|
const LoopSafetyInfo *SafetyInfo,
|
||||||
const Instruction *CtxI) {
|
const Instruction *CtxI) {
|
||||||
if (isSafeToSpeculativelyExecute(&Inst, CtxI, DT, TLI))
|
if (isSafeToSpeculativelyExecute(&Inst, CtxI, DT, TLI))
|
||||||
return true;
|
return true;
|
||||||
@ -737,44 +734,6 @@ static bool isSafeToExecuteUnconditionally(const Instruction &Inst,
|
|||||||
return isGuaranteedToExecute(Inst, DT, CurLoop, SafetyInfo);
|
return isGuaranteedToExecute(Inst, DT, CurLoop, SafetyInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isGuaranteedToExecute(const Instruction &Inst,
|
|
||||||
const DominatorTree *DT, const Loop *CurLoop,
|
|
||||||
const LICMSafetyInfo *SafetyInfo) {
|
|
||||||
|
|
||||||
// We have to check to make sure that the instruction dominates all
|
|
||||||
// of the exit blocks. If it doesn't, then there is a path out of the loop
|
|
||||||
// which does not execute this instruction, so we can't hoist it.
|
|
||||||
|
|
||||||
// If the instruction is in the header block for the loop (which is very
|
|
||||||
// common), it is always guaranteed to dominate the exit blocks. Since this
|
|
||||||
// is a common case, and can save some work, check it now.
|
|
||||||
if (Inst.getParent() == CurLoop->getHeader())
|
|
||||||
// If there's a throw in the header block, we can't guarantee we'll reach
|
|
||||||
// Inst.
|
|
||||||
return !SafetyInfo->HeaderMayThrow;
|
|
||||||
|
|
||||||
// Somewhere in this loop there is an instruction which may throw and make us
|
|
||||||
// exit the loop.
|
|
||||||
if (SafetyInfo->MayThrow)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Get the exit blocks for the current loop.
|
|
||||||
SmallVector<BasicBlock *, 8> ExitBlocks;
|
|
||||||
CurLoop->getExitBlocks(ExitBlocks);
|
|
||||||
|
|
||||||
// Verify that the block dominates each of the exit blocks of the loop.
|
|
||||||
for (BasicBlock *ExitBlock : ExitBlocks)
|
|
||||||
if (!DT->dominates(Inst.getParent(), ExitBlock))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// As a degenerate case, if the loop is statically infinite then we haven't
|
|
||||||
// proven anything since there are no exit blocks.
|
|
||||||
if (ExitBlocks.empty())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
class LoopPromoter : public LoadAndStorePromoter {
|
class LoopPromoter : public LoadAndStorePromoter {
|
||||||
Value *SomePtr; // Designated pointer to store to.
|
Value *SomePtr; // Designated pointer to store to.
|
||||||
@ -860,7 +819,7 @@ bool llvm::promoteLoopAccessesToScalars(
|
|||||||
AliasSet &AS, SmallVectorImpl<BasicBlock *> &ExitBlocks,
|
AliasSet &AS, SmallVectorImpl<BasicBlock *> &ExitBlocks,
|
||||||
SmallVectorImpl<Instruction *> &InsertPts, PredIteratorCache &PIC,
|
SmallVectorImpl<Instruction *> &InsertPts, PredIteratorCache &PIC,
|
||||||
LoopInfo *LI, DominatorTree *DT, const TargetLibraryInfo *TLI,
|
LoopInfo *LI, DominatorTree *DT, const TargetLibraryInfo *TLI,
|
||||||
Loop *CurLoop, AliasSetTracker *CurAST, LICMSafetyInfo *SafetyInfo) {
|
Loop *CurLoop, AliasSetTracker *CurAST, LoopSafetyInfo *SafetyInfo) {
|
||||||
// Verify inputs.
|
// Verify inputs.
|
||||||
assert(LI != nullptr && DT != nullptr && CurLoop != nullptr &&
|
assert(LI != nullptr && DT != nullptr && CurLoop != nullptr &&
|
||||||
CurAST != nullptr && SafetyInfo != nullptr &&
|
CurAST != nullptr && SafetyInfo != nullptr &&
|
||||||
|
@ -925,3 +925,42 @@ Optional<const MDOperand *> llvm::findStringMetadataForLoop(Loop *TheLoop,
|
|||||||
}
|
}
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns true if the instruction in a loop is guaranteed to execute at least
|
||||||
|
/// once.
|
||||||
|
bool llvm::isGuaranteedToExecute(const Instruction &Inst,
|
||||||
|
const DominatorTree *DT, const Loop *CurLoop,
|
||||||
|
const LoopSafetyInfo *SafetyInfo) {
|
||||||
|
// We have to check to make sure that the instruction dominates all
|
||||||
|
// of the exit blocks. If it doesn't, then there is a path out of the loop
|
||||||
|
// which does not execute this instruction, so we can't hoist it.
|
||||||
|
|
||||||
|
// If the instruction is in the header block for the loop (which is very
|
||||||
|
// common), it is always guaranteed to dominate the exit blocks. Since this
|
||||||
|
// is a common case, and can save some work, check it now.
|
||||||
|
if (Inst.getParent() == CurLoop->getHeader())
|
||||||
|
// If there's a throw in the header block, we can't guarantee we'll reach
|
||||||
|
// Inst.
|
||||||
|
return !SafetyInfo->HeaderMayThrow;
|
||||||
|
|
||||||
|
// Somewhere in this loop there is an instruction which may throw and make us
|
||||||
|
// exit the loop.
|
||||||
|
if (SafetyInfo->MayThrow)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Get the exit blocks for the current loop.
|
||||||
|
SmallVector<BasicBlock *, 8> ExitBlocks;
|
||||||
|
CurLoop->getExitBlocks(ExitBlocks);
|
||||||
|
|
||||||
|
// Verify that the block dominates each of the exit blocks of the loop.
|
||||||
|
for (BasicBlock *ExitBlock : ExitBlocks)
|
||||||
|
if (!DT->dominates(Inst.getParent(), ExitBlock))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// As a degenerate case, if the loop is statically infinite then we haven't
|
||||||
|
// proven anything since there are no exit blocks.
|
||||||
|
if (ExitBlocks.empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user