diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2014-11-24 09:08:18 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2014-11-24 09:08:18 +0000 |
| commit | 5ca98fd98791947eba83a1ed3f2c8191ef7afa6c (patch) | |
| tree | f5944309621cee4fe0976be6f9ac619b7ebfc4c2 /lib/Analysis/IPA | |
| parent | 68bcb7db193e4bc81430063148253d30a791023e (diff) | |
Notes
Diffstat (limited to 'lib/Analysis/IPA')
| -rw-r--r-- | lib/Analysis/IPA/CallGraph.cpp | 161 | ||||
| -rw-r--r-- | lib/Analysis/IPA/CallGraphSCCPass.cpp | 65 | ||||
| -rw-r--r-- | lib/Analysis/IPA/CallPrinter.cpp | 45 | ||||
| -rw-r--r-- | lib/Analysis/IPA/FindUsedTypes.cpp | 3 | ||||
| -rw-r--r-- | lib/Analysis/IPA/GlobalsModRef.cpp | 108 | ||||
| -rw-r--r-- | lib/Analysis/IPA/IPA.cpp | 4 | ||||
| -rw-r--r-- | lib/Analysis/IPA/InlineCost.cpp | 168 |
7 files changed, 307 insertions, 247 deletions
diff --git a/lib/Analysis/IPA/CallGraph.cpp b/lib/Analysis/IPA/CallGraph.cpp index f042964c21d9..dfabb0ad063d 100644 --- a/lib/Analysis/IPA/CallGraph.cpp +++ b/lib/Analysis/IPA/CallGraph.cpp @@ -8,17 +8,45 @@ //===----------------------------------------------------------------------===// #include "llvm/Analysis/CallGraph.h" +#include "llvm/IR/CallSite.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Module.h" -#include "llvm/Support/CallSite.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; -CallGraph::CallGraph() - : ModulePass(ID), Root(0), ExternalCallingNode(0), CallsExternalNode(0) { - initializeCallGraphPass(*PassRegistry::getPassRegistry()); +//===----------------------------------------------------------------------===// +// Implementations of the CallGraph class methods. +// + +CallGraph::CallGraph(Module &M) + : M(M), Root(nullptr), ExternalCallingNode(getOrInsertFunction(nullptr)), + CallsExternalNode(new CallGraphNode(nullptr)) { + // Add every function to the call graph. + for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) + addToCallGraph(I); + + // If we didn't find a main function, use the external call graph node + if (!Root) + Root = ExternalCallingNode; +} + +CallGraph::~CallGraph() { + // CallsExternalNode is not in the function map, delete it explicitly. + CallsExternalNode->allReferencesDropped(); + delete CallsExternalNode; + +// Reset all node's use counts to zero before deleting them to prevent an +// assertion from firing. +#ifndef NDEBUG + for (FunctionMapTy::iterator I = FunctionMap.begin(), E = FunctionMap.end(); + I != E; ++I) + I->second->allReferencesDropped(); +#endif + for (FunctionMapTy::iterator I = FunctionMap.begin(), E = FunctionMap.end(); + I != E; ++I) + delete I->second; } void CallGraph::addToCallGraph(Function *F) { @@ -62,59 +90,7 @@ void CallGraph::addToCallGraph(Function *F) { } } -void CallGraph::getAnalysisUsage(AnalysisUsage &AU) const { - AU.setPreservesAll(); -} - -bool CallGraph::runOnModule(Module &M) { - Mod = &M; - - ExternalCallingNode = getOrInsertFunction(0); - assert(!CallsExternalNode); - CallsExternalNode = new CallGraphNode(0); - Root = 0; - - // Add every function to the call graph. - for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) - addToCallGraph(I); - - // If we didn't find a main function, use the external call graph node - if (Root == 0) - Root = ExternalCallingNode; - - return false; -} - -INITIALIZE_PASS(CallGraph, "basiccg", "CallGraph Construction", false, true) - -char CallGraph::ID = 0; - -void CallGraph::releaseMemory() { - /// CallsExternalNode is not in the function map, delete it explicitly. - if (CallsExternalNode) { - CallsExternalNode->allReferencesDropped(); - delete CallsExternalNode; - CallsExternalNode = 0; - } - - if (FunctionMap.empty()) - return; - -// Reset all node's use counts to zero before deleting them to prevent an -// assertion from firing. -#ifndef NDEBUG - for (FunctionMapTy::iterator I = FunctionMap.begin(), E = FunctionMap.end(); - I != E; ++I) - I->second->allReferencesDropped(); -#endif - - for (FunctionMapTy::iterator I = FunctionMap.begin(), E = FunctionMap.end(); - I != E; ++I) - delete I->second; - FunctionMap.clear(); -} - -void CallGraph::print(raw_ostream &OS, const Module*) const { +void CallGraph::print(raw_ostream &OS) const { OS << "CallGraph Root is: "; if (Function *F = Root->getFunction()) OS << F->getName() << "\n"; @@ -125,16 +101,11 @@ void CallGraph::print(raw_ostream &OS, const Module*) const { for (CallGraph::const_iterator I = begin(), E = end(); I != E; ++I) I->second->print(OS); } + #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) -void CallGraph::dump() const { - print(dbgs(), 0); -} +void CallGraph::dump() const { print(dbgs()); } #endif -//===----------------------------------------------------------------------===// -// Implementations of public modification methods -// - // removeFunctionFromModule - Unlink the function from this module, returning // it. Because this removes the function from the module, the call graph node // is destroyed. This is only valid if the function does not call any other @@ -148,7 +119,7 @@ Function *CallGraph::removeFunctionFromModule(CallGraphNode *CGN) { delete CGN; // Delete the call graph node for this func FunctionMap.erase(F); // Remove the call graph node from the map - Mod->getFunctionList().remove(F); + M.getFunctionList().remove(F); return F; } @@ -172,12 +143,17 @@ void CallGraph::spliceFunction(const Function *From, const Function *To) { // not already exist. CallGraphNode *CallGraph::getOrInsertFunction(const Function *F) { CallGraphNode *&CGN = FunctionMap[F]; - if (CGN) return CGN; - - assert((!F || F->getParent() == Mod) && "Function not in current module!"); + if (CGN) + return CGN; + + assert((!F || F->getParent() == &M) && "Function not in current module!"); return CGN = new CallGraphNode(const_cast<Function*>(F)); } +//===----------------------------------------------------------------------===// +// Implementations of the CallGraphNode class methods. +// + void CallGraphNode::print(raw_ostream &OS) const { if (Function *F = getFunction()) OS << "Call graph node for function: '" << F->getName() << "'"; @@ -234,7 +210,7 @@ void CallGraphNode::removeOneAbstractEdgeTo(CallGraphNode *Callee) { for (CalledFunctionsVector::iterator I = CalledFunctions.begin(); ; ++I) { assert(I != CalledFunctions.end() && "Cannot find callee to remove!"); CallRecord &CR = *I; - if (CR.second == Callee && CR.first == 0) { + if (CR.second == Callee && CR.first == nullptr) { Callee->DropRef(); *I = CalledFunctions.back(); CalledFunctions.pop_back(); @@ -260,5 +236,52 @@ void CallGraphNode::replaceCallEdge(CallSite CS, } } +//===----------------------------------------------------------------------===// +// Out-of-line definitions of CallGraphAnalysis class members. +// + +char CallGraphAnalysis::PassID; + +//===----------------------------------------------------------------------===// +// Implementations of the CallGraphWrapperPass class methods. +// + +CallGraphWrapperPass::CallGraphWrapperPass() : ModulePass(ID) { + initializeCallGraphWrapperPassPass(*PassRegistry::getPassRegistry()); +} + +CallGraphWrapperPass::~CallGraphWrapperPass() {} + +void CallGraphWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); +} + +bool CallGraphWrapperPass::runOnModule(Module &M) { + // All the real work is done in the constructor for the CallGraph. + G.reset(new CallGraph(M)); + return false; +} + +INITIALIZE_PASS(CallGraphWrapperPass, "basiccg", "CallGraph Construction", + false, true) + +char CallGraphWrapperPass::ID = 0; + +void CallGraphWrapperPass::releaseMemory() { G.reset(); } + +void CallGraphWrapperPass::print(raw_ostream &OS, const Module *) const { + if (!G) { + OS << "No call graph has been built!\n"; + return; + } + + // Just delegate. + G->print(OS); +} + +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) +void CallGraphWrapperPass::dump() const { print(dbgs(), nullptr); } +#endif + // Enuse that users of CallGraph.h also link with this file DEFINING_FILE_FOR(CallGraph) diff --git a/lib/Analysis/IPA/CallGraphSCCPass.cpp b/lib/Analysis/IPA/CallGraphSCCPass.cpp index 182beca3643e..c27edbfa2ff5 100644 --- a/lib/Analysis/IPA/CallGraphSCCPass.cpp +++ b/lib/Analysis/IPA/CallGraphSCCPass.cpp @@ -15,7 +15,6 @@ // //===----------------------------------------------------------------------===// -#define DEBUG_TYPE "cgscc-passmgr" #include "llvm/Analysis/CallGraphSCCPass.h" #include "llvm/ADT/SCCIterator.h" #include "llvm/ADT/Statistic.h" @@ -23,12 +22,15 @@ #include "llvm/IR/Function.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/LegacyPassManagers.h" +#include "llvm/IR/LLVMContext.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Timer.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; +#define DEBUG_TYPE "cgscc-passmgr" + static cl::opt<unsigned> MaxIterations("max-cg-scc-iterations", cl::ReallyHidden, cl::init(4)); @@ -49,7 +51,7 @@ public: /// run - Execute all of the passes scheduled for execution. Keep track of /// whether any of the passes modifies the module, and if so, return true. - bool runOnModule(Module &M); + bool runOnModule(Module &M) override; using ModulePass::doInitialization; using ModulePass::doFinalization; @@ -58,21 +60,21 @@ public: bool doFinalization(CallGraph &CG); /// Pass Manager itself does not invalidate any analysis info. - void getAnalysisUsage(AnalysisUsage &Info) const { + void getAnalysisUsage(AnalysisUsage &Info) const override { // CGPassManager walks SCC and it needs CallGraph. - Info.addRequired<CallGraph>(); + Info.addRequired<CallGraphWrapperPass>(); Info.setPreservesAll(); } - virtual const char *getPassName() const { + const char *getPassName() const override { return "CallGraph Pass Manager"; } - virtual PMDataManager *getAsPMDataManager() { return this; } - virtual Pass *getAsPass() { return this; } + PMDataManager *getAsPMDataManager() override { return this; } + Pass *getAsPass() override { return this; } // Print passes managed by this manager - void dumpPassStructure(unsigned Offset) { + void dumpPassStructure(unsigned Offset) override { errs().indent(Offset*2) << "Call Graph SCC Pass Manager\n"; for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { Pass *P = getContainedPass(Index); @@ -86,7 +88,7 @@ public: return static_cast<Pass *>(PassVector[N]); } - virtual PassManagerType getPassManagerType() const { + PassManagerType getPassManagerType() const override { return PMT_CallGraphPassManager; } @@ -112,7 +114,7 @@ bool CGPassManager::RunPassOnSCC(Pass *P, CallGraphSCC &CurSCC, bool Changed = false; PMDataManager *PM = P->getAsPMDataManager(); - if (PM == 0) { + if (!PM) { CallGraphSCCPass *CGSP = (CallGraphSCCPass*)P; if (!CallGraphUpToDate) { DevirtualizedCall |= RefreshCallGraph(CurSCC, CG, false); @@ -144,8 +146,11 @@ bool CGPassManager::RunPassOnSCC(Pass *P, CallGraphSCC &CurSCC, I != E; ++I) { if (Function *F = (*I)->getFunction()) { dumpPassInfo(P, EXECUTION_MSG, ON_FUNCTION_MSG, F->getName()); - TimeRegion PassTimer(getPassTimer(FPP)); - Changed |= FPP->runOnFunction(*F); + { + TimeRegion PassTimer(getPassTimer(FPP)); + Changed |= FPP->runOnFunction(*F); + } + F->getContext().yield(); } } @@ -190,7 +195,7 @@ bool CGPassManager::RefreshCallGraph(CallGraphSCC &CurSCC, SCCIdx != E; ++SCCIdx, ++FunctionNo) { CallGraphNode *CGN = *SCCIdx; Function *F = CGN->getFunction(); - if (F == 0 || F->isDeclaration()) continue; + if (!F || F->isDeclaration()) continue; // Walk the function body looking for call sites. Sync up the call sites in // CGN with those actually in the function. @@ -203,7 +208,7 @@ bool CGPassManager::RefreshCallGraph(CallGraphSCC &CurSCC, for (CallGraphNode::iterator I = CGN->begin(), E = CGN->end(); I != E; ) { // If this call site is null, then the function pass deleted the call // entirely and the WeakVH nulled it out. - if (I->first == 0 || + if (!I->first || // If we've already seen this call site, then the FunctionPass RAUW'd // one call with another, which resulted in two "uses" in the edge // list of the same call. @@ -217,7 +222,7 @@ bool CGPassManager::RefreshCallGraph(CallGraphSCC &CurSCC, "CallGraphSCCPass did not update the CallGraph correctly!"); // If this was an indirect call site, count it. - if (I->second->getFunction() == 0) + if (!I->second->getFunction()) ++NumIndirectRemoved; else ++NumDirectRemoved; @@ -273,7 +278,7 @@ bool CGPassManager::RefreshCallGraph(CallGraphSCC &CurSCC, // site could be turned direct), don't reject it in checking mode, and // don't tweak it to be more precise. if (CheckingMode && CS.getCalledFunction() && - ExistingNode->getFunction() == 0) + ExistingNode->getFunction() == nullptr) continue; assert(!CheckingMode && @@ -286,7 +291,7 @@ bool CGPassManager::RefreshCallGraph(CallGraphSCC &CurSCC, CalleeNode = CG.getOrInsertFunction(Callee); // Keep track of whether we turned an indirect call into a direct // one. - if (ExistingNode->getFunction() == 0) { + if (!ExistingNode->getFunction()) { DevirtualizedCall = true; DEBUG(dbgs() << " CGSCCPASSMGR: Devirtualized call to '" << Callee->getName() << "'\n"); @@ -424,7 +429,7 @@ bool CGPassManager::RunAllPassesOnSCC(CallGraphSCC &CurSCC, CallGraph &CG, /// run - Execute all of the passes scheduled for execution. Keep track of /// whether any of the passes modifies the module, and if so, return true. bool CGPassManager::runOnModule(Module &M) { - CallGraph &CG = getAnalysis<CallGraph>(); + CallGraph &CG = getAnalysis<CallGraphWrapperPass>().getCallGraph(); bool Changed = doInitialization(CG); // Walk the callgraph in bottom-up SCC order. @@ -434,8 +439,8 @@ bool CGPassManager::runOnModule(Module &M) { while (!CGI.isAtEnd()) { // Copy the current SCC and increment past it so that the pass can hack // on the SCC if it wants to without invalidating our iterator. - std::vector<CallGraphNode*> &NodeVec = *CGI; - CurSCC.initialize(&NodeVec[0], &NodeVec[0]+NodeVec.size()); + const std::vector<CallGraphNode *> &NodeVec = *CGI; + CurSCC.initialize(NodeVec.data(), NodeVec.data() + NodeVec.size()); ++CGI; // At the top level, we run all the passes in this pass manager on the @@ -570,8 +575,8 @@ void CallGraphSCCPass::assignPassManager(PMStack &PMS, /// the call graph. If the derived class implements this method, it should /// always explicitly call the implementation here. void CallGraphSCCPass::getAnalysisUsage(AnalysisUsage &AU) const { - AU.addRequired<CallGraph>(); - AU.addPreserved<CallGraph>(); + AU.addRequired<CallGraphWrapperPass>(); + AU.addPreserved<CallGraphWrapperPass>(); } @@ -590,15 +595,19 @@ namespace { static char ID; PrintCallGraphPass(const std::string &B, raw_ostream &o) : CallGraphSCCPass(ID), Banner(B), Out(o) {} - - virtual void getAnalysisUsage(AnalysisUsage &AU) const { + + void getAnalysisUsage(AnalysisUsage &AU) const override { AU.setPreservesAll(); } - - bool runOnSCC(CallGraphSCC &SCC) { + + bool runOnSCC(CallGraphSCC &SCC) override { Out << Banner; - for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I) - (*I)->getFunction()->print(Out); + for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I) { + if ((*I)->getFunction()) + (*I)->getFunction()->print(Out); + else + Out << "\nPrinting <null> Function\n"; + } return false; } }; diff --git a/lib/Analysis/IPA/CallPrinter.cpp b/lib/Analysis/IPA/CallPrinter.cpp index 306ae7a4dbfb..68dcd3c06427 100644 --- a/lib/Analysis/IPA/CallPrinter.cpp +++ b/lib/Analysis/IPA/CallPrinter.cpp @@ -22,13 +22,10 @@ using namespace llvm; namespace llvm { -template<> -struct DOTGraphTraits<CallGraph*> : public DefaultDOTGraphTraits { - DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {} +template <> struct DOTGraphTraits<CallGraph *> : public DefaultDOTGraphTraits { + DOTGraphTraits(bool isSimple = false) : DefaultDOTGraphTraits(isSimple) {} - static std::string getGraphName(CallGraph *Graph) { - return "Call graph"; - } + static std::string getGraphName(CallGraph *Graph) { return "Call graph"; } std::string getNodeLabel(CallGraphNode *Node, CallGraph *Graph) { if (Function *Func = Node->getFunction()) @@ -38,49 +35,57 @@ struct DOTGraphTraits<CallGraph*> : public DefaultDOTGraphTraits { } }; +struct AnalysisCallGraphWrapperPassTraits { + static CallGraph *getGraph(CallGraphWrapperPass *P) { + return &P->getCallGraph(); + } +}; + } // end llvm namespace namespace { struct CallGraphViewer - : public DOTGraphTraitsModuleViewer<CallGraph, true> { + : public DOTGraphTraitsModuleViewer<CallGraphWrapperPass, true, CallGraph *, + AnalysisCallGraphWrapperPassTraits> { static char ID; CallGraphViewer() - : DOTGraphTraitsModuleViewer<CallGraph, true>("callgraph", ID) { + : DOTGraphTraitsModuleViewer<CallGraphWrapperPass, true, CallGraph *, + AnalysisCallGraphWrapperPassTraits>( + "callgraph", ID) { initializeCallGraphViewerPass(*PassRegistry::getPassRegistry()); } }; -struct CallGraphPrinter - : public DOTGraphTraitsModulePrinter<CallGraph, true> { +struct CallGraphPrinter : public DOTGraphTraitsModulePrinter< + CallGraphWrapperPass, true, CallGraph *, + AnalysisCallGraphWrapperPassTraits> { static char ID; CallGraphPrinter() - : DOTGraphTraitsModulePrinter<CallGraph, true>("callgraph", ID) { - initializeCallGraphPrinterPass(*PassRegistry::getPassRegistry()); + : DOTGraphTraitsModulePrinter<CallGraphWrapperPass, true, CallGraph *, + AnalysisCallGraphWrapperPassTraits>( + "callgraph", ID) { + initializeCallGraphPrinterPass(*PassRegistry::getPassRegistry()); } }; } // end anonymous namespace char CallGraphViewer::ID = 0; -INITIALIZE_PASS(CallGraphViewer, "view-callgraph", - "View call graph", - false, false) +INITIALIZE_PASS(CallGraphViewer, "view-callgraph", "View call graph", false, + false) char CallGraphPrinter::ID = 0; INITIALIZE_PASS(CallGraphPrinter, "dot-callgraph", - "Print call graph to 'dot' file", - false, false) + "Print call graph to 'dot' file", false, false) // Create methods available outside of this file, to use them // "include/llvm/LinkAllPasses.h". Otherwise the pass would be deleted by // the link time optimization. -ModulePass *llvm::createCallGraphViewerPass() { - return new CallGraphViewer(); -} +ModulePass *llvm::createCallGraphViewerPass() { return new CallGraphViewer(); } ModulePass *llvm::createCallGraphPrinterPass() { return new CallGraphPrinter(); diff --git a/lib/Analysis/IPA/FindUsedTypes.cpp b/lib/Analysis/IPA/FindUsedTypes.cpp index 1c4f17d3819a..b37344b044ce 100644 --- a/lib/Analysis/IPA/FindUsedTypes.cpp +++ b/lib/Analysis/IPA/FindUsedTypes.cpp @@ -14,11 +14,10 @@ //===----------------------------------------------------------------------===// #include "llvm/Analysis/FindUsedTypes.h" -#include "llvm/Assembly/Writer.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/InstIterator.h" #include "llvm/IR/Module.h" -#include "llvm/Support/InstIterator.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; diff --git a/lib/Analysis/IPA/GlobalsModRef.cpp b/lib/Analysis/IPA/GlobalsModRef.cpp index 7ec46442bf4c..607c06810123 100644 --- a/lib/Analysis/IPA/GlobalsModRef.cpp +++ b/lib/Analysis/IPA/GlobalsModRef.cpp @@ -14,7 +14,6 @@ // //===----------------------------------------------------------------------===// -#define DEBUG_TYPE "globalsmodref-aa" #include "llvm/Analysis/Passes.h" #include "llvm/ADT/SCCIterator.h" #include "llvm/ADT/Statistic.h" @@ -24,15 +23,17 @@ #include "llvm/Analysis/ValueTracking.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/InstIterator.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Module.h" #include "llvm/Pass.h" #include "llvm/Support/CommandLine.h" -#include "llvm/Support/InstIterator.h" #include <set> using namespace llvm; +#define DEBUG_TYPE "globalsmodref-aa" + STATISTIC(NumNonAddrTakenGlobalVars, "Number of global vars without address taken"); STATISTIC(NumNonAddrTakenFunctions,"Number of functions without address taken"); @@ -94,34 +95,38 @@ namespace { initializeGlobalsModRefPass(*PassRegistry::getPassRegistry()); } - bool runOnModule(Module &M) { - InitializeAliasAnalysis(this); // set up super class - AnalyzeGlobals(M); // find non-addr taken globals - AnalyzeCallGraph(getAnalysis<CallGraph>(), M); // Propagate on CG + bool runOnModule(Module &M) override { + InitializeAliasAnalysis(this); + + // Find non-addr taken globals. + AnalyzeGlobals(M); + + // Propagate on CG. + AnalyzeCallGraph(getAnalysis<CallGraphWrapperPass>().getCallGraph(), M); return false; } - virtual void getAnalysisUsage(AnalysisUsage &AU) const { + void getAnalysisUsage(AnalysisUsage &AU) const override { AliasAnalysis::getAnalysisUsage(AU); - AU.addRequired<CallGraph>(); + AU.addRequired<CallGraphWrapperPass>(); AU.setPreservesAll(); // Does not transform code } //------------------------------------------------ // Implement the AliasAnalysis API // - AliasResult alias(const Location &LocA, const Location &LocB); + AliasResult alias(const Location &LocA, const Location &LocB) override; ModRefResult getModRefInfo(ImmutableCallSite CS, - const Location &Loc); + const Location &Loc) override; ModRefResult getModRefInfo(ImmutableCallSite CS1, - ImmutableCallSite CS2) { + ImmutableCallSite CS2) override { return AliasAnalysis::getModRefInfo(CS1, CS2); } /// getModRefBehavior - Return the behavior of the specified function if /// called from the specified call site. The call site may be null in which /// case the most generic behavior of this function should be returned. - ModRefBehavior getModRefBehavior(const Function *F) { + ModRefBehavior getModRefBehavior(const Function *F) override { ModRefBehavior Min = UnknownModRefBehavior; if (FunctionRecord *FR = getFunctionInfo(F)) { @@ -137,7 +142,7 @@ namespace { /// getModRefBehavior - Return the behavior of the specified function if /// called from the specified call site. The call site may be null in which /// case the most generic behavior of this function should be returned. - ModRefBehavior getModRefBehavior(ImmutableCallSite CS) { + ModRefBehavior getModRefBehavior(ImmutableCallSite CS) override { ModRefBehavior Min = UnknownModRefBehavior; if (const Function* F = CS.getCalledFunction()) @@ -151,15 +156,15 @@ namespace { return ModRefBehavior(AliasAnalysis::getModRefBehavior(CS) & Min); } - virtual void deleteValue(Value *V); - virtual void copyValue(Value *From, Value *To); - virtual void addEscapingUse(Use &U); + void deleteValue(Value *V) override; + void copyValue(Value *From, Value *To) override; + void addEscapingUse(Use &U) override; /// getAdjustedAnalysisPointer - This method is used when a pass implements /// an analysis interface through multiple inheritance. If needed, it /// should override this to adjust the this pointer as needed for the /// specified pass info. - virtual void *getAdjustedAnalysisPointer(AnalysisID PI) { + void *getAdjustedAnalysisPointer(AnalysisID PI) override { if (PI == &AliasAnalysis::ID) return (AliasAnalysis*)this; return this; @@ -173,14 +178,14 @@ namespace { FunctionInfo.find(F); if (I != FunctionInfo.end()) return &I->second; - return 0; + return nullptr; } void AnalyzeGlobals(Module &M); void AnalyzeCallGraph(CallGraph &CG, Module &M); bool AnalyzeUsesOfPointer(Value *V, std::vector<Function*> &Readers, std::vector<Function*> &Writers, - GlobalValue *OkayStoreDest = 0); + GlobalValue *OkayStoreDest = nullptr); bool AnalyzeIndirectGlobalMemory(GlobalValue *GV); }; } @@ -189,7 +194,7 @@ char GlobalsModRef::ID = 0; INITIALIZE_AG_PASS_BEGIN(GlobalsModRef, AliasAnalysis, "globalsmodref-aa", "Simple mod/ref analysis for globals", false, true, false) -INITIALIZE_PASS_DEPENDENCY(CallGraph) +INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass) INITIALIZE_AG_PASS_END(GlobalsModRef, AliasAnalysis, "globalsmodref-aa", "Simple mod/ref analysis for globals", false, true, false) @@ -248,42 +253,33 @@ bool GlobalsModRef::AnalyzeUsesOfPointer(Value *V, GlobalValue *OkayStoreDest) { if (!V->getType()->isPointerTy()) return true; - for (Value::use_iterator UI = V->use_begin(), E=V->use_end(); UI != E; ++UI) { - User *U = *UI; - if (LoadInst *LI = dyn_cast<LoadInst>(U)) { + for (Use &U : V->uses()) { + User *I = U.getUser(); + if (LoadInst *LI = dyn_cast<LoadInst>(I)) { Readers.push_back(LI->getParent()->getParent()); - } else if (StoreInst *SI = dyn_cast<StoreInst>(U)) { + } else if (StoreInst *SI = dyn_cast<StoreInst>(I)) { if (V == SI->getOperand(1)) { Writers.push_back(SI->getParent()->getParent()); } else if (SI->getOperand(1) != OkayStoreDest) { return true; // Storing the pointer } - } else if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(U)) { - if (AnalyzeUsesOfPointer(GEP, Readers, Writers)) return true; - } else if (BitCastInst *BCI = dyn_cast<BitCastInst>(U)) { - if (AnalyzeUsesOfPointer(BCI, Readers, Writers, OkayStoreDest)) + } else if (Operator::getOpcode(I) == Instruction::GetElementPtr) { + if (AnalyzeUsesOfPointer(I, Readers, Writers)) return true; - } else if (isFreeCall(U, TLI)) { - Writers.push_back(cast<Instruction>(U)->getParent()->getParent()); - } else if (CallInst *CI = dyn_cast<CallInst>(U)) { - // Make sure that this is just the function being called, not that it is - // passing into the function. - for (unsigned i = 0, e = CI->getNumArgOperands(); i != e; ++i) - if (CI->getArgOperand(i) == V) return true; - } else if (InvokeInst *II = dyn_cast<InvokeInst>(U)) { + } else if (Operator::getOpcode(I) == Instruction::BitCast) { + if (AnalyzeUsesOfPointer(I, Readers, Writers, OkayStoreDest)) + return true; + } else if (CallSite CS = I) { // Make sure that this is just the function being called, not that it is // passing into the function. - for (unsigned i = 0, e = II->getNumArgOperands(); i != e; ++i) - if (II->getArgOperand(i) == V) return true; - } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(U)) { - if (CE->getOpcode() == Instruction::GetElementPtr || - CE->getOpcode() == Instruction::BitCast) { - if (AnalyzeUsesOfPointer(CE, Readers, Writers)) - return true; - } else { - return true; + if (!CS.isCallee(&U)) { + // Detect calls to free. + if (isFreeCall(I, TLI)) + Writers.push_back(CS->getParent()->getParent()); + else + return true; // Argument of an unknown call. } - } else if (ICmpInst *ICI = dyn_cast<ICmpInst>(U)) { + } else if (ICmpInst *ICI = dyn_cast<ICmpInst>(I)) { if (!isa<ConstantPointerNull>(ICI->getOperand(1))) return true; // Allow comparison against null. } else { @@ -308,8 +304,7 @@ bool GlobalsModRef::AnalyzeIndirectGlobalMemory(GlobalValue *GV) { // Walk the user list of the global. If we find anything other than a direct // load or store, bail out. - for (Value::use_iterator I = GV->use_begin(), E = GV->use_end(); I != E; ++I){ - User *U = *I; + for (User *U : GV->users()) { if (LoadInst *LI = dyn_cast<LoadInst>(U)) { // The pointer loaded from the global can only be used in simple ways: // we allow addressing of it and loading storing to it. We do *not* allow @@ -363,9 +358,8 @@ bool GlobalsModRef::AnalyzeIndirectGlobalMemory(GlobalValue *GV) { void GlobalsModRef::AnalyzeCallGraph(CallGraph &CG, Module &M) { // We do a bottom-up SCC traversal of the call graph. In other words, we // visit all callees before callers (leaf-first). - for (scc_iterator<CallGraph*> I = scc_begin(&CG), E = scc_end(&CG); I != E; - ++I) { - std::vector<CallGraphNode *> &SCC = *I; + for (scc_iterator<CallGraph*> I = scc_begin(&CG); !I.isAtEnd(); ++I) { + const std::vector<CallGraphNode *> &SCC = *I; assert(!SCC.empty() && "SCC with no functions?"); if (!SCC[0]->getFunction()) { @@ -417,10 +411,8 @@ void GlobalsModRef::AnalyzeCallGraph(CallGraph &CG, Module &M) { FunctionEffect |= CalleeFR->FunctionEffect; // Incorporate callee's effects on globals into our info. - for (std::map<const GlobalValue*, unsigned>::iterator GI = - CalleeFR->GlobalInfo.begin(), E = CalleeFR->GlobalInfo.end(); - GI != E; ++GI) - FR.GlobalInfo[GI->first] |= GI->second; + for (const auto &G : CalleeFR->GlobalInfo) + FR.GlobalInfo[G.first] |= G.second; FR.MayReadAnyGlobal |= CalleeFR->MayReadAnyGlobal; } else { // Can't say anything about it. However, if it is inside our SCC, @@ -499,8 +491,8 @@ GlobalsModRef::alias(const Location &LocA, if (GV1 || GV2) { // If the global's address is taken, pretend we don't know it's a pointer to // the global. - if (GV1 && !NonAddressTakenGlobals.count(GV1)) GV1 = 0; - if (GV2 && !NonAddressTakenGlobals.count(GV2)) GV2 = 0; + if (GV1 && !NonAddressTakenGlobals.count(GV1)) GV1 = nullptr; + if (GV2 && !NonAddressTakenGlobals.count(GV2)) GV2 = nullptr; // If the two pointers are derived from two different non-addr-taken // globals, or if one is and the other isn't, we know these can't alias. @@ -514,7 +506,7 @@ GlobalsModRef::alias(const Location &LocA, // These pointers may be based on the memory owned by an indirect global. If // so, we may be able to handle this. First check to see if the base pointer // is a direct load from an indirect global. - GV1 = GV2 = 0; + GV1 = GV2 = nullptr; if (const LoadInst *LI = dyn_cast<LoadInst>(UV1)) if (GlobalVariable *GV = dyn_cast<GlobalVariable>(LI->getOperand(0))) if (IndirectGlobals.count(GV)) diff --git a/lib/Analysis/IPA/IPA.cpp b/lib/Analysis/IPA/IPA.cpp index 47357cf92127..b26c052de67e 100644 --- a/lib/Analysis/IPA/IPA.cpp +++ b/lib/Analysis/IPA/IPA.cpp @@ -12,14 +12,14 @@ //===----------------------------------------------------------------------===// #include "llvm/InitializePasses.h" -#include "llvm/PassRegistry.h" #include "llvm-c/Initialization.h" +#include "llvm/PassRegistry.h" using namespace llvm; /// initializeIPA - Initialize all passes linked into the IPA library. void llvm::initializeIPA(PassRegistry &Registry) { - initializeCallGraphPass(Registry); + initializeCallGraphWrapperPassPass(Registry); initializeCallGraphPrinterPass(Registry); initializeCallGraphViewerPass(Registry); initializeFindUsedTypesPass(Registry); diff --git a/lib/Analysis/IPA/InlineCost.cpp b/lib/Analysis/IPA/InlineCost.cpp index 3bc796e53f90..8807529cabac 100644 --- a/lib/Analysis/IPA/InlineCost.cpp +++ b/lib/Analysis/IPA/InlineCost.cpp @@ -11,7 +11,6 @@ // //===----------------------------------------------------------------------===// -#define DEBUG_TYPE "inline-cost" #include "llvm/Analysis/InlineCost.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SetVector.h" @@ -21,19 +20,21 @@ #include "llvm/Analysis/ConstantFolding.h" #include "llvm/Analysis/InstructionSimplify.h" #include "llvm/Analysis/TargetTransformInfo.h" +#include "llvm/IR/CallSite.h" #include "llvm/IR/CallingConv.h" #include "llvm/IR/DataLayout.h" +#include "llvm/IR/GetElementPtrTypeIterator.h" #include "llvm/IR/GlobalAlias.h" +#include "llvm/IR/InstVisitor.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Operator.h" -#include "llvm/InstVisitor.h" -#include "llvm/Support/CallSite.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/GetElementPtrTypeIterator.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; +#define DEBUG_TYPE "inline-cost" + STATISTIC(NumCallsAnalyzed, "Number of call sites analyzed"); namespace { @@ -43,7 +44,7 @@ class CallAnalyzer : public InstVisitor<CallAnalyzer, bool> { friend class InstVisitor<CallAnalyzer, bool>; // DataLayout if available, or null. - const DataLayout *const TD; + const DataLayout *const DL; /// The TargetTransformInfo available for this compilation. const TargetTransformInfo &TTI; @@ -97,9 +98,6 @@ class CallAnalyzer : public InstVisitor<CallAnalyzer, bool> { void disableSROA(Value *V); void accumulateSROACost(DenseMap<Value *, int>::iterator CostIt, int InstructionCost); - bool handleSROACandidate(bool IsSROAValid, - DenseMap<Value *, int>::iterator CostIt, - int InstructionCost); bool isGEPOffsetConstant(GetElementPtrInst &GEP); bool accumulateGEPOffset(GEPOperator &GEP, APInt &Offset); bool simplifyCallSite(Function *F, CallSite CS); @@ -142,9 +140,9 @@ class CallAnalyzer : public InstVisitor<CallAnalyzer, bool> { bool visitUnreachableInst(UnreachableInst &I); public: - CallAnalyzer(const DataLayout *TD, const TargetTransformInfo &TTI, + CallAnalyzer(const DataLayout *DL, const TargetTransformInfo &TTI, Function &Callee, int Threshold) - : TD(TD), TTI(TTI), F(Callee), Threshold(Threshold), Cost(0), + : DL(DL), TTI(TTI), F(Callee), Threshold(Threshold), Cost(0), IsCallerRecursive(false), IsRecursiveCall(false), ExposesReturnsTwice(false), HasDynamicAlloca(false), ContainsNoDuplicateCall(false), HasReturn(false), HasIndirectBr(false), @@ -225,21 +223,6 @@ void CallAnalyzer::accumulateSROACost(DenseMap<Value *, int>::iterator CostIt, SROACostSavings += InstructionCost; } -/// \brief Helper for the common pattern of handling a SROA candidate. -/// Either accumulates the cost savings if the SROA remains valid, or disables -/// SROA for the candidate. -bool CallAnalyzer::handleSROACandidate(bool IsSROAValid, - DenseMap<Value *, int>::iterator CostIt, - int InstructionCost) { - if (IsSROAValid) { - accumulateSROACost(CostIt, InstructionCost); - return true; - } - - disableSROA(CostIt); - return false; -} - /// \brief Check whether a GEP's indices are all constant. /// /// Respects any simplified values known during the analysis of this callsite. @@ -256,10 +239,10 @@ bool CallAnalyzer::isGEPOffsetConstant(GetElementPtrInst &GEP) { /// Returns false if unable to compute the offset for any reason. Respects any /// simplified values known during the analysis of this callsite. bool CallAnalyzer::accumulateGEPOffset(GEPOperator &GEP, APInt &Offset) { - if (!TD) + if (!DL) return false; - unsigned IntPtrWidth = TD->getPointerSizeInBits(); + unsigned IntPtrWidth = DL->getPointerSizeInBits(); assert(IntPtrWidth == Offset.getBitWidth()); for (gep_type_iterator GTI = gep_type_begin(GEP), GTE = gep_type_end(GEP); @@ -275,25 +258,34 @@ bool CallAnalyzer::accumulateGEPOffset(GEPOperator &GEP, APInt &Offset) { // Handle a struct index, which adds its field offset to the pointer. if (StructType *STy = dyn_cast<StructType>(*GTI)) { unsigned ElementIdx = OpC->getZExtValue(); - const StructLayout *SL = TD->getStructLayout(STy); + const StructLayout *SL = DL->getStructLayout(STy); Offset += APInt(IntPtrWidth, SL->getElementOffset(ElementIdx)); continue; } - APInt TypeSize(IntPtrWidth, TD->getTypeAllocSize(GTI.getIndexedType())); + APInt TypeSize(IntPtrWidth, DL->getTypeAllocSize(GTI.getIndexedType())); Offset += OpC->getValue().sextOrTrunc(IntPtrWidth) * TypeSize; } return true; } bool CallAnalyzer::visitAlloca(AllocaInst &I) { - // FIXME: Check whether inlining will turn a dynamic alloca into a static + // Check whether inlining will turn a dynamic alloca into a static // alloca, and handle that case. + if (I.isArrayAllocation()) { + if (Constant *Size = SimplifiedValues.lookup(I.getArraySize())) { + ConstantInt *AllocSize = dyn_cast<ConstantInt>(Size); + assert(AllocSize && "Allocation size not a constant int?"); + Type *Ty = I.getAllocatedType(); + AllocatedSize += Ty->getPrimitiveSizeInBits() * AllocSize->getZExtValue(); + return Base::visitAlloca(I); + } + } // Accumulate the allocated size. if (I.isStaticAlloca()) { Type *Ty = I.getAllocatedType(); - AllocatedSize += (TD ? TD->getTypeAllocSize(Ty) : + AllocatedSize += (DL ? DL->getTypeAllocSize(Ty) : Ty->getPrimitiveSizeInBits()); } @@ -330,7 +322,7 @@ bool CallAnalyzer::visitGetElementPtr(GetElementPtrInst &I) { // Try to fold GEPs of constant-offset call site argument pointers. This // requires target data and inbounds GEPs. - if (TD && I.isInBounds()) { + if (DL && I.isInBounds()) { // Check if we have a base + offset for the pointer. Value *Ptr = I.getPointerOperand(); std::pair<Value *, APInt> BaseAndOffset = ConstantOffsetPtrs.lookup(Ptr); @@ -399,6 +391,7 @@ bool CallAnalyzer::visitBitCast(BitCastInst &I) { } bool CallAnalyzer::visitPtrToInt(PtrToIntInst &I) { + const DataLayout *DL = I.getDataLayout(); // Propagate constants through ptrtoint. Constant *COp = dyn_cast<Constant>(I.getOperand(0)); if (!COp) @@ -412,7 +405,7 @@ bool CallAnalyzer::visitPtrToInt(PtrToIntInst &I) { // Track base/offset pairs when converted to a plain integer provided the // integer is large enough to represent the pointer. unsigned IntegerSize = I.getType()->getScalarSizeInBits(); - if (TD && IntegerSize >= TD->getPointerSizeInBits()) { + if (DL && IntegerSize >= DL->getPointerSizeInBits()) { std::pair<Value *, APInt> BaseAndOffset = ConstantOffsetPtrs.lookup(I.getOperand(0)); if (BaseAndOffset.first) @@ -435,6 +428,7 @@ bool CallAnalyzer::visitPtrToInt(PtrToIntInst &I) { } bool CallAnalyzer::visitIntToPtr(IntToPtrInst &I) { + const DataLayout *DL = I.getDataLayout(); // Propagate constants through ptrtoint. Constant *COp = dyn_cast<Constant>(I.getOperand(0)); if (!COp) @@ -449,7 +443,7 @@ bool CallAnalyzer::visitIntToPtr(IntToPtrInst &I) { // modifications provided the integer is not too large. Value *Op = I.getOperand(0); unsigned IntegerSize = Op->getType()->getScalarSizeInBits(); - if (TD && IntegerSize <= TD->getPointerSizeInBits()) { + if (DL && IntegerSize <= DL->getPointerSizeInBits()) { std::pair<Value *, APInt> BaseAndOffset = ConstantOffsetPtrs.lookup(Op); if (BaseAndOffset.first) ConstantOffsetPtrs[&I] = BaseAndOffset; @@ -488,7 +482,7 @@ bool CallAnalyzer::visitUnaryInstruction(UnaryInstruction &I) { COp = SimplifiedValues.lookup(Operand); if (COp) if (Constant *C = ConstantFoldInstOperands(I.getOpcode(), I.getType(), - COp, TD)) { + COp, DL)) { SimplifiedValues[&I] = C; return true; } @@ -523,9 +517,9 @@ bool CallAnalyzer::visitCmpInst(CmpInst &I) { // a common base. Value *LHSBase, *RHSBase; APInt LHSOffset, RHSOffset; - llvm::tie(LHSBase, LHSOffset) = ConstantOffsetPtrs.lookup(LHS); + std::tie(LHSBase, LHSOffset) = ConstantOffsetPtrs.lookup(LHS); if (LHSBase) { - llvm::tie(RHSBase, RHSOffset) = ConstantOffsetPtrs.lookup(RHS); + std::tie(RHSBase, RHSOffset) = ConstantOffsetPtrs.lookup(RHS); if (RHSBase && LHSBase == RHSBase) { // We have common bases, fold the icmp to a constant based on the // offsets. @@ -573,9 +567,9 @@ bool CallAnalyzer::visitSub(BinaryOperator &I) { Value *LHS = I.getOperand(0), *RHS = I.getOperand(1); Value *LHSBase, *RHSBase; APInt LHSOffset, RHSOffset; - llvm::tie(LHSBase, LHSOffset) = ConstantOffsetPtrs.lookup(LHS); + std::tie(LHSBase, LHSOffset) = ConstantOffsetPtrs.lookup(LHS); if (LHSBase) { - llvm::tie(RHSBase, RHSOffset) = ConstantOffsetPtrs.lookup(RHS); + std::tie(RHSBase, RHSOffset) = ConstantOffsetPtrs.lookup(RHS); if (RHSBase && LHSBase == RHSBase) { // We have common bases, fold the subtract to a constant based on the // offsets. @@ -602,7 +596,7 @@ bool CallAnalyzer::visitBinaryOperator(BinaryOperator &I) { if (!isa<Constant>(RHS)) if (Constant *SimpleRHS = SimplifiedValues.lookup(RHS)) RHS = SimpleRHS; - Value *SimpleV = SimplifyBinOp(I.getOpcode(), LHS, RHS, TD); + Value *SimpleV = SimplifyBinOp(I.getOpcode(), LHS, RHS, DL); if (Constant *C = dyn_cast_or_null<Constant>(SimpleV)) { SimplifiedValues[&I] = C; return true; @@ -721,7 +715,7 @@ bool CallAnalyzer::visitCallSite(CallSite CS) { return false; } if (CS.isCall() && - cast<CallInst>(CS.getInstruction())->hasFnAttr(Attribute::NoDuplicate)) + cast<CallInst>(CS.getInstruction())->cannotDuplicate()) ContainsNoDuplicateCall = true; if (Function *F = CS.getCalledFunction()) { @@ -784,7 +778,7 @@ bool CallAnalyzer::visitCallSite(CallSite CS) { // during devirtualization and so we want to give it a hefty bonus for // inlining, but cap that bonus in the event that inlining wouldn't pan // out. Pretend to inline the function, with a custom threshold. - CallAnalyzer CA(TD, TTI, *F, InlineConstants::IndirectCallThreshold); + CallAnalyzer CA(DL, TTI, *F, InlineConstants::IndirectCallThreshold); if (CA.analyzeCall(CS)) { // We were able to inline the indirect call! Subtract the cost from the // bonus we want to apply, but don't go below zero. @@ -814,9 +808,29 @@ bool CallAnalyzer::visitBranchInst(BranchInst &BI) { bool CallAnalyzer::visitSwitchInst(SwitchInst &SI) { // We model unconditional switches as free, see the comments on handling // branches. - return isa<ConstantInt>(SI.getCondition()) || - dyn_cast_or_null<ConstantInt>( - SimplifiedValues.lookup(SI.getCondition())); + if (isa<ConstantInt>(SI.getCondition())) + return true; + if (Value *V = SimplifiedValues.lookup(SI.getCondition())) + if (isa<ConstantInt>(V)) + return true; + + // Otherwise, we need to accumulate a cost proportional to the number of + // distinct successor blocks. This fan-out in the CFG cannot be represented + // for free even if we can represent the core switch as a jumptable that + // takes a single instruction. + // + // NB: We convert large switches which are just used to initialize large phi + // nodes to lookup tables instead in simplify-cfg, so this shouldn't prevent + // inlining those. It will prevent inlining in cases where the optimization + // does not (yet) fire. + SmallPtrSet<BasicBlock *, 8> SuccessorBlocks; + SuccessorBlocks.insert(SI.getDefaultDest()); + for (auto I = SI.case_begin(), E = SI.case_end(); I != E; ++I) + SuccessorBlocks.insert(I.getCaseSuccessor()); + // Add cost corresponding to the number of distinct destinations. The first + // we model as free because of fallthrough. + Cost += (SuccessorBlocks.size() - 1) * InlineConstants::InstrCost; + return false; } bool CallAnalyzer::visitIndirectBrInst(IndirectBrInst &IBI) { @@ -827,10 +841,7 @@ bool CallAnalyzer::visitIndirectBrInst(IndirectBrInst &IBI) { // original function which is extremely undefined behavior. // FIXME: This logic isn't really right; we can safely inline functions with // indirectbr's as long as no other function or global references the - // blockaddress of a block within the current function. And as a QOI issue, - // if someone is using a blockaddress without an indirectbr, and that - // reference somehow ends up in another function or global, we probably don't - // want to inline this function. + // blockaddress of a block within the current function. HasIndirectBr = true; return false; } @@ -872,6 +883,16 @@ bool CallAnalyzer::visitInstruction(Instruction &I) { /// viable, and true if inlining remains viable. bool CallAnalyzer::analyzeBlock(BasicBlock *BB) { for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) { + // FIXME: Currently, the number of instructions in a function regardless of + // our ability to simplify them during inline to constants or dead code, + // are actually used by the vector bonus heuristic. As long as that's true, + // we have to special case debug intrinsics here to prevent differences in + // inlining due to debug symbols. Eventually, the number of unsimplified + // instructions shouldn't factor into the cost computation, but until then, + // hack around it here. + if (isa<DbgInfoIntrinsic>(I)) + continue; + ++NumInstructions; if (isa<ExtractElementInst>(I) || I->getType()->isVectorTy()) ++NumVectorInstructions; @@ -921,10 +942,10 @@ bool CallAnalyzer::analyzeBlock(BasicBlock *BB) { /// returns 0 if V is not a pointer, and returns the constant '0' if there are /// no constant offsets applied. ConstantInt *CallAnalyzer::stripAndComputeInBoundsConstantOffsets(Value *&V) { - if (!TD || !V->getType()->isPointerTy()) - return 0; + if (!DL || !V->getType()->isPointerTy()) + return nullptr; - unsigned IntPtrWidth = TD->getPointerSizeInBits(); + unsigned IntPtrWidth = DL->getPointerSizeInBits(); APInt Offset = APInt::getNullValue(IntPtrWidth); // Even though we don't look through PHI nodes, we could be called on an @@ -934,7 +955,7 @@ ConstantInt *CallAnalyzer::stripAndComputeInBoundsConstantOffsets(Value *&V) { do { if (GEPOperator *GEP = dyn_cast<GEPOperator>(V)) { if (!GEP->isInBounds() || !accumulateGEPOffset(*GEP, Offset)) - return 0; + return nullptr; V = GEP->getPointerOperand(); } else if (Operator::getOpcode(V) == Instruction::BitCast) { V = cast<Operator>(V)->getOperand(0); @@ -948,7 +969,7 @@ ConstantInt *CallAnalyzer::stripAndComputeInBoundsConstantOffsets(Value *&V) { assert(V->getType()->isPointerTy() && "Unexpected operand type!"); } while (Visited.insert(V)); - Type *IntPtrTy = TD->getIntPtrType(V->getContext()); + Type *IntPtrTy = DL->getIntPtrType(V->getContext()); return cast<ConstantInt>(ConstantInt::get(IntPtrTy, Offset)); } @@ -983,12 +1004,12 @@ bool CallAnalyzer::analyzeCall(CallSite CS) { // Give out bonuses per argument, as the instructions setting them up will // be gone after inlining. for (unsigned I = 0, E = CS.arg_size(); I != E; ++I) { - if (TD && CS.isByValArgument(I)) { + if (DL && CS.isByValArgument(I)) { // We approximate the number of loads and stores needed by dividing the // size of the byval type by the target's pointer size. PointerType *PTy = cast<PointerType>(CS.getArgument(I)->getType()); - unsigned TypeSize = TD->getTypeSizeInBits(PTy->getElementType()); - unsigned PointerSize = TD->getPointerSizeInBits(); + unsigned TypeSize = DL->getTypeSizeInBits(PTy->getElementType()); + unsigned PointerSize = DL->getPointerSizeInBits(); // Ceiling division. unsigned NumStores = (TypeSize + PointerSize - 1) / PointerSize; @@ -1040,9 +1061,8 @@ bool CallAnalyzer::analyzeCall(CallSite CS) { Function *Caller = CS.getInstruction()->getParent()->getParent(); // Check if the caller function is recursive itself. - for (Value::use_iterator U = Caller->use_begin(), E = Caller->use_end(); - U != E; ++U) { - CallSite Site(cast<Value>(*U)); + for (User *U : Caller->users()) { + CallSite Site(U); if (!Site) continue; Instruction *I = Site.getInstruction(); @@ -1098,6 +1118,15 @@ bool CallAnalyzer::analyzeCall(CallSite CS) { if (BB->empty()) continue; + // Disallow inlining a blockaddress. A blockaddress only has defined + // behavior for an indirect branch in the same function, and we do not + // currently support inlining indirect branches. But, the inliner may not + // see an indirect branch that ends up being dead code at a particular call + // site. If the blockaddress escapes the function, e.g., via a global + // variable, inlining may lead to an invalid cross-function reference. + if (BB->hasAddressTaken()) + return false; + // Analyze the cost of this block. If we blow through the threshold, this // returns false, and we can bail on out. if (!analyzeBlock(BB)) { @@ -1154,7 +1183,7 @@ bool CallAnalyzer::analyzeCall(CallSite CS) { } } - // If this is a noduplicate call, we can still inline as long as + // If this is a noduplicate call, we can still inline as long as // inlining this would cause the removal of the caller (so the instruction // is not actually duplicated, just moved). if (!OnlyOneCallAndLocalLinkage && ContainsNoDuplicateCall) @@ -1168,7 +1197,7 @@ bool CallAnalyzer::analyzeCall(CallSite CS) { #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) /// \brief Dump stats about this call's analysis. void CallAnalyzer::dump() { -#define DEBUG_PRINT_STAT(x) llvm::dbgs() << " " #x ": " << x << "\n" +#define DEBUG_PRINT_STAT(x) dbgs() << " " #x ": " << x << "\n" DEBUG_PRINT_STAT(NumConstantArgs); DEBUG_PRINT_STAT(NumConstantOffsetPtrArgs); DEBUG_PRINT_STAT(NumAllocaArgs); @@ -1178,6 +1207,9 @@ void CallAnalyzer::dump() { DEBUG_PRINT_STAT(SROACostSavings); DEBUG_PRINT_STAT(SROACostSavingsLost); DEBUG_PRINT_STAT(ContainsNoDuplicateCall); + DEBUG_PRINT_STAT(Cost); + DEBUG_PRINT_STAT(Threshold); + DEBUG_PRINT_STAT(VectorBonus); #undef DEBUG_PRINT_STAT } #endif @@ -1190,7 +1222,7 @@ INITIALIZE_PASS_END(InlineCostAnalysis, "inline-cost", "Inline Cost Analysis", char InlineCostAnalysis::ID = 0; -InlineCostAnalysis::InlineCostAnalysis() : CallGraphSCCPass(ID), TD(0) {} +InlineCostAnalysis::InlineCostAnalysis() : CallGraphSCCPass(ID) {} InlineCostAnalysis::~InlineCostAnalysis() {} @@ -1201,7 +1233,6 @@ void InlineCostAnalysis::getAnalysisUsage(AnalysisUsage &AU) const { } bool InlineCostAnalysis::runOnSCC(CallGraphSCC &SCC) { - TD = getAnalysisIfAvailable<DataLayout>(); TTI = &getAnalysis<TargetTransformInfo>(); return false; } @@ -1234,7 +1265,7 @@ InlineCost InlineCostAnalysis::getInlineCost(CallSite CS, Function *Callee, // Calls to functions with always-inline attributes should be inlined // whenever possible. - if (Callee->hasFnAttribute(Attribute::AlwaysInline)) { + if (CS.hasFnAttr(Attribute::AlwaysInline)) { if (isInlineViable(*Callee)) return llvm::InlineCost::getAlways(); return llvm::InlineCost::getNever(); @@ -1259,7 +1290,7 @@ InlineCost InlineCostAnalysis::getInlineCost(CallSite CS, Function *Callee, DEBUG(llvm::dbgs() << " Analyzing call of " << Callee->getName() << "...\n"); - CallAnalyzer CA(TD, *TTI, *Callee, Threshold); + CallAnalyzer CA(Callee->getDataLayout(), *TTI, *Callee, Threshold); bool ShouldInline = CA.analyzeCall(CS); DEBUG(CA.dump()); @@ -1278,8 +1309,9 @@ bool InlineCostAnalysis::isInlineViable(Function &F) { F.getAttributes().hasAttribute(AttributeSet::FunctionIndex, Attribute::ReturnsTwice); for (Function::iterator BI = F.begin(), BE = F.end(); BI != BE; ++BI) { - // Disallow inlining of functions which contain an indirect branch. - if (isa<IndirectBrInst>(BI->getTerminator())) + // Disallow inlining of functions which contain indirect branches or + // blockaddresses. + if (isa<IndirectBrInst>(BI->getTerminator()) || BI->hasAddressTaken()) return false; for (BasicBlock::iterator II = BI->begin(), IE = BI->end(); II != IE; |
