mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 10:42:39 +01:00
clang-format some files in preparation of coming patch reviews.
llvm-svn: 268583
This commit is contained in:
parent
de3dbc167b
commit
07daedc517
@ -37,13 +37,12 @@ class TargetLibraryInfo;
|
||||
/// \brief Captures loop safety information.
|
||||
/// It keep information for loop & its header may throw exception.
|
||||
struct LICMSafetyInfo {
|
||||
bool MayThrow; // The current loop contains an instruction which
|
||||
// may throw.
|
||||
bool HeaderMayThrow; // Same as previous, but specific to loop header
|
||||
bool MayThrow; // The current loop contains an instruction which
|
||||
// may throw.
|
||||
bool HeaderMayThrow; // Same as previous, but specific to loop header
|
||||
// Used to update funclet bundle operands.
|
||||
DenseMap<BasicBlock *, ColorVector> BlockColors;
|
||||
LICMSafetyInfo() : MayThrow(false), HeaderMayThrow(false)
|
||||
{}
|
||||
LICMSafetyInfo() : MayThrow(false), HeaderMayThrow(false) {}
|
||||
};
|
||||
|
||||
/// The RecurrenceDescriptor is used to identify recurrences variables in a
|
||||
@ -268,7 +267,7 @@ public:
|
||||
public:
|
||||
/// Default constructor - creates an invalid induction.
|
||||
InductionDescriptor()
|
||||
: StartValue(nullptr), IK(IK_NoInduction), StepValue(nullptr) {}
|
||||
: StartValue(nullptr), IK(IK_NoInduction), StepValue(nullptr) {}
|
||||
|
||||
/// Get the consecutive direction. Returns:
|
||||
/// 0 - unknown or non-consecutive.
|
||||
@ -325,8 +324,7 @@ bool simplifyLoop(Loop *L, DominatorTree *DT, LoopInfo *LI, ScalarEvolution *SE,
|
||||
/// If ScalarEvolution is passed in, it will be preserved.
|
||||
///
|
||||
/// Returns true if any modifications are made to the loop.
|
||||
bool formLCSSA(Loop &L, DominatorTree &DT, LoopInfo *LI,
|
||||
ScalarEvolution *SE);
|
||||
bool formLCSSA(Loop &L, DominatorTree &DT, LoopInfo *LI, ScalarEvolution *SE);
|
||||
|
||||
/// \brief Put a loop nest into LCSSA form.
|
||||
///
|
||||
@ -370,8 +368,8 @@ bool hoistRegion(DomTreeNode *, AliasAnalysis *, LoopInfo *, DominatorTree *,
|
||||
/// insertion point vector, PredIteratorCache, LoopInfo, DominatorTree, Loop,
|
||||
/// AliasSet information for all instructions of the loop and loop safety
|
||||
/// information as arguments. It returns changed status.
|
||||
bool promoteLoopAccessesToScalars(AliasSet &, SmallVectorImpl<BasicBlock*> &,
|
||||
SmallVectorImpl<Instruction*> &,
|
||||
bool promoteLoopAccessesToScalars(AliasSet &, SmallVectorImpl<BasicBlock *> &,
|
||||
SmallVectorImpl<Instruction *> &,
|
||||
PredIteratorCache &, LoopInfo *,
|
||||
DominatorTree *, const TargetLibraryInfo *,
|
||||
Loop *, AliasSetTracker *, LICMSafetyInfo *);
|
||||
@ -394,7 +392,7 @@ Optional<const MDOperand *> findStringMetadataForLoop(Loop *TheLoop,
|
||||
StringRef Name);
|
||||
|
||||
/// \brief Set input string into loop metadata by keeping other values intact.
|
||||
void addStringMetadataToLoop(Loop *TheLoop, const char *MDString,
|
||||
void addStringMetadataToLoop(Loop *TheLoop, const char *MDString,
|
||||
unsigned V = 0);
|
||||
|
||||
/// Helper to consistently add the set of standard passes to a loop pass's \c
|
||||
@ -403,7 +401,6 @@ void addStringMetadataToLoop(Loop *TheLoop, const char *MDString,
|
||||
/// All loop passes should call this as part of implementing their \c
|
||||
/// getAnalysisUsage.
|
||||
void getLoopAnalysisUsage(AnalysisUsage &AU);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -30,7 +30,6 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/Transforms/Scalar.h"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/Analysis/AliasAnalysis.h"
|
||||
#include "llvm/Analysis/AliasSetTracker.h"
|
||||
@ -59,6 +58,7 @@
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Transforms/Scalar.h"
|
||||
#include "llvm/Transforms/Utils/Local.h"
|
||||
#include "llvm/Transforms/Utils/LoopUtils.h"
|
||||
#include "llvm/Transforms/Utils/SSAUpdater.h"
|
||||
@ -67,15 +67,15 @@ using namespace llvm;
|
||||
|
||||
#define DEBUG_TYPE "licm"
|
||||
|
||||
STATISTIC(NumSunk , "Number of instructions sunk out of loop");
|
||||
STATISTIC(NumHoisted , "Number of instructions hoisted out of loop");
|
||||
STATISTIC(NumSunk, "Number of instructions sunk out of loop");
|
||||
STATISTIC(NumHoisted, "Number of instructions hoisted out of loop");
|
||||
STATISTIC(NumMovedLoads, "Number of load insts hoisted or sunk");
|
||||
STATISTIC(NumMovedCalls, "Number of call insts hoisted or sunk");
|
||||
STATISTIC(NumPromoted , "Number of memory locations promoted to registers");
|
||||
STATISTIC(NumPromoted, "Number of memory locations promoted to registers");
|
||||
|
||||
static cl::opt<bool>
|
||||
DisablePromotion("disable-licm-promotion", cl::Hidden,
|
||||
cl::desc("Disable memory promotion in LICM pass"));
|
||||
DisablePromotion("disable-licm-promotion", cl::Hidden,
|
||||
cl::desc("Disable memory promotion in LICM pass"));
|
||||
|
||||
static bool inSubLoop(BasicBlock *BB, Loop *CurLoop, LoopInfo *LI);
|
||||
static bool isNotUsedInLoop(const Instruction &I, const Loop *CurLoop,
|
||||
@ -86,8 +86,7 @@ static bool sink(Instruction &I, const LoopInfo *LI, const DominatorTree *DT,
|
||||
const Loop *CurLoop, AliasSetTracker *CurAST,
|
||||
const LICMSafetyInfo *SafetyInfo);
|
||||
static bool isGuaranteedToExecute(const Instruction &Inst,
|
||||
const DominatorTree *DT,
|
||||
const Loop *CurLoop,
|
||||
const DominatorTree *DT, const Loop *CurLoop,
|
||||
const LICMSafetyInfo *SafetyInfo);
|
||||
static bool isSafeToExecuteUnconditionally(const Instruction &Inst,
|
||||
const DominatorTree *DT,
|
||||
@ -96,7 +95,7 @@ static bool isSafeToExecuteUnconditionally(const Instruction &Inst,
|
||||
const LICMSafetyInfo *SafetyInfo,
|
||||
const Instruction *CtxI = nullptr);
|
||||
static bool pointerInvalidatedByLoop(Value *V, uint64_t Size,
|
||||
const AAMDNodes &AAInfo,
|
||||
const AAMDNodes &AAInfo,
|
||||
AliasSetTracker *CurAST);
|
||||
static Instruction *
|
||||
CloneInstructionInExitBlock(Instruction &I, BasicBlock &ExitBlock, PHINode &PN,
|
||||
@ -108,57 +107,57 @@ static bool canSinkOrHoistInst(Instruction &I, AliasAnalysis *AA,
|
||||
LICMSafetyInfo *SafetyInfo);
|
||||
|
||||
namespace {
|
||||
struct LICM : public LoopPass {
|
||||
static char ID; // Pass identification, replacement for typeid
|
||||
LICM() : LoopPass(ID) {
|
||||
initializeLICMPass(*PassRegistry::getPassRegistry());
|
||||
}
|
||||
struct LICM : public LoopPass {
|
||||
static char ID; // Pass identification, replacement for typeid
|
||||
LICM() : LoopPass(ID) {
|
||||
initializeLICMPass(*PassRegistry::getPassRegistry());
|
||||
}
|
||||
|
||||
bool runOnLoop(Loop *L, LPPassManager &LPM) override;
|
||||
bool runOnLoop(Loop *L, LPPassManager &LPM) override;
|
||||
|
||||
/// This transformation requires natural loop information & requires that
|
||||
/// loop preheaders be inserted into the CFG...
|
||||
///
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
||||
AU.setPreservesCFG();
|
||||
AU.addRequired<TargetLibraryInfoWrapperPass>();
|
||||
getLoopAnalysisUsage(AU);
|
||||
}
|
||||
/// This transformation requires natural loop information & requires that
|
||||
/// loop preheaders be inserted into the CFG...
|
||||
///
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
||||
AU.setPreservesCFG();
|
||||
AU.addRequired<TargetLibraryInfoWrapperPass>();
|
||||
getLoopAnalysisUsage(AU);
|
||||
}
|
||||
|
||||
using llvm::Pass::doFinalization;
|
||||
using llvm::Pass::doFinalization;
|
||||
|
||||
bool doFinalization() override {
|
||||
assert(LoopToAliasSetMap.empty() && "Didn't free loop alias sets");
|
||||
return false;
|
||||
}
|
||||
bool doFinalization() override {
|
||||
assert(LoopToAliasSetMap.empty() && "Didn't free loop alias sets");
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
AliasAnalysis *AA; // Current AliasAnalysis information
|
||||
LoopInfo *LI; // Current LoopInfo
|
||||
DominatorTree *DT; // Dominator Tree for the current Loop.
|
||||
private:
|
||||
AliasAnalysis *AA; // Current AliasAnalysis information
|
||||
LoopInfo *LI; // Current LoopInfo
|
||||
DominatorTree *DT; // Dominator Tree for the current Loop.
|
||||
|
||||
TargetLibraryInfo *TLI; // TargetLibraryInfo for constant folding.
|
||||
TargetLibraryInfo *TLI; // TargetLibraryInfo for constant folding.
|
||||
|
||||
// State that is updated as we process loops.
|
||||
bool Changed; // Set to true when we change anything.
|
||||
BasicBlock *Preheader; // The preheader block of the current loop...
|
||||
Loop *CurLoop; // The current loop we are working on...
|
||||
AliasSetTracker *CurAST; // AliasSet information for the current loop...
|
||||
DenseMap<Loop*, AliasSetTracker*> LoopToAliasSetMap;
|
||||
// State that is updated as we process loops.
|
||||
bool Changed; // Set to true when we change anything.
|
||||
BasicBlock *Preheader; // The preheader block of the current loop...
|
||||
Loop *CurLoop; // The current loop we are working on...
|
||||
AliasSetTracker *CurAST; // AliasSet information for the current loop...
|
||||
DenseMap<Loop *, AliasSetTracker *> LoopToAliasSetMap;
|
||||
|
||||
/// cloneBasicBlockAnalysis - Simple Analysis hook. Clone alias set info.
|
||||
void cloneBasicBlockAnalysis(BasicBlock *From, BasicBlock *To,
|
||||
Loop *L) override;
|
||||
/// cloneBasicBlockAnalysis - Simple Analysis hook. Clone alias set info.
|
||||
void cloneBasicBlockAnalysis(BasicBlock *From, BasicBlock *To,
|
||||
Loop *L) override;
|
||||
|
||||
/// deleteAnalysisValue - Simple Analysis hook. Delete value V from alias
|
||||
/// set.
|
||||
void deleteAnalysisValue(Value *V, Loop *L) override;
|
||||
/// deleteAnalysisValue - Simple Analysis hook. Delete value V from alias
|
||||
/// set.
|
||||
void deleteAnalysisValue(Value *V, Loop *L) override;
|
||||
|
||||
/// Simple Analysis hook. Delete loop L from alias set map.
|
||||
void deleteAnalysisLoop(Loop *L) override;
|
||||
/// Simple Analysis hook. Delete loop L from alias set map.
|
||||
void deleteAnalysisLoop(Loop *L) override;
|
||||
|
||||
AliasSetTracker *collectAliasInfoForLoop(Loop *L);
|
||||
};
|
||||
AliasSetTracker *collectAliasInfoForLoop(Loop *L);
|
||||
};
|
||||
}
|
||||
|
||||
char LICM::ID = 0;
|
||||
@ -225,9 +224,9 @@ bool LICM::runOnLoop(Loop *L, LPPassManager &LPM) {
|
||||
|
||||
// Loop over all of the alias sets in the tracker object.
|
||||
for (AliasSet &AS : *CurAST)
|
||||
Changed |= promoteLoopAccessesToScalars(AS, ExitBlocks, InsertPts,
|
||||
PIC, LI, DT, TLI, CurLoop,
|
||||
CurAST, &SafetyInfo);
|
||||
Changed |=
|
||||
promoteLoopAccessesToScalars(AS, ExitBlocks, InsertPts, PIC, LI, DT,
|
||||
TLI, CurLoop, CurAST, &SafetyInfo);
|
||||
|
||||
// Once we have promoted values across the loop body we have to recursively
|
||||
// reform LCSSA as any nested loop may now have values defined within the
|
||||
@ -266,7 +265,7 @@ bool LICM::runOnLoop(Loop *L, LPPassManager &LPM) {
|
||||
}
|
||||
|
||||
/// Walk the specified region of the CFG (defined by all blocks dominated by
|
||||
/// the specified block, and that are in the current loop) in reverse depth
|
||||
/// the specified block, and that are in the current loop) in reverse depth
|
||||
/// first order w.r.t the DominatorTree. This allows us to visit uses before
|
||||
/// definitions, allowing us to sink a loop body in one pass without iteration.
|
||||
///
|
||||
@ -275,25 +274,27 @@ bool llvm::sinkRegion(DomTreeNode *N, AliasAnalysis *AA, LoopInfo *LI,
|
||||
AliasSetTracker *CurAST, LICMSafetyInfo *SafetyInfo) {
|
||||
|
||||
// Verify inputs.
|
||||
assert(N != nullptr && AA != nullptr && LI != nullptr &&
|
||||
DT != nullptr && CurLoop != nullptr && CurAST != nullptr &&
|
||||
SafetyInfo != nullptr && "Unexpected input to sinkRegion");
|
||||
assert(N != nullptr && AA != nullptr && LI != nullptr && DT != nullptr &&
|
||||
CurLoop != nullptr && CurAST != nullptr && SafetyInfo != nullptr &&
|
||||
"Unexpected input to sinkRegion");
|
||||
|
||||
BasicBlock *BB = N->getBlock();
|
||||
// If this subregion is not in the top level loop at all, exit.
|
||||
if (!CurLoop->contains(BB)) return false;
|
||||
if (!CurLoop->contains(BB))
|
||||
return false;
|
||||
|
||||
// We are processing blocks in reverse dfo, so process children first.
|
||||
bool Changed = false;
|
||||
const std::vector<DomTreeNode*> &Children = N->getChildren();
|
||||
const std::vector<DomTreeNode *> &Children = N->getChildren();
|
||||
for (DomTreeNode *Child : Children)
|
||||
Changed |= sinkRegion(Child, AA, LI, DT, TLI, CurLoop, CurAST, SafetyInfo);
|
||||
|
||||
// Only need to process the contents of this block if it is not part of a
|
||||
// subloop (which would already have been processed).
|
||||
if (inSubLoop(BB,CurLoop,LI)) return Changed;
|
||||
if (inSubLoop(BB, CurLoop, LI))
|
||||
return Changed;
|
||||
|
||||
for (BasicBlock::iterator II = BB->end(); II != BB->begin(); ) {
|
||||
for (BasicBlock::iterator II = BB->end(); II != BB->begin();) {
|
||||
Instruction &I = *--II;
|
||||
|
||||
// If the instruction is dead, we would try to sink it because it isn't used
|
||||
@ -330,20 +331,21 @@ bool llvm::hoistRegion(DomTreeNode *N, AliasAnalysis *AA, LoopInfo *LI,
|
||||
DominatorTree *DT, TargetLibraryInfo *TLI, Loop *CurLoop,
|
||||
AliasSetTracker *CurAST, LICMSafetyInfo *SafetyInfo) {
|
||||
// Verify inputs.
|
||||
assert(N != nullptr && AA != nullptr && LI != nullptr &&
|
||||
DT != nullptr && CurLoop != nullptr && CurAST != nullptr &&
|
||||
SafetyInfo != nullptr && "Unexpected input to hoistRegion");
|
||||
assert(N != nullptr && AA != nullptr && LI != nullptr && DT != nullptr &&
|
||||
CurLoop != nullptr && CurAST != nullptr && SafetyInfo != nullptr &&
|
||||
"Unexpected input to hoistRegion");
|
||||
|
||||
BasicBlock *BB = N->getBlock();
|
||||
|
||||
// If this subregion is not in the top level loop at all, exit.
|
||||
if (!CurLoop->contains(BB)) return false;
|
||||
if (!CurLoop->contains(BB))
|
||||
return false;
|
||||
|
||||
// Only need to process the contents of this block if it is not part of a
|
||||
// subloop (which would already have been processed).
|
||||
bool Changed = false;
|
||||
if (!inSubLoop(BB, CurLoop, LI))
|
||||
for (BasicBlock::iterator II = BB->begin(), E = BB->end(); II != E; ) {
|
||||
for (BasicBlock::iterator II = BB->begin(), E = BB->end(); II != E;) {
|
||||
Instruction &I = *II++;
|
||||
// Try constant folding this instruction. If all the operands are
|
||||
// constants, it is technically hoistable, but it would be better to just
|
||||
@ -364,12 +366,13 @@ bool llvm::hoistRegion(DomTreeNode *N, AliasAnalysis *AA, LoopInfo *LI,
|
||||
//
|
||||
if (CurLoop->hasLoopInvariantOperands(&I) &&
|
||||
canSinkOrHoistInst(I, AA, DT, TLI, CurLoop, CurAST, SafetyInfo) &&
|
||||
isSafeToExecuteUnconditionally(I, DT, TLI, CurLoop, SafetyInfo,
|
||||
CurLoop->getLoopPreheader()->getTerminator()))
|
||||
isSafeToExecuteUnconditionally(
|
||||
I, DT, TLI, CurLoop, SafetyInfo,
|
||||
CurLoop->getLoopPreheader()->getTerminator()))
|
||||
Changed |= hoist(I, DT, CurLoop, SafetyInfo);
|
||||
}
|
||||
|
||||
const std::vector<DomTreeNode*> &Children = N->getChildren();
|
||||
const std::vector<DomTreeNode *> &Children = N->getChildren();
|
||||
for (DomTreeNode *Child : Children)
|
||||
Changed |= hoistRegion(Child, AA, LI, DT, TLI, CurLoop, CurAST, SafetyInfo);
|
||||
return Changed;
|
||||
@ -378,7 +381,7 @@ bool llvm::hoistRegion(DomTreeNode *N, AliasAnalysis *AA, LoopInfo *LI,
|
||||
/// Computes loop safety information, checks loop body & header
|
||||
/// for the possibility of may throw exception.
|
||||
///
|
||||
void llvm::computeLICMSafetyInfo(LICMSafetyInfo * SafetyInfo, Loop * CurLoop) {
|
||||
void llvm::computeLICMSafetyInfo(LICMSafetyInfo *SafetyInfo, Loop *CurLoop) {
|
||||
assert(CurLoop != nullptr && "CurLoop cant be null");
|
||||
BasicBlock *Header = CurLoop->getHeader();
|
||||
// Setting default safety values.
|
||||
@ -388,11 +391,12 @@ void llvm::computeLICMSafetyInfo(LICMSafetyInfo * SafetyInfo, Loop * CurLoop) {
|
||||
for (BasicBlock::iterator I = Header->begin(), E = Header->end();
|
||||
(I != E) && !SafetyInfo->HeaderMayThrow; ++I)
|
||||
SafetyInfo->HeaderMayThrow |= I->mayThrow();
|
||||
|
||||
|
||||
SafetyInfo->MayThrow = SafetyInfo->HeaderMayThrow;
|
||||
// Iterate over loop instructions and compute safety info.
|
||||
for (Loop::block_iterator BB = CurLoop->block_begin(),
|
||||
BBE = CurLoop->block_end(); (BB != BBE) && !SafetyInfo->MayThrow ; ++BB)
|
||||
// Iterate over loop instructions and compute safety info.
|
||||
for (Loop::block_iterator BB = CurLoop->block_begin(),
|
||||
BBE = CurLoop->block_end();
|
||||
(BB != BBE) && !SafetyInfo->MayThrow; ++BB)
|
||||
for (BasicBlock::iterator I = (*BB)->begin(), E = (*BB)->end();
|
||||
(I != E) && !SafetyInfo->MayThrow; ++I)
|
||||
SafetyInfo->MayThrow |= I->mayThrow();
|
||||
@ -415,7 +419,7 @@ bool canSinkOrHoistInst(Instruction &I, AliasAnalysis *AA, DominatorTree *DT,
|
||||
// Loads have extra constraints we have to verify before we can hoist them.
|
||||
if (LoadInst *LI = dyn_cast<LoadInst>(&I)) {
|
||||
if (!LI->isUnordered())
|
||||
return false; // Don't hoist volatile/atomic loads!
|
||||
return false; // Don't hoist volatile/atomic loads!
|
||||
|
||||
// Loads from constant memory are always safe to move, even if they end up
|
||||
// in the same alias set as something that ends up being modified.
|
||||
@ -467,7 +471,8 @@ bool canSinkOrHoistInst(Instruction &I, AliasAnalysis *AA, DominatorTree *DT,
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!FoundMod) return true;
|
||||
if (!FoundMod)
|
||||
return true;
|
||||
}
|
||||
|
||||
// FIXME: This should use mod/ref information to see if we can hoist or
|
||||
@ -486,7 +491,7 @@ bool canSinkOrHoistInst(Instruction &I, AliasAnalysis *AA, DominatorTree *DT,
|
||||
|
||||
// TODO: Plumb the context instruction through to make hoisting and sinking
|
||||
// more powerful. Hoisting of loads already works due to the special casing
|
||||
// above.
|
||||
// above.
|
||||
return isSafeToExecuteUnconditionally(I, DT, TLI, CurLoop, SafetyInfo,
|
||||
nullptr);
|
||||
}
|
||||
@ -589,7 +594,8 @@ CloneInstructionInExitBlock(Instruction &I, BasicBlock &ExitBlock, PHINode &PN,
|
||||
}
|
||||
|
||||
ExitBlock.getInstList().insert(ExitBlock.getFirstInsertionPt(), New);
|
||||
if (!I.getName().empty()) New->setName(I.getName() + ".le");
|
||||
if (!I.getName().empty())
|
||||
New->setName(I.getName() + ".le");
|
||||
|
||||
// Build LCSSA PHI nodes for any in-loop operands. Note that this is
|
||||
// particularly cheap because we can rip off the PHI node that we're
|
||||
@ -623,15 +629,17 @@ static bool sink(Instruction &I, const LoopInfo *LI, const DominatorTree *DT,
|
||||
const LICMSafetyInfo *SafetyInfo) {
|
||||
DEBUG(dbgs() << "LICM sinking instruction: " << I << "\n");
|
||||
bool Changed = false;
|
||||
if (isa<LoadInst>(I)) ++NumMovedLoads;
|
||||
else if (isa<CallInst>(I)) ++NumMovedCalls;
|
||||
if (isa<LoadInst>(I))
|
||||
++NumMovedLoads;
|
||||
else if (isa<CallInst>(I))
|
||||
++NumMovedCalls;
|
||||
++NumSunk;
|
||||
Changed = true;
|
||||
|
||||
#ifndef NDEBUG
|
||||
SmallVector<BasicBlock *, 32> ExitBlocks;
|
||||
CurLoop->getUniqueExitBlocks(ExitBlocks);
|
||||
SmallPtrSet<BasicBlock *, 32> ExitBlockSet(ExitBlocks.begin(),
|
||||
SmallPtrSet<BasicBlock *, 32> ExitBlockSet(ExitBlocks.begin(),
|
||||
ExitBlocks.end());
|
||||
#endif
|
||||
|
||||
@ -688,8 +696,8 @@ static bool sink(Instruction &I, const LoopInfo *LI, const DominatorTree *DT,
|
||||
static bool hoist(Instruction &I, const DominatorTree *DT, const Loop *CurLoop,
|
||||
const LICMSafetyInfo *SafetyInfo) {
|
||||
auto *Preheader = CurLoop->getLoopPreheader();
|
||||
DEBUG(dbgs() << "LICM hoisting to " << Preheader->getName() << ": "
|
||||
<< I << "\n");
|
||||
DEBUG(dbgs() << "LICM hoisting to " << Preheader->getName() << ": " << I
|
||||
<< "\n");
|
||||
|
||||
// Metadata can be dependent on conditions we are hoisting above.
|
||||
// Conservatively strip all metadata on the instruction unless we were
|
||||
@ -705,8 +713,10 @@ static bool hoist(Instruction &I, const DominatorTree *DT, const Loop *CurLoop,
|
||||
// Move the new node to the Preheader, before its terminator.
|
||||
I.moveBefore(Preheader->getTerminator());
|
||||
|
||||
if (isa<LoadInst>(I)) ++NumMovedLoads;
|
||||
else if (isa<CallInst>(I)) ++NumMovedCalls;
|
||||
if (isa<LoadInst>(I))
|
||||
++NumMovedLoads;
|
||||
else if (isa<CallInst>(I))
|
||||
++NumMovedCalls;
|
||||
++NumHoisted;
|
||||
return true;
|
||||
}
|
||||
@ -714,7 +724,7 @@ static bool hoist(Instruction &I, const DominatorTree *DT, const Loop *CurLoop,
|
||||
/// Only sink or hoist an instruction if it is not a trapping instruction,
|
||||
/// or if the instruction is known not to trap when moved to the preheader.
|
||||
/// or if it is a trapping instruction and is guaranteed to execute.
|
||||
static bool isSafeToExecuteUnconditionally(const Instruction &Inst,
|
||||
static bool isSafeToExecuteUnconditionally(const Instruction &Inst,
|
||||
const DominatorTree *DT,
|
||||
const TargetLibraryInfo *TLI,
|
||||
const Loop *CurLoop,
|
||||
@ -727,9 +737,8 @@ static bool isSafeToExecuteUnconditionally(const Instruction &Inst,
|
||||
}
|
||||
|
||||
static bool isGuaranteedToExecute(const Instruction &Inst,
|
||||
const DominatorTree *DT,
|
||||
const Loop *CurLoop,
|
||||
const LICMSafetyInfo * SafetyInfo) {
|
||||
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
|
||||
@ -749,7 +758,7 @@ static bool isGuaranteedToExecute(const Instruction &Inst,
|
||||
return false;
|
||||
|
||||
// Get the exit blocks for the current loop.
|
||||
SmallVector<BasicBlock*, 8> ExitBlocks;
|
||||
SmallVector<BasicBlock *, 8> ExitBlocks;
|
||||
CurLoop->getExitBlocks(ExitBlocks);
|
||||
|
||||
// Verify that the block dominates each of the exit blocks of the loop.
|
||||
@ -766,82 +775,79 @@ static bool isGuaranteedToExecute(const Instruction &Inst,
|
||||
}
|
||||
|
||||
namespace {
|
||||
class LoopPromoter : public LoadAndStorePromoter {
|
||||
Value *SomePtr; // Designated pointer to store to.
|
||||
SmallPtrSetImpl<Value*> &PointerMustAliases;
|
||||
SmallVectorImpl<BasicBlock*> &LoopExitBlocks;
|
||||
SmallVectorImpl<Instruction*> &LoopInsertPts;
|
||||
PredIteratorCache &PredCache;
|
||||
AliasSetTracker &AST;
|
||||
LoopInfo &LI;
|
||||
DebugLoc DL;
|
||||
int Alignment;
|
||||
AAMDNodes AATags;
|
||||
class LoopPromoter : public LoadAndStorePromoter {
|
||||
Value *SomePtr; // Designated pointer to store to.
|
||||
SmallPtrSetImpl<Value *> &PointerMustAliases;
|
||||
SmallVectorImpl<BasicBlock *> &LoopExitBlocks;
|
||||
SmallVectorImpl<Instruction *> &LoopInsertPts;
|
||||
PredIteratorCache &PredCache;
|
||||
AliasSetTracker &AST;
|
||||
LoopInfo &LI;
|
||||
DebugLoc DL;
|
||||
int Alignment;
|
||||
AAMDNodes AATags;
|
||||
|
||||
Value *maybeInsertLCSSAPHI(Value *V, BasicBlock *BB) const {
|
||||
if (Instruction *I = dyn_cast<Instruction>(V))
|
||||
if (Loop *L = LI.getLoopFor(I->getParent()))
|
||||
if (!L->contains(BB)) {
|
||||
// We need to create an LCSSA PHI node for the incoming value and
|
||||
// store that.
|
||||
PHINode *PN =
|
||||
PHINode::Create(I->getType(), PredCache.size(BB),
|
||||
I->getName() + ".lcssa", &BB->front());
|
||||
for (BasicBlock *Pred : PredCache.get(BB))
|
||||
PN->addIncoming(I, Pred);
|
||||
return PN;
|
||||
}
|
||||
return V;
|
||||
}
|
||||
Value *maybeInsertLCSSAPHI(Value *V, BasicBlock *BB) const {
|
||||
if (Instruction *I = dyn_cast<Instruction>(V))
|
||||
if (Loop *L = LI.getLoopFor(I->getParent()))
|
||||
if (!L->contains(BB)) {
|
||||
// We need to create an LCSSA PHI node for the incoming value and
|
||||
// store that.
|
||||
PHINode *PN = PHINode::Create(I->getType(), PredCache.size(BB),
|
||||
I->getName() + ".lcssa", &BB->front());
|
||||
for (BasicBlock *Pred : PredCache.get(BB))
|
||||
PN->addIncoming(I, Pred);
|
||||
return PN;
|
||||
}
|
||||
return V;
|
||||
}
|
||||
|
||||
public:
|
||||
LoopPromoter(Value *SP,
|
||||
ArrayRef<const Instruction *> Insts,
|
||||
SSAUpdater &S, SmallPtrSetImpl<Value *> &PMA,
|
||||
SmallVectorImpl<BasicBlock *> &LEB,
|
||||
SmallVectorImpl<Instruction *> &LIP, PredIteratorCache &PIC,
|
||||
AliasSetTracker &ast, LoopInfo &li, DebugLoc dl, int alignment,
|
||||
const AAMDNodes &AATags)
|
||||
: LoadAndStorePromoter(Insts, S), SomePtr(SP), PointerMustAliases(PMA),
|
||||
LoopExitBlocks(LEB), LoopInsertPts(LIP), PredCache(PIC), AST(ast),
|
||||
LI(li), DL(dl), Alignment(alignment), AATags(AATags) {}
|
||||
public:
|
||||
LoopPromoter(Value *SP, ArrayRef<const Instruction *> Insts, SSAUpdater &S,
|
||||
SmallPtrSetImpl<Value *> &PMA,
|
||||
SmallVectorImpl<BasicBlock *> &LEB,
|
||||
SmallVectorImpl<Instruction *> &LIP, PredIteratorCache &PIC,
|
||||
AliasSetTracker &ast, LoopInfo &li, DebugLoc dl, int alignment,
|
||||
const AAMDNodes &AATags)
|
||||
: LoadAndStorePromoter(Insts, S), SomePtr(SP), PointerMustAliases(PMA),
|
||||
LoopExitBlocks(LEB), LoopInsertPts(LIP), PredCache(PIC), AST(ast),
|
||||
LI(li), DL(dl), Alignment(alignment), AATags(AATags) {}
|
||||
|
||||
bool isInstInList(Instruction *I,
|
||||
const SmallVectorImpl<Instruction*> &) const override {
|
||||
Value *Ptr;
|
||||
if (LoadInst *LI = dyn_cast<LoadInst>(I))
|
||||
Ptr = LI->getOperand(0);
|
||||
else
|
||||
Ptr = cast<StoreInst>(I)->getPointerOperand();
|
||||
return PointerMustAliases.count(Ptr);
|
||||
}
|
||||
bool isInstInList(Instruction *I,
|
||||
const SmallVectorImpl<Instruction *> &) const override {
|
||||
Value *Ptr;
|
||||
if (LoadInst *LI = dyn_cast<LoadInst>(I))
|
||||
Ptr = LI->getOperand(0);
|
||||
else
|
||||
Ptr = cast<StoreInst>(I)->getPointerOperand();
|
||||
return PointerMustAliases.count(Ptr);
|
||||
}
|
||||
|
||||
void doExtraRewritesBeforeFinalDeletion() const override {
|
||||
// Insert stores after in the loop exit blocks. Each exit block gets a
|
||||
// store of the live-out values that feed them. Since we've already told
|
||||
// the SSA updater about the defs in the loop and the preheader
|
||||
// definition, it is all set and we can start using it.
|
||||
for (unsigned i = 0, e = LoopExitBlocks.size(); i != e; ++i) {
|
||||
BasicBlock *ExitBlock = LoopExitBlocks[i];
|
||||
Value *LiveInValue = SSA.GetValueInMiddleOfBlock(ExitBlock);
|
||||
LiveInValue = maybeInsertLCSSAPHI(LiveInValue, ExitBlock);
|
||||
Value *Ptr = maybeInsertLCSSAPHI(SomePtr, ExitBlock);
|
||||
Instruction *InsertPos = LoopInsertPts[i];
|
||||
StoreInst *NewSI = new StoreInst(LiveInValue, Ptr, InsertPos);
|
||||
NewSI->setAlignment(Alignment);
|
||||
NewSI->setDebugLoc(DL);
|
||||
if (AATags) NewSI->setAAMetadata(AATags);
|
||||
}
|
||||
void doExtraRewritesBeforeFinalDeletion() const override {
|
||||
// Insert stores after in the loop exit blocks. Each exit block gets a
|
||||
// store of the live-out values that feed them. Since we've already told
|
||||
// the SSA updater about the defs in the loop and the preheader
|
||||
// definition, it is all set and we can start using it.
|
||||
for (unsigned i = 0, e = LoopExitBlocks.size(); i != e; ++i) {
|
||||
BasicBlock *ExitBlock = LoopExitBlocks[i];
|
||||
Value *LiveInValue = SSA.GetValueInMiddleOfBlock(ExitBlock);
|
||||
LiveInValue = maybeInsertLCSSAPHI(LiveInValue, ExitBlock);
|
||||
Value *Ptr = maybeInsertLCSSAPHI(SomePtr, ExitBlock);
|
||||
Instruction *InsertPos = LoopInsertPts[i];
|
||||
StoreInst *NewSI = new StoreInst(LiveInValue, Ptr, InsertPos);
|
||||
NewSI->setAlignment(Alignment);
|
||||
NewSI->setDebugLoc(DL);
|
||||
if (AATags)
|
||||
NewSI->setAAMetadata(AATags);
|
||||
}
|
||||
}
|
||||
|
||||
void replaceLoadWithValue(LoadInst *LI, Value *V) const override {
|
||||
// Update alias analysis.
|
||||
AST.copyValue(LI, V);
|
||||
}
|
||||
void instructionDeleted(Instruction *I) const override {
|
||||
AST.deleteValue(I);
|
||||
}
|
||||
};
|
||||
void replaceLoadWithValue(LoadInst *LI, Value *V) const override {
|
||||
// Update alias analysis.
|
||||
AST.copyValue(LI, V);
|
||||
}
|
||||
void instructionDeleted(Instruction *I) const override { AST.deleteValue(I); }
|
||||
};
|
||||
} // end anon namespace
|
||||
|
||||
/// Try to promote memory values to scalars by sinking stores out of the
|
||||
@ -849,19 +855,14 @@ namespace {
|
||||
/// the stores in the loop, looking for stores to Must pointers which are
|
||||
/// loop invariant.
|
||||
///
|
||||
bool llvm::promoteLoopAccessesToScalars(AliasSet &AS,
|
||||
SmallVectorImpl<BasicBlock*>&ExitBlocks,
|
||||
SmallVectorImpl<Instruction*>&InsertPts,
|
||||
PredIteratorCache &PIC, LoopInfo *LI,
|
||||
DominatorTree *DT,
|
||||
const TargetLibraryInfo *TLI,
|
||||
Loop *CurLoop,
|
||||
AliasSetTracker *CurAST,
|
||||
LICMSafetyInfo * SafetyInfo) {
|
||||
bool llvm::promoteLoopAccessesToScalars(
|
||||
AliasSet &AS, SmallVectorImpl<BasicBlock *> &ExitBlocks,
|
||||
SmallVectorImpl<Instruction *> &InsertPts, PredIteratorCache &PIC,
|
||||
LoopInfo *LI, DominatorTree *DT, const TargetLibraryInfo *TLI,
|
||||
Loop *CurLoop, AliasSetTracker *CurAST, LICMSafetyInfo *SafetyInfo) {
|
||||
// Verify inputs.
|
||||
assert(LI != nullptr && DT != nullptr &&
|
||||
CurLoop != nullptr && CurAST != nullptr &&
|
||||
SafetyInfo != nullptr &&
|
||||
assert(LI != nullptr && DT != nullptr && CurLoop != nullptr &&
|
||||
CurAST != nullptr && SafetyInfo != nullptr &&
|
||||
"Unexpected Input to promoteLoopAccessesToScalars");
|
||||
|
||||
// We can promote this alias set if it has a store, if it is a "Must" alias
|
||||
@ -875,7 +876,7 @@ bool llvm::promoteLoopAccessesToScalars(AliasSet &AS,
|
||||
"Must alias set should have at least one pointer element in it!");
|
||||
|
||||
Value *SomePtr = AS.begin()->getValue();
|
||||
BasicBlock * Preheader = CurLoop->getLoopPreheader();
|
||||
BasicBlock *Preheader = CurLoop->getLoopPreheader();
|
||||
|
||||
// It isn't safe to promote a load/store from the loop if the load/store is
|
||||
// conditional. For example, turning:
|
||||
@ -907,8 +908,8 @@ bool llvm::promoteLoopAccessesToScalars(AliasSet &AS,
|
||||
// since they're all must alias.
|
||||
bool CanSpeculateLoad = false;
|
||||
|
||||
SmallVector<Instruction*, 64> LoopUses;
|
||||
SmallPtrSet<Value*, 4> PointerMustAliases;
|
||||
SmallVector<Instruction *, 64> LoopUses;
|
||||
SmallPtrSet<Value *, 4> PointerMustAliases;
|
||||
|
||||
// We start with an alignment of one and try to find instructions that allow
|
||||
// us to prove better alignment.
|
||||
@ -923,7 +924,7 @@ bool llvm::promoteLoopAccessesToScalars(AliasSet &AS,
|
||||
// is available.
|
||||
if (!HasDedicatedExits || !Preheader)
|
||||
return false;
|
||||
|
||||
|
||||
const DataLayout &MDL = Preheader->getModule()->getDataLayout();
|
||||
|
||||
// Check that all of the pointers in the alias set have the same type. We
|
||||
@ -954,10 +955,8 @@ bool llvm::promoteLoopAccessesToScalars(AliasSet &AS,
|
||||
return Changed;
|
||||
|
||||
if (!GuaranteedToExecute && !CanSpeculateLoad)
|
||||
CanSpeculateLoad =
|
||||
isSafeToExecuteUnconditionally(*Load, DT, TLI, CurLoop,
|
||||
SafetyInfo,
|
||||
Preheader->getTerminator());
|
||||
CanSpeculateLoad = isSafeToExecuteUnconditionally(
|
||||
*Load, DT, TLI, CurLoop, SafetyInfo, Preheader->getTerminator());
|
||||
} else if (const StoreInst *Store = dyn_cast<StoreInst>(UI)) {
|
||||
// Stores *of* the pointer are not interesting, only stores *to* the
|
||||
// pointer.
|
||||
@ -983,16 +982,13 @@ bool llvm::promoteLoopAccessesToScalars(AliasSet &AS,
|
||||
}
|
||||
|
||||
if (!GuaranteedToExecute)
|
||||
GuaranteedToExecute = isGuaranteedToExecute(*UI, DT,
|
||||
CurLoop, SafetyInfo);
|
||||
|
||||
GuaranteedToExecute =
|
||||
isGuaranteedToExecute(*UI, DT, CurLoop, SafetyInfo);
|
||||
|
||||
if (!GuaranteedToExecute && !CanSpeculateLoad) {
|
||||
CanSpeculateLoad =
|
||||
isDereferenceableAndAlignedPointer(Store->getPointerOperand(),
|
||||
Store->getAlignment(), MDL,
|
||||
Preheader->getTerminator(),
|
||||
DT, TLI);
|
||||
CanSpeculateLoad = isDereferenceableAndAlignedPointer(
|
||||
Store->getPointerOperand(), Store->getAlignment(), MDL,
|
||||
Preheader->getTerminator(), DT, TLI);
|
||||
}
|
||||
} else
|
||||
return Changed; // Not a load or store.
|
||||
@ -1014,10 +1010,10 @@ bool llvm::promoteLoopAccessesToScalars(AliasSet &AS,
|
||||
if (!PromotionIsLegal && CanSpeculateLoad) {
|
||||
// If this is a thread local location, then we can insert stores along
|
||||
// paths which originally didn't have them without violating the memory
|
||||
// model.
|
||||
// model.
|
||||
Value *Object = GetUnderlyingObject(SomePtr, MDL);
|
||||
PromotionIsLegal = isAllocLikeFn(Object, TLI) &&
|
||||
!PointerMayBeCaptured(Object, true, true);
|
||||
PromotionIsLegal =
|
||||
isAllocLikeFn(Object, TLI) && !PointerMayBeCaptured(Object, true, true);
|
||||
}
|
||||
if (!PromotionIsLegal)
|
||||
return Changed;
|
||||
@ -1038,7 +1034,8 @@ bool llvm::promoteLoopAccessesToScalars(AliasSet &AS,
|
||||
return Changed;
|
||||
|
||||
// Otherwise, this is safe to promote, lets do it!
|
||||
DEBUG(dbgs() << "LICM: Promoting value stored to in loop: " <<*SomePtr<<'\n');
|
||||
DEBUG(dbgs() << "LICM: Promoting value stored to in loop: " << *SomePtr
|
||||
<< '\n');
|
||||
Changed = true;
|
||||
++NumPromoted;
|
||||
|
||||
@ -1049,20 +1046,19 @@ bool llvm::promoteLoopAccessesToScalars(AliasSet &AS,
|
||||
DebugLoc DL = LoopUses[0]->getDebugLoc();
|
||||
|
||||
// We use the SSAUpdater interface to insert phi nodes as required.
|
||||
SmallVector<PHINode*, 16> NewPHIs;
|
||||
SmallVector<PHINode *, 16> NewPHIs;
|
||||
SSAUpdater SSA(&NewPHIs);
|
||||
LoopPromoter Promoter(SomePtr, LoopUses, SSA,
|
||||
PointerMustAliases, ExitBlocks,
|
||||
LoopPromoter Promoter(SomePtr, LoopUses, SSA, PointerMustAliases, ExitBlocks,
|
||||
InsertPts, PIC, *CurAST, *LI, DL, Alignment, AATags);
|
||||
|
||||
// Set up the preheader to have a definition of the value. It is the live-out
|
||||
// value from the preheader that uses in the loop will use.
|
||||
LoadInst *PreheaderLoad =
|
||||
new LoadInst(SomePtr, SomePtr->getName()+".promoted",
|
||||
Preheader->getTerminator());
|
||||
LoadInst *PreheaderLoad = new LoadInst(
|
||||
SomePtr, SomePtr->getName() + ".promoted", Preheader->getTerminator());
|
||||
PreheaderLoad->setAlignment(Alignment);
|
||||
PreheaderLoad->setDebugLoc(DL);
|
||||
if (AATags) PreheaderLoad->setAAMetadata(AATags);
|
||||
if (AATags)
|
||||
PreheaderLoad->setAAMetadata(AATags);
|
||||
SSA.AddAvailableValue(Preheader, PreheaderLoad);
|
||||
|
||||
// Rewrite all the loads in the loop and remember all the definitions from
|
||||
@ -1157,12 +1153,11 @@ void LICM::deleteAnalysisLoop(Loop *L) {
|
||||
LoopToAliasSetMap.erase(L);
|
||||
}
|
||||
|
||||
|
||||
/// Return true if the body of this loop may store into the memory
|
||||
/// location pointed to by V.
|
||||
///
|
||||
static bool pointerInvalidatedByLoop(Value *V, uint64_t Size,
|
||||
const AAMDNodes &AAInfo,
|
||||
const AAMDNodes &AAInfo,
|
||||
AliasSetTracker *CurAST) {
|
||||
// Check to see if any of the basic blocks in CurLoop invalidate *V.
|
||||
return CurAST->getAliasSetForPointer(V, Size, AAInfo).isMod();
|
||||
@ -1175,4 +1170,3 @@ static bool inSubLoop(BasicBlock *BB, Loop *CurLoop, LoopInfo *LI) {
|
||||
assert(CurLoop->contains(BB) && "Only valid if BB is IN the loop");
|
||||
return LI->getLoopFor(BB) != CurLoop;
|
||||
}
|
||||
|
||||
|
@ -12,11 +12,10 @@
|
||||
// counts of loops easily.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/Transforms/Scalar.h"
|
||||
#include "llvm/ADT/SetVector.h"
|
||||
#include "llvm/Analysis/GlobalsModRef.h"
|
||||
#include "llvm/Analysis/AssumptionCache.h"
|
||||
#include "llvm/Analysis/CodeMetrics.h"
|
||||
#include "llvm/Analysis/GlobalsModRef.h"
|
||||
#include "llvm/Analysis/InstructionSimplify.h"
|
||||
#include "llvm/Analysis/LoopPass.h"
|
||||
#include "llvm/Analysis/LoopUnrollAnalyzer.h"
|
||||
@ -32,6 +31,7 @@
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Transforms/Scalar.h"
|
||||
#include "llvm/Transforms/Utils/LoopUtils.h"
|
||||
#include "llvm/Transforms/Utils/UnrollLoop.h"
|
||||
#include <climits>
|
||||
@ -60,34 +60,34 @@ static cl::opt<unsigned> UnrollMaxIterationsCountToAnalyze(
|
||||
cl::desc("Don't allow loop unrolling to simulate more than this number of"
|
||||
"iterations when checking full unroll profitability"));
|
||||
|
||||
static cl::opt<unsigned>
|
||||
UnrollCount("unroll-count", cl::Hidden,
|
||||
cl::desc("Use this unroll count for all loops including those with "
|
||||
"unroll_count pragma values, for testing purposes"));
|
||||
static cl::opt<unsigned> UnrollCount(
|
||||
"unroll-count", cl::Hidden,
|
||||
cl::desc("Use this unroll count for all loops including those with "
|
||||
"unroll_count pragma values, for testing purposes"));
|
||||
|
||||
static cl::opt<unsigned>
|
||||
UnrollMaxCount("unroll-max-count", cl::Hidden,
|
||||
cl::desc("Set the max unroll count for partial and runtime unrolling, for"
|
||||
"testing purposes"));
|
||||
static cl::opt<unsigned> UnrollMaxCount(
|
||||
"unroll-max-count", cl::Hidden,
|
||||
cl::desc("Set the max unroll count for partial and runtime unrolling, for"
|
||||
"testing purposes"));
|
||||
|
||||
static cl::opt<unsigned>
|
||||
UnrollFullMaxCount("unroll-full-max-count", cl::Hidden,
|
||||
cl::desc("Set the max unroll count for full unrolling, for testing purposes"));
|
||||
static cl::opt<unsigned> UnrollFullMaxCount(
|
||||
"unroll-full-max-count", cl::Hidden,
|
||||
cl::desc(
|
||||
"Set the max unroll count for full unrolling, for testing purposes"));
|
||||
|
||||
static cl::opt<bool>
|
||||
UnrollAllowPartial("unroll-allow-partial", cl::Hidden,
|
||||
cl::desc("Allows loops to be partially unrolled until "
|
||||
"-unroll-threshold loop size is reached."));
|
||||
UnrollAllowPartial("unroll-allow-partial", cl::Hidden,
|
||||
cl::desc("Allows loops to be partially unrolled until "
|
||||
"-unroll-threshold loop size is reached."));
|
||||
|
||||
static cl::opt<bool>
|
||||
UnrollRuntime("unroll-runtime", cl::ZeroOrMore, cl::Hidden,
|
||||
cl::desc("Unroll loops with run-time trip counts"));
|
||||
|
||||
static cl::opt<unsigned>
|
||||
PragmaUnrollThreshold("pragma-unroll-threshold", cl::init(16 * 1024), cl::Hidden,
|
||||
cl::desc("Unrolled size limit for loops with an unroll(full) or "
|
||||
"unroll_count pragma."));
|
||||
UnrollRuntime("unroll-runtime", cl::ZeroOrMore, cl::Hidden,
|
||||
cl::desc("Unroll loops with run-time trip counts"));
|
||||
|
||||
static cl::opt<unsigned> PragmaUnrollThreshold(
|
||||
"pragma-unroll-threshold", cl::init(16 * 1024), cl::Hidden,
|
||||
cl::desc("Unrolled size limit for loops with an unroll(full) or "
|
||||
"unroll_count pragma."));
|
||||
|
||||
/// A magic value for use with the Threshold parameter to indicate
|
||||
/// that the loop unroll should be performed regardless of how much
|
||||
@ -453,7 +453,8 @@ static unsigned UnrollCountPragmaValue(const Loop *L) {
|
||||
// unrolling pass is run more than once (which it generally is).
|
||||
static void SetLoopAlreadyUnrolled(Loop *L) {
|
||||
MDNode *LoopID = L->getLoopID();
|
||||
if (!LoopID) return;
|
||||
if (!LoopID)
|
||||
return;
|
||||
|
||||
// First remove any existing loop unrolling metadata.
|
||||
SmallVector<Metadata *, 4> MDs;
|
||||
@ -514,9 +515,9 @@ static bool canUnrollCompletely(Loop *L, unsigned Threshold,
|
||||
(int64_t)UnrolledCost - (int64_t)DynamicCostSavingsDiscount <=
|
||||
(int64_t)Threshold) {
|
||||
DEBUG(dbgs() << " Can fully unroll, because unrolling will reduce the "
|
||||
"expected dynamic cost by " << PercentDynamicCostSaved
|
||||
<< "% (threshold: " << PercentDynamicCostSavedThreshold
|
||||
<< "%)\n"
|
||||
"expected dynamic cost by "
|
||||
<< PercentDynamicCostSaved << "% (threshold: "
|
||||
<< PercentDynamicCostSavedThreshold << "%)\n"
|
||||
<< " and the unrolled cost (" << UnrolledCost
|
||||
<< ") is less than the max threshold ("
|
||||
<< DynamicCostSavingsDiscount << ").\n");
|
||||
@ -544,7 +545,7 @@ static bool tryToUnrollLoop(Loop *L, DominatorTree &DT, LoopInfo *LI,
|
||||
Optional<bool> ProvidedRuntime) {
|
||||
BasicBlock *Header = L->getHeader();
|
||||
DEBUG(dbgs() << "Loop Unroll: F[" << Header->getParent()->getName()
|
||||
<< "] Loop %" << Header->getName() << "\n");
|
||||
<< "] Loop %" << Header->getName() << "\n");
|
||||
|
||||
if (HasUnrollDisablePragma(L)) {
|
||||
return false;
|
||||
@ -592,7 +593,7 @@ static bool tryToUnrollLoop(Loop *L, DominatorTree &DT, LoopInfo *LI,
|
||||
// When computing the unrolled size, note that the conditional branch on the
|
||||
// backedge and the comparison feeding it are not replicated like the rest of
|
||||
// the loop body (which is why 2 is subtracted).
|
||||
uint64_t UnrolledSize = (uint64_t)(LoopSize-2) * Count + 2;
|
||||
uint64_t UnrolledSize = (uint64_t)(LoopSize - 2) * Count + 2;
|
||||
if (NotDuplicatable) {
|
||||
DEBUG(dbgs() << " Not unrolling loop which contains non-duplicatable"
|
||||
<< " instructions.\n");
|
||||
@ -680,7 +681,7 @@ static bool tryToUnrollLoop(Loop *L, DominatorTree &DT, LoopInfo *LI,
|
||||
// the original count which satisfies the threshold limit.
|
||||
while (Count != 0 && UnrolledSize > UP.PartialThreshold) {
|
||||
Count >>= 1;
|
||||
UnrolledSize = (LoopSize-2) * Count + 2;
|
||||
UnrolledSize = (LoopSize - 2) * Count + 2;
|
||||
}
|
||||
|
||||
if (Count > UP.MaxCount)
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user