diff options
Diffstat (limited to 'contrib/llvm/lib/Transforms/IPO')
22 files changed, 473 insertions, 649 deletions
diff --git a/contrib/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp b/contrib/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp index 28ea079..0c77e1f 100644 --- a/contrib/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp +++ b/contrib/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp @@ -67,7 +67,7 @@ namespace { virtual bool runOnSCC(CallGraphSCC &SCC); static char ID; // Pass identification, replacement for typeid explicit ArgPromotion(unsigned maxElements = 3) - : CallGraphSCCPass(&ID), maxElements(maxElements) {} + : CallGraphSCCPass(ID), maxElements(maxElements) {} /// A vector used to hold the indices of a single GEP instruction typedef std::vector<uint64_t> IndicesVector; @@ -84,8 +84,8 @@ namespace { } char ArgPromotion::ID = 0; -static RegisterPass<ArgPromotion> -X("argpromotion", "Promote 'by reference' arguments to scalars"); +INITIALIZE_PASS(ArgPromotion, "argpromotion", + "Promote 'by reference' arguments to scalars", false, false); Pass *llvm::createArgumentPromotionPass(unsigned maxElements) { return new ArgPromotion(maxElements); @@ -208,8 +208,8 @@ static bool AllCalleesPassInValidPointerForArgument(Argument *Arg) { // have direct callees. for (Value::use_iterator UI = Callee->use_begin(), E = Callee->use_end(); UI != E; ++UI) { - CallSite CS = CallSite::get(*UI); - assert(CS.getInstruction() && "Should only have direct calls!"); + CallSite CS(*UI); + assert(CS && "Should only have direct calls!"); if (!IsAlwaysValidPointer(CS.getArgument(ArgNo))) return false; @@ -619,14 +619,13 @@ CallGraphNode *ArgPromotion::DoPromotion(Function *F, // Get a new callgraph node for NF. CallGraphNode *NF_CGN = CG.getOrInsertFunction(NF); - // Loop over all of the callers of the function, transforming the call sites // to pass in the loaded pointers. // SmallVector<Value*, 16> Args; while (!F->use_empty()) { - CallSite CS = CallSite::get(F->use_back()); + CallSite CS(F->use_back()); assert(CS.getCalledFunction() == F); Instruction *Call = CS.getInstruction(); const AttrListPtr &CallPAL = CS.getAttributes(); diff --git a/contrib/llvm/lib/Transforms/IPO/ConstantMerge.cpp b/contrib/llvm/lib/Transforms/IPO/ConstantMerge.cpp index 3c05f88..64e8d79 100644 --- a/contrib/llvm/lib/Transforms/IPO/ConstantMerge.cpp +++ b/contrib/llvm/lib/Transforms/IPO/ConstantMerge.cpp @@ -19,10 +19,12 @@ #define DEBUG_TYPE "constmerge" #include "llvm/Transforms/IPO.h" +#include "llvm/Constants.h" #include "llvm/DerivedTypes.h" #include "llvm/Module.h" #include "llvm/Pass.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/Statistic.h" using namespace llvm; @@ -31,7 +33,7 @@ STATISTIC(NumMerged, "Number of global constants merged"); namespace { struct ConstantMerge : public ModulePass { static char ID; // Pass identification, replacement for typeid - ConstantMerge() : ModulePass(&ID) {} + ConstantMerge() : ModulePass(ID) {} // run - For this pass, process all of the globals in the module, // eliminating duplicate constants. @@ -41,12 +43,32 @@ namespace { } char ConstantMerge::ID = 0; -static RegisterPass<ConstantMerge> -X("constmerge", "Merge Duplicate Global Constants"); +INITIALIZE_PASS(ConstantMerge, "constmerge", + "Merge Duplicate Global Constants", false, false); ModulePass *llvm::createConstantMergePass() { return new ConstantMerge(); } + + +/// Find values that are marked as llvm.used. +static void FindUsedValues(GlobalVariable *LLVMUsed, + SmallPtrSet<const GlobalValue*, 8> &UsedValues) { + if (LLVMUsed == 0) return; + ConstantArray *Inits = dyn_cast<ConstantArray>(LLVMUsed->getInitializer()); + if (Inits == 0) return; + + for (unsigned i = 0, e = Inits->getNumOperands(); i != e; ++i) + if (GlobalValue *GV = + dyn_cast<GlobalValue>(Inits->getOperand(i)->stripPointerCasts())) + UsedValues.insert(GV); +} + bool ConstantMerge::runOnModule(Module &M) { + // Find all the globals that are marked "used". These cannot be merged. + SmallPtrSet<const GlobalValue*, 8> UsedGlobals; + FindUsedValues(M.getGlobalVariable("llvm.used"), UsedGlobals); + FindUsedValues(M.getGlobalVariable("llvm.compiler.used"), UsedGlobals); + // Map unique constant/section pairs to globals. We don't want to merge // globals in different sections. DenseMap<Constant*, GlobalVariable*> CMap; @@ -79,9 +101,13 @@ bool ConstantMerge::runOnModule(Module &M) { // Only process constants with initializers in the default addres space. if (!GV->isConstant() ||!GV->hasDefinitiveInitializer() || - GV->getType()->getAddressSpace() != 0 || !GV->getSection().empty()) + GV->getType()->getAddressSpace() != 0 || !GV->getSection().empty() || + // Don't touch values marked with attribute(used). + UsedGlobals.count(GV)) continue; + + Constant *Init = GV->getInitializer(); // Check to see if the initializer is already known. diff --git a/contrib/llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp b/contrib/llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp index 475eee8..47df235 100644 --- a/contrib/llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp +++ b/contrib/llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp @@ -122,11 +122,11 @@ namespace { protected: // DAH uses this to specify a different ID. - explicit DAE(void *ID) : ModulePass(ID) {} + explicit DAE(char &ID) : ModulePass(ID) {} public: static char ID; // Pass identification, replacement for typeid - DAE() : ModulePass(&ID) {} + DAE() : ModulePass(ID) {} bool runOnModule(Module &M); @@ -151,8 +151,7 @@ namespace { char DAE::ID = 0; -static RegisterPass<DAE> -X("deadargelim", "Dead Argument Elimination"); +INITIALIZE_PASS(DAE, "deadargelim", "Dead Argument Elimination", false, false); namespace { /// DAH - DeadArgumentHacking pass - Same as dead argument elimination, but @@ -160,15 +159,16 @@ namespace { /// by bugpoint. struct DAH : public DAE { static char ID; - DAH() : DAE(&ID) {} + DAH() : DAE(ID) {} virtual bool ShouldHackArguments() const { return true; } }; } char DAH::ID = 0; -static RegisterPass<DAH> -Y("deadarghaX0r", "Dead Argument Hacking (BUGPOINT USE ONLY; DO NOT USE)"); +INITIALIZE_PASS(DAH, "deadarghaX0r", + "Dead Argument Hacking (BUGPOINT USE ONLY; DO NOT USE)", + false, false); /// createDeadArgEliminationPass - This pass removes arguments from functions /// which are not used by the body of the function. @@ -220,11 +220,11 @@ bool DAE::DeleteDeadVarargs(Function &Fn) { // std::vector<Value*> Args; while (!Fn.use_empty()) { - CallSite CS = CallSite::get(Fn.use_back()); + CallSite CS(Fn.use_back()); Instruction *Call = CS.getInstruction(); // Pass all the same arguments. - Args.assign(CS.arg_begin(), CS.arg_begin()+NumArgs); + Args.assign(CS.arg_begin(), CS.arg_begin() + NumArgs); // Drop any attributes that were on the vararg arguments. AttrListPtr PAL = CS.getAttributes(); @@ -250,8 +250,7 @@ bool DAE::DeleteDeadVarargs(Function &Fn) { if (cast<CallInst>(Call)->isTailCall()) cast<CallInst>(New)->setTailCall(); } - if (MDNode *N = Call->getDbgMetadata()) - New->setDbgMetadata(N); + New->setDebugLoc(Call->getDebugLoc()); Args.clear(); @@ -725,7 +724,7 @@ bool DAE::RemoveDeadStuffFromFunction(Function *F) { // std::vector<Value*> Args; while (!F->use_empty()) { - CallSite CS = CallSite::get(F->use_back()); + CallSite CS(F->use_back()); Instruction *Call = CS.getInstruction(); AttributesVec.clear(); @@ -780,8 +779,7 @@ bool DAE::RemoveDeadStuffFromFunction(Function *F) { if (cast<CallInst>(Call)->isTailCall()) cast<CallInst>(New)->setTailCall(); } - if (MDNode *N = Call->getDbgMetadata()) - New->setDbgMetadata(N); + New->setDebugLoc(Call->getDebugLoc()); Args.clear(); diff --git a/contrib/llvm/lib/Transforms/IPO/DeadTypeElimination.cpp b/contrib/llvm/lib/Transforms/IPO/DeadTypeElimination.cpp index 662fbb5..5dc50c5 100644 --- a/contrib/llvm/lib/Transforms/IPO/DeadTypeElimination.cpp +++ b/contrib/llvm/lib/Transforms/IPO/DeadTypeElimination.cpp @@ -26,7 +26,7 @@ STATISTIC(NumKilled, "Number of unused typenames removed from symtab"); namespace { struct DTE : public ModulePass { static char ID; // Pass identification, replacement for typeid - DTE() : ModulePass(&ID) {} + DTE() : ModulePass(ID) {} // doPassInitialization - For this pass, it removes global symbol table // entries for primitive types. These are never used for linking in GCC and @@ -45,7 +45,7 @@ namespace { } char DTE::ID = 0; -static RegisterPass<DTE> X("deadtypeelim", "Dead Type Elimination"); +INITIALIZE_PASS(DTE, "deadtypeelim", "Dead Type Elimination", false, false); ModulePass *llvm::createDeadTypeEliminationPass() { return new DTE(); diff --git a/contrib/llvm/lib/Transforms/IPO/ExtractGV.cpp b/contrib/llvm/lib/Transforms/IPO/ExtractGV.cpp index 7f67e48..45c5fe7 100644 --- a/contrib/llvm/lib/Transforms/IPO/ExtractGV.cpp +++ b/contrib/llvm/lib/Transforms/IPO/ExtractGV.cpp @@ -17,15 +17,15 @@ #include "llvm/Pass.h" #include "llvm/Constants.h" #include "llvm/Transforms/IPO.h" +#include "llvm/ADT/SetVector.h" #include <algorithm> using namespace llvm; namespace { /// @brief A pass to extract specific functions and their dependencies. class GVExtractorPass : public ModulePass { - std::vector<GlobalValue*> Named; + SetVector<GlobalValue *> Named; bool deleteStuff; - bool reLink; public: static char ID; // Pass identification, replacement for typeid @@ -33,135 +33,42 @@ namespace { /// specified function. Otherwise, it deletes as much of the module as /// possible, except for the function specified. /// - explicit GVExtractorPass(std::vector<GlobalValue*>& GVs, bool deleteS = true, - bool relinkCallees = false) - : ModulePass(&ID), Named(GVs), deleteStuff(deleteS), - reLink(relinkCallees) {} + explicit GVExtractorPass(std::vector<GlobalValue*>& GVs, bool deleteS = true) + : ModulePass(ID), Named(GVs.begin(), GVs.end()), deleteStuff(deleteS) {} bool runOnModule(Module &M) { - if (Named.size() == 0) { - return false; // Nothing to extract - } - - - if (deleteStuff) - return deleteGV(); - M.setModuleInlineAsm(""); - return isolateGV(M); - } - - bool deleteGV() { - for (std::vector<GlobalValue*>::iterator GI = Named.begin(), - GE = Named.end(); GI != GE; ++GI) { - if (Function* NamedFunc = dyn_cast<Function>(*GI)) { - // If we're in relinking mode, set linkage of all internal callees to - // external. This will allow us extract function, and then - link - // everything together - if (reLink) { - for (Function::iterator B = NamedFunc->begin(), BE = NamedFunc->end(); - B != BE; ++B) { - for (BasicBlock::iterator I = B->begin(), E = B->end(); - I != E; ++I) { - if (CallInst* callInst = dyn_cast<CallInst>(&*I)) { - Function* Callee = callInst->getCalledFunction(); - if (Callee && Callee->hasLocalLinkage()) - Callee->setLinkage(GlobalValue::ExternalLinkage); - } - } - } - } - - NamedFunc->setLinkage(GlobalValue::ExternalLinkage); - NamedFunc->deleteBody(); - assert(NamedFunc->isDeclaration() && "This didn't make the function external!"); - } else { - if (!(*GI)->isDeclaration()) { - cast<GlobalVariable>(*GI)->setInitializer(0); //clear the initializer - (*GI)->setLinkage(GlobalValue::ExternalLinkage); - } - } - } - return true; - } - - bool isolateGV(Module &M) { - // Mark all globals internal - // FIXME: what should we do with private linkage? - for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) + // Visit the global inline asm. + if (!deleteStuff) + M.setModuleInlineAsm(""); + + // For simplicity, just give all GlobalValues ExternalLinkage. A trickier + // implementation could figure out which GlobalValues are actually + // referenced by the Named set, and which GlobalValues in the rest of + // the module are referenced by the NamedSet, and get away with leaving + // more internal and private things internal and private. But for now, + // be conservative and simple. + + // Visit the GlobalVariables. + for (Module::global_iterator I = M.global_begin(), E = M.global_end(); + I != E; ++I) if (!I->isDeclaration()) { - I->setLinkage(GlobalValue::InternalLinkage); + if (I->hasLocalLinkage()) + I->setVisibility(GlobalValue::HiddenVisibility); + I->setLinkage(GlobalValue::ExternalLinkage); + if (deleteStuff == Named.count(I)) + I->setInitializer(0); } + + // Visit the Functions. for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) if (!I->isDeclaration()) { - I->setLinkage(GlobalValue::InternalLinkage); - } - - // Make sure our result is globally accessible... - // by putting them in the used array - { - std::vector<Constant *> AUGs; - const Type *SBP= - Type::getInt8PtrTy(M.getContext()); - for (std::vector<GlobalValue*>::iterator GI = Named.begin(), - GE = Named.end(); GI != GE; ++GI) { - (*GI)->setLinkage(GlobalValue::ExternalLinkage); - AUGs.push_back(ConstantExpr::getBitCast(*GI, SBP)); - } - ArrayType *AT = ArrayType::get(SBP, AUGs.size()); - Constant *Init = ConstantArray::get(AT, AUGs); - GlobalValue *gv = new GlobalVariable(M, AT, false, - GlobalValue::AppendingLinkage, - Init, "llvm.used"); - gv->setSection("llvm.metadata"); - } - - // All of the functions may be used by global variables or the named - // globals. Loop through them and create a new, external functions that - // can be "used", instead of ones with bodies. - std::vector<Function*> NewFunctions; - - Function *Last = --M.end(); // Figure out where the last real fn is. - - for (Module::iterator I = M.begin(); ; ++I) { - if (std::find(Named.begin(), Named.end(), &*I) == Named.end()) { - Function *New = Function::Create(I->getFunctionType(), - GlobalValue::ExternalLinkage); - New->copyAttributesFrom(I); - - // If it's not the named function, delete the body of the function - I->dropAllReferences(); - - M.getFunctionList().push_back(New); - NewFunctions.push_back(New); - New->takeName(I); + if (I->hasLocalLinkage()) + I->setVisibility(GlobalValue::HiddenVisibility); + I->setLinkage(GlobalValue::ExternalLinkage); + if (deleteStuff == Named.count(I)) + I->deleteBody(); } - if (&*I == Last) break; // Stop after processing the last function - } - - // Now that we have replacements all set up, loop through the module, - // deleting the old functions, replacing them with the newly created - // functions. - if (!NewFunctions.empty()) { - unsigned FuncNum = 0; - Module::iterator I = M.begin(); - do { - if (std::find(Named.begin(), Named.end(), &*I) == Named.end()) { - // Make everything that uses the old function use the new dummy fn - I->replaceAllUsesWith(NewFunctions[FuncNum++]); - - Function *Old = I; - ++I; // Move the iterator to the new function - - // Delete the old function! - M.getFunctionList().erase(Old); - - } else { - ++I; // Skip the function we are extracting - } - } while (&*I != NewFunctions[0]); - } - return true; } }; @@ -170,6 +77,6 @@ namespace { } ModulePass *llvm::createGVExtractionPass(std::vector<GlobalValue*>& GVs, - bool deleteFn, bool relinkCallees) { - return new GVExtractorPass(GVs, deleteFn, relinkCallees); + bool deleteFn) { + return new GVExtractorPass(GVs, deleteFn); } diff --git a/contrib/llvm/lib/Transforms/IPO/FunctionAttrs.cpp b/contrib/llvm/lib/Transforms/IPO/FunctionAttrs.cpp index 9bd7af6..6165ba0 100644 --- a/contrib/llvm/lib/Transforms/IPO/FunctionAttrs.cpp +++ b/contrib/llvm/lib/Transforms/IPO/FunctionAttrs.cpp @@ -41,7 +41,7 @@ STATISTIC(NumNoAlias, "Number of function returns marked noalias"); namespace { struct FunctionAttrs : public CallGraphSCCPass { static char ID; // Pass identification, replacement for typeid - FunctionAttrs() : CallGraphSCCPass(&ID) {} + FunctionAttrs() : CallGraphSCCPass(ID) {} // runOnSCC - Analyze the SCC, performing the transformation if possible. bool runOnSCC(CallGraphSCC &SCC); @@ -69,8 +69,8 @@ namespace { } char FunctionAttrs::ID = 0; -static RegisterPass<FunctionAttrs> -X("functionattrs", "Deduce function attributes"); +INITIALIZE_PASS(FunctionAttrs, "functionattrs", + "Deduce function attributes", false, false); Pass *llvm::createFunctionAttrsPass() { return new FunctionAttrs(); } @@ -162,14 +162,14 @@ bool FunctionAttrs::AddReadAttrs(const CallGraphSCC &SCC) { // Some instructions can be ignored even if they read or write memory. // Detect these now, skipping to the next instruction if one is found. - CallSite CS = CallSite::get(I); - if (CS.getInstruction() && CS.getCalledFunction()) { + CallSite CS(cast<Value>(I)); + if (CS && CS.getCalledFunction()) { // Ignore calls to functions in the same SCC. if (SCCNodes.count(CS.getCalledFunction())) continue; // Ignore intrinsics that only access local memory. if (unsigned id = CS.getCalledFunction()->getIntrinsicID()) - if (AliasAnalysis::getModRefBehavior(id) == + if (AliasAnalysis::getIntrinsicModRefBehavior(id) == AliasAnalysis::AccessesArguments) { // Check that all pointer arguments point to local memory. for (CallSite::arg_iterator CI = CS.arg_begin(), CE = CS.arg_end(); diff --git a/contrib/llvm/lib/Transforms/IPO/GlobalDCE.cpp b/contrib/llvm/lib/Transforms/IPO/GlobalDCE.cpp index 44216a6..aa18601 100644 --- a/contrib/llvm/lib/Transforms/IPO/GlobalDCE.cpp +++ b/contrib/llvm/lib/Transforms/IPO/GlobalDCE.cpp @@ -31,7 +31,7 @@ STATISTIC(NumVariables, "Number of global variables removed"); namespace { struct GlobalDCE : public ModulePass { static char ID; // Pass identification, replacement for typeid - GlobalDCE() : ModulePass(&ID) {} + GlobalDCE() : ModulePass(ID) {} // run - Do the GlobalDCE pass on the specified module, optionally updating // the specified callgraph to reflect the changes. @@ -51,7 +51,8 @@ namespace { } char GlobalDCE::ID = 0; -static RegisterPass<GlobalDCE> X("globaldce", "Dead Global Elimination"); +INITIALIZE_PASS(GlobalDCE, "globaldce", + "Dead Global Elimination", false, false); ModulePass *llvm::createGlobalDCEPass() { return new GlobalDCE(); } diff --git a/contrib/llvm/lib/Transforms/IPO/GlobalOpt.cpp b/contrib/llvm/lib/Transforms/IPO/GlobalOpt.cpp index 735a1c4..a77af54 100644 --- a/contrib/llvm/lib/Transforms/IPO/GlobalOpt.cpp +++ b/contrib/llvm/lib/Transforms/IPO/GlobalOpt.cpp @@ -59,7 +59,7 @@ namespace { virtual void getAnalysisUsage(AnalysisUsage &AU) const { } static char ID; // Pass identification, replacement for typeid - GlobalOpt() : ModulePass(&ID) {} + GlobalOpt() : ModulePass(ID) {} bool runOnModule(Module &M); @@ -74,7 +74,8 @@ namespace { } char GlobalOpt::ID = 0; -static RegisterPass<GlobalOpt> X("globalopt", "Global Variable Optimizer"); +INITIALIZE_PASS(GlobalOpt, "globalopt", + "Global Variable Optimizer", false, false); ModulePass *llvm::createGlobalOptimizerPass() { return new GlobalOpt(); } @@ -1467,7 +1468,7 @@ static bool TryToOptimizeStoreOfMallocToGlobal(GlobalVariable *GV, TargetData *TD) { if (!TD) return false; - + // If this is a malloc of an abstract type, don't touch it. if (!AllocTy->isSized()) return false; @@ -2077,7 +2078,7 @@ static bool isSimpleEnoughPointerToCommit(Constant *C) { return false; // The first index must be zero. - ConstantInt *CI = dyn_cast<ConstantInt>(*next(CE->op_begin())); + ConstantInt *CI = dyn_cast<ConstantInt>(*llvm::next(CE->op_begin())); if (!CI || !CI->isZero()) return false; // The remaining indices must be compile-time known integers within the @@ -2302,7 +2303,8 @@ static bool EvaluateFunction(Function *F, Constant *&RetVal, if (isa<InlineAsm>(CI->getCalledValue())) return false; // Resolve function pointers. - Function *Callee = dyn_cast<Function>(getVal(Values, CI->getCalledValue())); + Function *Callee = dyn_cast<Function>(getVal(Values, + CI->getCalledValue())); if (!Callee) return false; // Cannot resolve. SmallVector<Constant*, 8> Formals; diff --git a/contrib/llvm/lib/Transforms/IPO/IPConstantPropagation.cpp b/contrib/llvm/lib/Transforms/IPO/IPConstantPropagation.cpp index e4db235..1b3cf78 100644 --- a/contrib/llvm/lib/Transforms/IPO/IPConstantPropagation.cpp +++ b/contrib/llvm/lib/Transforms/IPO/IPConstantPropagation.cpp @@ -35,7 +35,7 @@ namespace { /// struct IPCP : public ModulePass { static char ID; // Pass identification, replacement for typeid - IPCP() : ModulePass(&ID) {} + IPCP() : ModulePass(ID) {} bool runOnModule(Module &M); private: @@ -45,8 +45,8 @@ namespace { } char IPCP::ID = 0; -static RegisterPass<IPCP> -X("ipconstprop", "Interprocedural constant propagation"); +INITIALIZE_PASS(IPCP, "ipconstprop", + "Interprocedural constant propagation", false, false); ModulePass *llvm::createIPConstantPropagationPass() { return new IPCP(); } @@ -94,7 +94,7 @@ bool IPCP::PropagateConstantsIntoArguments(Function &F) { if (!isa<CallInst>(U) && !isa<InvokeInst>(U)) return false; - CallSite CS = CallSite::get(cast<Instruction>(U)); + CallSite CS(cast<Instruction>(U)); if (!CS.isCallee(UI)) return false; @@ -219,7 +219,7 @@ bool IPCP::PropagateConstantReturn(Function &F) { // constant. bool MadeChange = false; for (Value::use_iterator UI = F.use_begin(), E = F.use_end(); UI != E; ++UI) { - CallSite CS = CallSite::get(*UI); + CallSite CS(*UI); Instruction* Call = CS.getInstruction(); // Not a call instruction or a call instruction that's not calling F diff --git a/contrib/llvm/lib/Transforms/IPO/InlineAlways.cpp b/contrib/llvm/lib/Transforms/IPO/InlineAlways.cpp index 8e312e7..ecc60ad 100644 --- a/contrib/llvm/lib/Transforms/IPO/InlineAlways.cpp +++ b/contrib/llvm/lib/Transforms/IPO/InlineAlways.cpp @@ -36,7 +36,7 @@ namespace { InlineCostAnalyzer CA; public: // Use extremely low threshold. - AlwaysInliner() : Inliner(&ID, -2000000000) {} + AlwaysInliner() : Inliner(ID, -2000000000) {} static char ID; // Pass identification, replacement for typeid InlineCost getInlineCost(CallSite CS) { return CA.getInlineCost(CS, NeverInline); @@ -61,8 +61,8 @@ namespace { } char AlwaysInliner::ID = 0; -static RegisterPass<AlwaysInliner> -X("always-inline", "Inliner for always_inline functions"); +INITIALIZE_PASS(AlwaysInliner, "always-inline", + "Inliner for always_inline functions", false, false); Pass *llvm::createAlwaysInlinerPass() { return new AlwaysInliner(); } diff --git a/contrib/llvm/lib/Transforms/IPO/InlineSimple.cpp b/contrib/llvm/lib/Transforms/IPO/InlineSimple.cpp index 74b4a1c..9c6637d 100644 --- a/contrib/llvm/lib/Transforms/IPO/InlineSimple.cpp +++ b/contrib/llvm/lib/Transforms/IPO/InlineSimple.cpp @@ -33,8 +33,8 @@ namespace { SmallPtrSet<const Function*, 16> NeverInline; InlineCostAnalyzer CA; public: - SimpleInliner() : Inliner(&ID) {} - SimpleInliner(int Threshold) : Inliner(&ID, Threshold) {} + SimpleInliner() : Inliner(ID) {} + SimpleInliner(int Threshold) : Inliner(ID, Threshold) {} static char ID; // Pass identification, replacement for typeid InlineCost getInlineCost(CallSite CS) { return CA.getInlineCost(CS, NeverInline); @@ -56,8 +56,8 @@ namespace { } char SimpleInliner::ID = 0; -static RegisterPass<SimpleInliner> -X("inline", "Function Integration/Inlining"); +INITIALIZE_PASS(SimpleInliner, "inline", + "Function Integration/Inlining", false, false); Pass *llvm::createFunctionInliningPass() { return new SimpleInliner(); } diff --git a/contrib/llvm/lib/Transforms/IPO/Inliner.cpp b/contrib/llvm/lib/Transforms/IPO/Inliner.cpp index 9bb01f5..4983e8e 100644 --- a/contrib/llvm/lib/Transforms/IPO/Inliner.cpp +++ b/contrib/llvm/lib/Transforms/IPO/Inliner.cpp @@ -48,10 +48,10 @@ HintThreshold("inlinehint-threshold", cl::Hidden, cl::init(325), // Threshold to use when optsize is specified (and there is no -inline-limit). const int OptSizeThreshold = 75; -Inliner::Inliner(void *ID) +Inliner::Inliner(char &ID) : CallGraphSCCPass(ID), InlineThreshold(InlineLimit) {} -Inliner::Inliner(void *ID, int Threshold) +Inliner::Inliner(char &ID, int Threshold) : CallGraphSCCPass(ID), InlineThreshold(Threshold) {} /// getAnalysisUsage - For this class, we declare that we require and preserve @@ -238,11 +238,11 @@ bool Inliner::shouldInline(CallSite CS) { bool someOuterCallWouldNotBeInlined = false; for (Value::use_iterator I = Caller->use_begin(), E =Caller->use_end(); I != E; ++I) { - CallSite CS2 = CallSite::get(*I); + CallSite CS2(*I); // If this isn't a call to Caller (it could be some other sort // of reference) skip it. - if (CS2.getInstruction() == 0 || CS2.getCalledFunction() != Caller) + if (!CS2 || CS2.getCalledFunction() != Caller) continue; InlineCost IC2 = getInlineCost(CS2); @@ -334,10 +334,10 @@ bool Inliner::runOnSCC(CallGraphSCC &SCC) { for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) { - CallSite CS = CallSite::get(I); + CallSite CS(cast<Value>(I)); // If this isn't a call, or it is a call to an intrinsic, it can // never be inlined. - if (CS.getInstruction() == 0 || isa<IntrinsicInst>(I)) + if (!CS || isa<IntrinsicInst>(I)) continue; // If this is a direct call to an external function, we can never inline diff --git a/contrib/llvm/lib/Transforms/IPO/Internalize.cpp b/contrib/llvm/lib/Transforms/IPO/Internalize.cpp index 47abb7d..a1d919f 100644 --- a/contrib/llvm/lib/Transforms/IPO/Internalize.cpp +++ b/contrib/llvm/lib/Transforms/IPO/Internalize.cpp @@ -63,11 +63,11 @@ namespace { } // end anonymous namespace char InternalizePass::ID = 0; -static RegisterPass<InternalizePass> -X("internalize", "Internalize Global Symbols"); +INITIALIZE_PASS(InternalizePass, "internalize", + "Internalize Global Symbols", false, false); InternalizePass::InternalizePass(bool AllButMain) - : ModulePass(&ID), AllButMain(AllButMain){ + : ModulePass(ID), AllButMain(AllButMain){ if (!APIFile.empty()) // If a filename is specified, use it. LoadFile(APIFile.c_str()); if (!APIList.empty()) // If a list is specified, use it as well. @@ -75,7 +75,7 @@ InternalizePass::InternalizePass(bool AllButMain) } InternalizePass::InternalizePass(const std::vector<const char *>&exportList) - : ModulePass(&ID), AllButMain(false){ + : ModulePass(ID), AllButMain(false){ for(std::vector<const char *>::const_iterator itr = exportList.begin(); itr != exportList.end(); itr++) { ExternalNames.insert(*itr); diff --git a/contrib/llvm/lib/Transforms/IPO/LoopExtractor.cpp b/contrib/llvm/lib/Transforms/IPO/LoopExtractor.cpp index cb81330..f88dff6 100644 --- a/contrib/llvm/lib/Transforms/IPO/LoopExtractor.cpp +++ b/contrib/llvm/lib/Transforms/IPO/LoopExtractor.cpp @@ -37,7 +37,7 @@ namespace { unsigned NumLoops; explicit LoopExtractor(unsigned numLoops = ~0) - : LoopPass(&ID), NumLoops(numLoops) {} + : LoopPass(ID), NumLoops(numLoops) {} virtual bool runOnLoop(Loop *L, LPPassManager &LPM); @@ -50,8 +50,8 @@ namespace { } char LoopExtractor::ID = 0; -static RegisterPass<LoopExtractor> -X("loop-extract", "Extract loops into new functions"); +INITIALIZE_PASS(LoopExtractor, "loop-extract", + "Extract loops into new functions", false, false); namespace { /// SingleLoopExtractor - For bugpoint. @@ -62,8 +62,8 @@ namespace { } // End anonymous namespace char SingleLoopExtractor::ID = 0; -static RegisterPass<SingleLoopExtractor> -Y("loop-extract-single", "Extract at most one loop into a new function"); +INITIALIZE_PASS(SingleLoopExtractor, "loop-extract-single", + "Extract at most one loop into a new function", false, false); // createLoopExtractorPass - This pass extracts all natural loops from the // program into a function if it can. @@ -147,27 +147,26 @@ namespace { std::vector<std::pair<std::string, std::string> > BlocksToNotExtractByName; public: static char ID; // Pass identification, replacement for typeid - explicit BlockExtractorPass(const std::vector<BasicBlock*> &B) - : ModulePass(&ID), BlocksToNotExtract(B) { + BlockExtractorPass() : ModulePass(ID) { if (!BlockFile.empty()) LoadFile(BlockFile.c_str()); } - BlockExtractorPass() : ModulePass(&ID) {} bool runOnModule(Module &M); }; } char BlockExtractorPass::ID = 0; -static RegisterPass<BlockExtractorPass> -XX("extract-blocks", "Extract Basic Blocks From Module (for bugpoint use)"); +INITIALIZE_PASS(BlockExtractorPass, "extract-blocks", + "Extract Basic Blocks From Module (for bugpoint use)", + false, false); // createBlockExtractorPass - This pass extracts all blocks (except those // specified in the argument list) from the functions in the module. // -ModulePass *llvm::createBlockExtractorPass(const std::vector<BasicBlock*> &BTNE) +ModulePass *llvm::createBlockExtractorPass() { - return new BlockExtractorPass(BTNE); + return new BlockExtractorPass(); } void BlockExtractorPass::LoadFile(const char *Filename) { diff --git a/contrib/llvm/lib/Transforms/IPO/LowerSetJmp.cpp b/contrib/llvm/lib/Transforms/IPO/LowerSetJmp.cpp index 76cfef8..6c715de 100644 --- a/contrib/llvm/lib/Transforms/IPO/LowerSetJmp.cpp +++ b/contrib/llvm/lib/Transforms/IPO/LowerSetJmp.cpp @@ -109,7 +109,7 @@ namespace { bool IsTransformableFunction(StringRef Name); public: static char ID; // Pass identification, replacement for typeid - LowerSetJmp() : ModulePass(&ID) {} + LowerSetJmp() : ModulePass(ID) {} void visitCallInst(CallInst& CI); void visitInvokeInst(InvokeInst& II); @@ -122,7 +122,7 @@ namespace { } // end anonymous namespace char LowerSetJmp::ID = 0; -static RegisterPass<LowerSetJmp> X("lowersetjmp", "Lower Set Jump"); +INITIALIZE_PASS(LowerSetJmp, "lowersetjmp", "Lower Set Jump", false, false); // run - Run the transformation on the program. We grab the function // prototypes for longjmp and setjmp. If they are used in the program, diff --git a/contrib/llvm/lib/Transforms/IPO/MergeFunctions.cpp b/contrib/llvm/lib/Transforms/IPO/MergeFunctions.cpp index aeeafe7..5d838f9 100644 --- a/contrib/llvm/lib/Transforms/IPO/MergeFunctions.cpp +++ b/contrib/llvm/lib/Transforms/IPO/MergeFunctions.cpp @@ -29,44 +29,27 @@ // // Many functions have their address taken by the virtual function table for // the object they belong to. However, as long as it's only used for a lookup -// and call, this is irrelevant, and we'd like to fold such implementations. +// and call, this is irrelevant, and we'd like to fold such functions. // -// * use SCC to cut down on pair-wise comparisons and solve larger cycles. +// * switch from n^2 pair-wise comparisons to an n-way comparison for each +// bucket. // -// The current implementation loops over a pair-wise comparison of all -// functions in the program where the two functions in the pair are treated as -// assumed to be equal until proven otherwise. We could both use fewer -// comparisons and optimize more complex cases if we used strongly connected -// components of the call graph. -// -// * be smarter about bitcast. +// * be smarter about bitcasts. // // In order to fold functions, we will sometimes add either bitcast instructions // or bitcast constant expressions. Unfortunately, this can confound further // analysis since the two functions differ where one has a bitcast and the -// other doesn't. We should learn to peer through bitcasts without imposing bad -// performance properties. -// -// * don't emit aliases for Mach-O. -// -// Mach-O doesn't support aliases which means that we must avoid introducing -// them in the bitcode on architectures which don't support them, such as -// Mac OSX. There's a few approaches to this problem; -// a) teach codegen to lower global aliases to thunks on platforms which don't -// support them. -// b) always emit thunks, and create a separate thunk-to-alias pass which -// runs on ELF systems. This has the added benefit of transforming other -// thunks such as those produced by a C++ frontend into aliases when legal -// to do so. +// other doesn't. We should learn to look through bitcasts. // //===----------------------------------------------------------------------===// #define DEBUG_TYPE "mergefunc" #include "llvm/Transforms/IPO.h" -#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/Statistic.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/Constants.h" #include "llvm/InlineAsm.h" #include "llvm/Instructions.h" @@ -76,68 +59,103 @@ #include "llvm/Support/CallSite.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/IRBuilder.h" +#include "llvm/Support/ValueHandle.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetData.h" -#include <map> #include <vector> using namespace llvm; STATISTIC(NumFunctionsMerged, "Number of functions merged"); namespace { + /// MergeFunctions finds functions which will generate identical machine code, + /// by considering all pointer types to be equivalent. Once identified, + /// MergeFunctions will fold them by replacing a call to one to a call to a + /// bitcast of the other. + /// class MergeFunctions : public ModulePass { public: - static char ID; // Pass identification, replacement for typeid - MergeFunctions() : ModulePass(&ID) {} + static char ID; + MergeFunctions() : ModulePass(ID) {} bool runOnModule(Module &M); private: - bool isEquivalentGEP(const GetElementPtrInst *GEP1, - const GetElementPtrInst *GEP2); - - bool equals(const BasicBlock *BB1, const BasicBlock *BB2); - bool equals(const Function *F, const Function *G); + /// MergeTwoFunctions - Merge two equivalent functions. Upon completion, G + /// may be deleted, or may be converted into a thunk. In either case, it + /// should never be visited again. + void MergeTwoFunctions(Function *F, Function *G) const; - bool compare(const Value *V1, const Value *V2); + /// WriteThunk - Replace G with a simple tail call to bitcast(F). Also + /// replace direct uses of G with bitcast(F). + void WriteThunk(Function *F, Function *G) const; - const Function *LHS, *RHS; - typedef DenseMap<const Value *, unsigned long> IDMap; - IDMap Map; - DenseMap<const Function *, IDMap> Domains; - DenseMap<const Function *, unsigned long> DomainCount; TargetData *TD; }; } char MergeFunctions::ID = 0; -static RegisterPass<MergeFunctions> X("mergefunc", "Merge Functions"); +INITIALIZE_PASS(MergeFunctions, "mergefunc", "Merge Functions", false, false); ModulePass *llvm::createMergeFunctionsPass() { return new MergeFunctions(); } -// ===----------------------------------------------------------------------=== -// Comparison of functions -// ===----------------------------------------------------------------------=== +namespace { +/// FunctionComparator - Compares two functions to determine whether or not +/// they will generate machine code with the same behaviour. TargetData is +/// used if available. The comparator always fails conservatively (erring on the +/// side of claiming that two functions are different). +class FunctionComparator { +public: + FunctionComparator(const TargetData *TD, const Function *F1, + const Function *F2) + : F1(F1), F2(F2), TD(TD), IDMap1Count(0), IDMap2Count(0) {} + + /// Compare - test whether the two functions have equivalent behaviour. + bool Compare(); + +private: + /// Compare - test whether two basic blocks have equivalent behaviour. + bool Compare(const BasicBlock *BB1, const BasicBlock *BB2); + + /// Enumerate - Assign or look up previously assigned numbers for the two + /// values, and return whether the numbers are equal. Numbers are assigned in + /// the order visited. + bool Enumerate(const Value *V1, const Value *V2); + + /// isEquivalentOperation - Compare two Instructions for equivalence, similar + /// to Instruction::isSameOperationAs but with modifications to the type + /// comparison. + bool isEquivalentOperation(const Instruction *I1, + const Instruction *I2) const; + + /// isEquivalentGEP - Compare two GEPs for equivalent pointer arithmetic. + bool isEquivalentGEP(const GEPOperator *GEP1, const GEPOperator *GEP2); + bool isEquivalentGEP(const GetElementPtrInst *GEP1, + const GetElementPtrInst *GEP2) { + return isEquivalentGEP(cast<GEPOperator>(GEP1), cast<GEPOperator>(GEP2)); + } -static unsigned long hash(const Function *F) { - const FunctionType *FTy = F->getFunctionType(); + /// isEquivalentType - Compare two Types, treating all pointer types as equal. + bool isEquivalentType(const Type *Ty1, const Type *Ty2) const; - FoldingSetNodeID ID; - ID.AddInteger(F->size()); - ID.AddInteger(F->getCallingConv()); - ID.AddBoolean(F->hasGC()); - ID.AddBoolean(FTy->isVarArg()); - ID.AddInteger(FTy->getReturnType()->getTypeID()); - for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i) - ID.AddInteger(FTy->getParamType(i)->getTypeID()); - return ID.ComputeHash(); + // The two functions undergoing comparison. + const Function *F1, *F2; + + const TargetData *TD; + + typedef DenseMap<const Value *, unsigned long> IDMap; + IDMap Map1, Map2; + unsigned long IDMap1Count, IDMap2Count; +}; } -/// isEquivalentType - any two pointers are equivalent. Otherwise, standard -/// type equivalence rules apply. -static bool isEquivalentType(const Type *Ty1, const Type *Ty2) { +/// isEquivalentType - any two pointers in the same address space are +/// equivalent. Otherwise, standard type equivalence rules apply. +bool FunctionComparator::isEquivalentType(const Type *Ty1, + const Type *Ty2) const { if (Ty1 == Ty2) return true; if (Ty1->getTypeID() != Ty2->getTypeID()) @@ -184,21 +202,6 @@ static bool isEquivalentType(const Type *Ty1, const Type *Ty2) { return true; } - case Type::UnionTyID: { - const UnionType *UTy1 = cast<UnionType>(Ty1); - const UnionType *UTy2 = cast<UnionType>(Ty2); - - // TODO: we could be fancy with union(A, union(A, B)) === union(A, B), etc. - if (UTy1->getNumElements() != UTy2->getNumElements()) - return false; - - for (unsigned i = 0, e = UTy1->getNumElements(); i != e; ++i) { - if (!isEquivalentType(UTy1->getElementType(i), UTy2->getElementType(i))) - return false; - } - return true; - } - case Type::FunctionTyID: { const FunctionType *FTy1 = cast<FunctionType>(Ty1); const FunctionType *FTy2 = cast<FunctionType>(Ty2); @@ -216,11 +219,18 @@ static bool isEquivalentType(const Type *Ty1, const Type *Ty2) { return true; } - case Type::ArrayTyID: + case Type::ArrayTyID: { + const ArrayType *ATy1 = cast<ArrayType>(Ty1); + const ArrayType *ATy2 = cast<ArrayType>(Ty2); + return ATy1->getNumElements() == ATy2->getNumElements() && + isEquivalentType(ATy1->getElementType(), ATy2->getElementType()); + } + case Type::VectorTyID: { - const SequentialType *STy1 = cast<SequentialType>(Ty1); - const SequentialType *STy2 = cast<SequentialType>(Ty2); - return isEquivalentType(STy1->getElementType(), STy2->getElementType()); + const VectorType *VTy1 = cast<VectorType>(Ty1); + const VectorType *VTy2 = cast<VectorType>(Ty2); + return VTy1->getNumElements() == VTy2->getNumElements() && + isEquivalentType(VTy1->getElementType(), VTy2->getElementType()); } } } @@ -228,8 +238,8 @@ static bool isEquivalentType(const Type *Ty1, const Type *Ty2) { /// isEquivalentOperation - determine whether the two operations are the same /// except that pointer-to-A and pointer-to-B are equivalent. This should be /// kept in sync with Instruction::isSameOperationAs. -static bool -isEquivalentOperation(const Instruction *I1, const Instruction *I2) { +bool FunctionComparator::isEquivalentOperation(const Instruction *I1, + const Instruction *I2) const { if (I1->getOpcode() != I2->getOpcode() || I1->getNumOperands() != I2->getNumOperands() || !isEquivalentType(I1->getType(), I2->getType()) || @@ -281,18 +291,15 @@ isEquivalentOperation(const Instruction *I1, const Instruction *I2) { return true; } -bool MergeFunctions::isEquivalentGEP(const GetElementPtrInst *GEP1, - const GetElementPtrInst *GEP2) { +/// isEquivalentGEP - determine whether two GEP operations perform the same +/// underlying arithmetic. +bool FunctionComparator::isEquivalentGEP(const GEPOperator *GEP1, + const GEPOperator *GEP2) { + // When we have target data, we can reduce the GEP down to the value in bytes + // added to the address. if (TD && GEP1->hasAllConstantIndices() && GEP2->hasAllConstantIndices()) { - SmallVector<Value *, 8> Indices1, Indices2; - for (GetElementPtrInst::const_op_iterator I = GEP1->idx_begin(), - E = GEP1->idx_end(); I != E; ++I) { - Indices1.push_back(*I); - } - for (GetElementPtrInst::const_op_iterator I = GEP2->idx_begin(), - E = GEP2->idx_end(); I != E; ++I) { - Indices2.push_back(*I); - } + SmallVector<Value *, 8> Indices1(GEP1->idx_begin(), GEP1->idx_end()); + SmallVector<Value *, 8> Indices2(GEP2->idx_begin(), GEP2->idx_end()); uint64_t Offset1 = TD->getIndexedOffset(GEP1->getPointerOperandType(), Indices1.data(), Indices1.size()); uint64_t Offset2 = TD->getIndexedOffset(GEP2->getPointerOperandType(), @@ -300,7 +307,6 @@ bool MergeFunctions::isEquivalentGEP(const GetElementPtrInst *GEP1, return Offset1 == Offset2; } - // Equivalent types aren't enough. if (GEP1->getPointerOperand()->getType() != GEP2->getPointerOperand()->getType()) return false; @@ -309,19 +315,26 @@ bool MergeFunctions::isEquivalentGEP(const GetElementPtrInst *GEP1, return false; for (unsigned i = 0, e = GEP1->getNumOperands(); i != e; ++i) { - if (!compare(GEP1->getOperand(i), GEP2->getOperand(i))) + if (!Enumerate(GEP1->getOperand(i), GEP2->getOperand(i))) return false; } return true; } -bool MergeFunctions::compare(const Value *V1, const Value *V2) { - if (V1 == LHS || V1 == RHS) - if (V2 == LHS || V2 == RHS) - return true; +/// Enumerate - Compare two values used by the two functions under pair-wise +/// comparison. If this is the first time the values are seen, they're added to +/// the mapping so that we will detect mismatches on next use. +bool FunctionComparator::Enumerate(const Value *V1, const Value *V2) { + // Check for function @f1 referring to itself and function @f2 referring to + // itself, or referring to each other, or both referring to either of them. + // They're all equivalent if the two functions are otherwise equivalent. + if (V1 == F1 && V2 == F2) + return true; + if (V1 == F2 && V2 == F1) + return true; - // TODO: constant expressions in terms of LHS and RHS + // TODO: constant expressions with GEP or references to F1 or F2. if (isa<Constant>(V1)) return V1 == V2; @@ -332,228 +345,138 @@ bool MergeFunctions::compare(const Value *V1, const Value *V2) { IA1->getConstraintString() == IA2->getConstraintString(); } - // We enumerate constants globally and arguments, basic blocks or - // instructions within the function they belong to. - const Function *Domain1 = NULL; - if (const Argument *A = dyn_cast<Argument>(V1)) { - Domain1 = A->getParent(); - } else if (const BasicBlock *BB = dyn_cast<BasicBlock>(V1)) { - Domain1 = BB->getParent(); - } else if (const Instruction *I = dyn_cast<Instruction>(V1)) { - Domain1 = I->getParent()->getParent(); - } - - const Function *Domain2 = NULL; - if (const Argument *A = dyn_cast<Argument>(V2)) { - Domain2 = A->getParent(); - } else if (const BasicBlock *BB = dyn_cast<BasicBlock>(V2)) { - Domain2 = BB->getParent(); - } else if (const Instruction *I = dyn_cast<Instruction>(V2)) { - Domain2 = I->getParent()->getParent(); - } - - if (Domain1 != Domain2) - if (Domain1 != LHS && Domain1 != RHS) - if (Domain2 != LHS && Domain2 != RHS) - return false; - - IDMap &Map1 = Domains[Domain1]; unsigned long &ID1 = Map1[V1]; if (!ID1) - ID1 = ++DomainCount[Domain1]; + ID1 = ++IDMap1Count; - IDMap &Map2 = Domains[Domain2]; unsigned long &ID2 = Map2[V2]; if (!ID2) - ID2 = ++DomainCount[Domain2]; + ID2 = ++IDMap2Count; return ID1 == ID2; } -bool MergeFunctions::equals(const BasicBlock *BB1, const BasicBlock *BB2) { - BasicBlock::const_iterator FI = BB1->begin(), FE = BB1->end(); - BasicBlock::const_iterator GI = BB2->begin(), GE = BB2->end(); +/// Compare - test whether two basic blocks have equivalent behaviour. +bool FunctionComparator::Compare(const BasicBlock *BB1, const BasicBlock *BB2) { + BasicBlock::const_iterator F1I = BB1->begin(), F1E = BB1->end(); + BasicBlock::const_iterator F2I = BB2->begin(), F2E = BB2->end(); do { - if (!compare(FI, GI)) + if (!Enumerate(F1I, F2I)) return false; - if (isa<GetElementPtrInst>(FI) && isa<GetElementPtrInst>(GI)) { - const GetElementPtrInst *GEP1 = cast<GetElementPtrInst>(FI); - const GetElementPtrInst *GEP2 = cast<GetElementPtrInst>(GI); + if (const GetElementPtrInst *GEP1 = dyn_cast<GetElementPtrInst>(F1I)) { + const GetElementPtrInst *GEP2 = dyn_cast<GetElementPtrInst>(F2I); + if (!GEP2) + return false; - if (!compare(GEP1->getPointerOperand(), GEP2->getPointerOperand())) + if (!Enumerate(GEP1->getPointerOperand(), GEP2->getPointerOperand())) return false; if (!isEquivalentGEP(GEP1, GEP2)) return false; } else { - if (!isEquivalentOperation(FI, GI)) + if (!isEquivalentOperation(F1I, F2I)) return false; - for (unsigned i = 0, e = FI->getNumOperands(); i != e; ++i) { - Value *OpF = FI->getOperand(i); - Value *OpG = GI->getOperand(i); + assert(F1I->getNumOperands() == F2I->getNumOperands()); + for (unsigned i = 0, e = F1I->getNumOperands(); i != e; ++i) { + Value *OpF1 = F1I->getOperand(i); + Value *OpF2 = F2I->getOperand(i); - if (!compare(OpF, OpG)) + if (!Enumerate(OpF1, OpF2)) return false; - if (OpF->getValueID() != OpG->getValueID() || - !isEquivalentType(OpF->getType(), OpG->getType())) + if (OpF1->getValueID() != OpF2->getValueID() || + !isEquivalentType(OpF1->getType(), OpF2->getType())) return false; } } - ++FI, ++GI; - } while (FI != FE && GI != GE); + ++F1I, ++F2I; + } while (F1I != F1E && F2I != F2E); - return FI == FE && GI == GE; + return F1I == F1E && F2I == F2E; } -bool MergeFunctions::equals(const Function *F, const Function *G) { +/// Compare - test whether the two functions have equivalent behaviour. +bool FunctionComparator::Compare() { // We need to recheck everything, but check the things that weren't included // in the hash first. - if (F->getAttributes() != G->getAttributes()) + if (F1->getAttributes() != F2->getAttributes()) return false; - if (F->hasGC() != G->hasGC()) + if (F1->hasGC() != F2->hasGC()) return false; - if (F->hasGC() && F->getGC() != G->getGC()) + if (F1->hasGC() && F1->getGC() != F2->getGC()) return false; - if (F->hasSection() != G->hasSection()) + if (F1->hasSection() != F2->hasSection()) return false; - if (F->hasSection() && F->getSection() != G->getSection()) + if (F1->hasSection() && F1->getSection() != F2->getSection()) return false; - if (F->isVarArg() != G->isVarArg()) + if (F1->isVarArg() != F2->isVarArg()) return false; // TODO: if it's internal and only used in direct calls, we could handle this // case too. - if (F->getCallingConv() != G->getCallingConv()) + if (F1->getCallingConv() != F2->getCallingConv()) return false; - if (!isEquivalentType(F->getFunctionType(), G->getFunctionType())) + if (!isEquivalentType(F1->getFunctionType(), F2->getFunctionType())) return false; - assert(F->arg_size() == G->arg_size() && + assert(F1->arg_size() == F2->arg_size() && "Identical functions have a different number of args."); - LHS = F; - RHS = G; - // Visit the arguments so that they get enumerated in the order they're // passed in. - for (Function::const_arg_iterator fi = F->arg_begin(), gi = G->arg_begin(), - fe = F->arg_end(); fi != fe; ++fi, ++gi) { - if (!compare(fi, gi)) + for (Function::const_arg_iterator f1i = F1->arg_begin(), + f2i = F2->arg_begin(), f1e = F1->arg_end(); f1i != f1e; ++f1i, ++f2i) { + if (!Enumerate(f1i, f2i)) llvm_unreachable("Arguments repeat"); } - SmallVector<const BasicBlock *, 8> FBBs, GBBs; - SmallSet<const BasicBlock *, 128> VisitedBBs; // in terms of F. - FBBs.push_back(&F->getEntryBlock()); - GBBs.push_back(&G->getEntryBlock()); - VisitedBBs.insert(FBBs[0]); - while (!FBBs.empty()) { - const BasicBlock *FBB = FBBs.pop_back_val(); - const BasicBlock *GBB = GBBs.pop_back_val(); - if (!compare(FBB, GBB) || !equals(FBB, GBB)) { - Domains.clear(); - DomainCount.clear(); - return false; - } - const TerminatorInst *FTI = FBB->getTerminator(); - const TerminatorInst *GTI = GBB->getTerminator(); - assert(FTI->getNumSuccessors() == GTI->getNumSuccessors()); - for (unsigned i = 0, e = FTI->getNumSuccessors(); i != e; ++i) { - if (!VisitedBBs.insert(FTI->getSuccessor(i))) - continue; - FBBs.push_back(FTI->getSuccessor(i)); - GBBs.push_back(GTI->getSuccessor(i)); - } - } + // We do a CFG-ordered walk since the actual ordering of the blocks in the + // linked list is immaterial. Our walk starts at the entry block for both + // functions, then takes each block from each terminator in order. As an + // artifact, this also means that unreachable blocks are ignored. + SmallVector<const BasicBlock *, 8> F1BBs, F2BBs; + SmallSet<const BasicBlock *, 128> VisitedBBs; // in terms of F1. - Domains.clear(); - DomainCount.clear(); - return true; -} + F1BBs.push_back(&F1->getEntryBlock()); + F2BBs.push_back(&F2->getEntryBlock()); -// ===----------------------------------------------------------------------=== -// Folding of functions -// ===----------------------------------------------------------------------=== - -// Cases: -// * F is external strong, G is external strong: -// turn G into a thunk to F (1) -// * F is external strong, G is external weak: -// turn G into a thunk to F (1) -// * F is external weak, G is external weak: -// unfoldable -// * F is external strong, G is internal: -// address of G taken: -// turn G into a thunk to F (1) -// address of G not taken: -// make G an alias to F (2) -// * F is internal, G is external weak -// address of F is taken: -// turn G into a thunk to F (1) -// address of F is not taken: -// make G an alias of F (2) -// * F is internal, G is internal: -// address of F and G are taken: -// turn G into a thunk to F (1) -// address of G is not taken: -// make G an alias to F (2) -// -// alias requires linkage == (external,local,weak) fallback to creating a thunk -// external means 'externally visible' linkage != (internal,private) -// internal means linkage == (internal,private) -// weak means linkage mayBeOverridable -// being external implies that the address is taken -// -// 1. turn G into a thunk to F -// 2. make G an alias to F + VisitedBBs.insert(F1BBs[0]); + while (!F1BBs.empty()) { + const BasicBlock *F1BB = F1BBs.pop_back_val(); + const BasicBlock *F2BB = F2BBs.pop_back_val(); -enum LinkageCategory { - ExternalStrong, - ExternalWeak, - Internal -}; + if (!Enumerate(F1BB, F2BB) || !Compare(F1BB, F2BB)) + return false; -static LinkageCategory categorize(const Function *F) { - switch (F->getLinkage()) { - case GlobalValue::InternalLinkage: - case GlobalValue::PrivateLinkage: - case GlobalValue::LinkerPrivateLinkage: - return Internal; - - case GlobalValue::WeakAnyLinkage: - case GlobalValue::WeakODRLinkage: - case GlobalValue::ExternalWeakLinkage: - case GlobalValue::LinkerPrivateWeakLinkage: - return ExternalWeak; - - case GlobalValue::ExternalLinkage: - case GlobalValue::AvailableExternallyLinkage: - case GlobalValue::LinkOnceAnyLinkage: - case GlobalValue::LinkOnceODRLinkage: - case GlobalValue::AppendingLinkage: - case GlobalValue::DLLImportLinkage: - case GlobalValue::DLLExportLinkage: - case GlobalValue::CommonLinkage: - return ExternalStrong; - } + const TerminatorInst *F1TI = F1BB->getTerminator(); + const TerminatorInst *F2TI = F2BB->getTerminator(); - llvm_unreachable("Unknown LinkageType."); - return ExternalWeak; + assert(F1TI->getNumSuccessors() == F2TI->getNumSuccessors()); + for (unsigned i = 0, e = F1TI->getNumSuccessors(); i != e; ++i) { + if (!VisitedBBs.insert(F1TI->getSuccessor(i))) + continue; + + F1BBs.push_back(F1TI->getSuccessor(i)); + F2BBs.push_back(F2TI->getSuccessor(i)); + } + } + return true; } -static void ThunkGToF(Function *F, Function *G) { +/// WriteThunk - Replace G with a simple tail call to bitcast(F). Also replace +/// direct uses of G with bitcast(F). +void MergeFunctions::WriteThunk(Function *F, Function *G) const { if (!G->mayBeOverridden()) { // Redirect direct callers of G to F. Constant *BitcastF = ConstantExpr::getBitCast(F, G->getType()); @@ -567,33 +490,34 @@ static void ThunkGToF(Function *F, Function *G) { } } + // If G was internal then we may have replaced all uses if G with F. If so, + // stop here and delete G. There's no need for a thunk. + if (G->hasLocalLinkage() && G->use_empty()) { + G->eraseFromParent(); + return; + } + Function *NewG = Function::Create(G->getFunctionType(), G->getLinkage(), "", G->getParent()); BasicBlock *BB = BasicBlock::Create(F->getContext(), "", NewG); + IRBuilder<false> Builder(BB); SmallVector<Value *, 16> Args; unsigned i = 0; const FunctionType *FFTy = F->getFunctionType(); for (Function::arg_iterator AI = NewG->arg_begin(), AE = NewG->arg_end(); AI != AE; ++AI) { - if (FFTy->getParamType(i) == AI->getType()) { - Args.push_back(AI); - } else { - Args.push_back(new BitCastInst(AI, FFTy->getParamType(i), "", BB)); - } + Args.push_back(Builder.CreateBitCast(AI, FFTy->getParamType(i))); ++i; } - CallInst *CI = CallInst::Create(F, Args.begin(), Args.end(), "", BB); + CallInst *CI = Builder.CreateCall(F, Args.begin(), Args.end()); CI->setTailCall(); CI->setCallingConv(F->getCallingConv()); if (NewG->getReturnType()->isVoidTy()) { - ReturnInst::Create(F->getContext(), BB); - } else if (CI->getType() != NewG->getReturnType()) { - Value *BCI = new BitCastInst(CI, NewG->getReturnType(), "", BB); - ReturnInst::Create(F->getContext(), BCI, BB); + Builder.CreateRetVoid(); } else { - ReturnInst::Create(F->getContext(), CI, BB); + Builder.CreateRet(Builder.CreateBitCast(CI, NewG->getReturnType())); } NewG->copyAttributesFrom(G); @@ -602,152 +526,126 @@ static void ThunkGToF(Function *F, Function *G) { G->eraseFromParent(); } -static void AliasGToF(Function *F, Function *G) { - // Darwin will trigger llvm_unreachable if asked to codegen an alias. - return ThunkGToF(F, G); - -#if 0 - if (!G->hasExternalLinkage() && !G->hasLocalLinkage() && !G->hasWeakLinkage()) - return ThunkGToF(F, G); - - GlobalAlias *GA = new GlobalAlias( - G->getType(), G->getLinkage(), "", - ConstantExpr::getBitCast(F, G->getType()), G->getParent()); - F->setAlignment(std::max(F->getAlignment(), G->getAlignment())); - GA->takeName(G); - GA->setVisibility(G->getVisibility()); - G->replaceAllUsesWith(GA); - G->eraseFromParent(); -#endif -} - -static bool fold(std::vector<Function *> &FnVec, unsigned i, unsigned j) { - Function *F = FnVec[i]; - Function *G = FnVec[j]; - - LinkageCategory catF = categorize(F); - LinkageCategory catG = categorize(G); - - if (catF == ExternalWeak || (catF == Internal && catG == ExternalStrong)) { - std::swap(FnVec[i], FnVec[j]); - std::swap(F, G); - std::swap(catF, catG); - } - - switch (catF) { - case ExternalStrong: - switch (catG) { - case ExternalStrong: - case ExternalWeak: - ThunkGToF(F, G); - break; - case Internal: - if (G->hasAddressTaken()) - ThunkGToF(F, G); - else - AliasGToF(F, G); - break; - } - break; - - case ExternalWeak: { - assert(catG == ExternalWeak); +/// MergeTwoFunctions - Merge two equivalent functions. Upon completion, +/// Function G is deleted. +void MergeFunctions::MergeTwoFunctions(Function *F, Function *G) const { + if (F->isWeakForLinker()) { + assert(G->isWeakForLinker()); // Make them both thunks to the same internal function. - F->setAlignment(std::max(F->getAlignment(), G->getAlignment())); Function *H = Function::Create(F->getFunctionType(), F->getLinkage(), "", F->getParent()); H->copyAttributesFrom(F); H->takeName(F); F->replaceAllUsesWith(H); - ThunkGToF(F, G); - ThunkGToF(F, H); + unsigned MaxAlignment = std::max(G->getAlignment(), H->getAlignment()); - F->setLinkage(GlobalValue::InternalLinkage); - } break; - - case Internal: - switch (catG) { - case ExternalStrong: - llvm_unreachable(0); - // fall-through - case ExternalWeak: - if (F->hasAddressTaken()) - ThunkGToF(F, G); - else - AliasGToF(F, G); - break; - case Internal: { - bool addrTakenF = F->hasAddressTaken(); - bool addrTakenG = G->hasAddressTaken(); - if (!addrTakenF && addrTakenG) { - std::swap(FnVec[i], FnVec[j]); - std::swap(F, G); - std::swap(addrTakenF, addrTakenG); - } + WriteThunk(F, G); + WriteThunk(F, H); - if (addrTakenF && addrTakenG) { - ThunkGToF(F, G); - } else { - assert(!addrTakenG); - AliasGToF(F, G); - } - } break; - } break; + F->setAlignment(MaxAlignment); + F->setLinkage(GlobalValue::InternalLinkage); + } else { + WriteThunk(F, G); } ++NumFunctionsMerged; - return true; } -// ===----------------------------------------------------------------------=== -// Pass definition -// ===----------------------------------------------------------------------=== +static unsigned ProfileFunction(const Function *F) { + const FunctionType *FTy = F->getFunctionType(); -bool MergeFunctions::runOnModule(Module &M) { - bool Changed = false; + FoldingSetNodeID ID; + ID.AddInteger(F->size()); + ID.AddInteger(F->getCallingConv()); + ID.AddBoolean(F->hasGC()); + ID.AddBoolean(FTy->isVarArg()); + ID.AddInteger(FTy->getReturnType()->getTypeID()); + for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i) + ID.AddInteger(FTy->getParamType(i)->getTypeID()); + return ID.ComputeHash(); +} - std::map<unsigned long, std::vector<Function *> > FnMap; +class ComparableFunction { +public: + ComparableFunction(Function *Func, TargetData *TD) + : Func(Func), Hash(ProfileFunction(Func)), TD(TD) {} - for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { - if (F->isDeclaration()) - continue; + AssertingVH<Function> const Func; + const unsigned Hash; + TargetData * const TD; +}; - FnMap[hash(F)].push_back(F); +struct MergeFunctionsEqualityInfo { + static ComparableFunction *getEmptyKey() { + return reinterpret_cast<ComparableFunction*>(0); + } + static ComparableFunction *getTombstoneKey() { + return reinterpret_cast<ComparableFunction*>(-1); } + static unsigned getHashValue(const ComparableFunction *CF) { + return CF->Hash; + } + static bool isEqual(const ComparableFunction *LHS, + const ComparableFunction *RHS) { + if (LHS == RHS) + return true; + if (LHS == getEmptyKey() || LHS == getTombstoneKey() || + RHS == getEmptyKey() || RHS == getTombstoneKey()) + return false; + assert(LHS->TD == RHS->TD && "Comparing functions for different targets"); + return FunctionComparator(LHS->TD, LHS->Func, RHS->Func).Compare(); + } +}; +bool MergeFunctions::runOnModule(Module &M) { + typedef DenseSet<ComparableFunction *, MergeFunctionsEqualityInfo> FnSetType; + + bool Changed = false; TD = getAnalysisIfAvailable<TargetData>(); + std::vector<Function *> Funcs; + for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { + if (!F->isDeclaration() && !F->hasAvailableExternallyLinkage()) + Funcs.push_back(F); + } + bool LocalChanged; do { LocalChanged = false; - DEBUG(dbgs() << "size: " << FnMap.size() << "\n"); - for (std::map<unsigned long, std::vector<Function *> >::iterator - I = FnMap.begin(), E = FnMap.end(); I != E; ++I) { - std::vector<Function *> &FnVec = I->second; - DEBUG(dbgs() << "hash (" << I->first << "): " << FnVec.size() << "\n"); - - for (int i = 0, e = FnVec.size(); i != e; ++i) { - for (int j = i + 1; j != e; ++j) { - bool isEqual = equals(FnVec[i], FnVec[j]); - - DEBUG(dbgs() << " " << FnVec[i]->getName() - << (isEqual ? " == " : " != ") - << FnVec[j]->getName() << "\n"); - - if (isEqual) { - if (fold(FnVec, i, j)) { - LocalChanged = true; - FnVec.erase(FnVec.begin() + j); - --j, --e; - } - } - } - } + FnSetType FnSet; + for (unsigned i = 0, e = Funcs.size(); i != e;) { + Function *F = Funcs[i]; + ComparableFunction *NewF = new ComparableFunction(F, TD); + std::pair<FnSetType::iterator, bool> Result = FnSet.insert(NewF); + if (!Result.second) { + ComparableFunction *&OldF = *Result.first; + assert(OldF && "Expected a hash collision"); + + // NewF will be deleted in favour of OldF unless NewF is strong and + // OldF is weak in which case swap them to keep the strong definition. + + if (OldF->Func->isWeakForLinker() && !NewF->Func->isWeakForLinker()) + std::swap(OldF, NewF); + + DEBUG(dbgs() << " " << OldF->Func->getName() << " == " + << NewF->Func->getName() << '\n'); + + Funcs.erase(Funcs.begin() + i); + --e; + + Function *DeleteF = NewF->Func; + delete NewF; + MergeTwoFunctions(OldF->Func, DeleteF); + LocalChanged = true; + Changed = true; + } else { + ++i; + } } - Changed |= LocalChanged; + DeleteContainerPointers(FnSet); } while (LocalChanged); return Changed; diff --git a/contrib/llvm/lib/Transforms/IPO/PartialInlining.cpp b/contrib/llvm/lib/Transforms/IPO/PartialInlining.cpp index 6b9814c..432f7c5 100644 --- a/contrib/llvm/lib/Transforms/IPO/PartialInlining.cpp +++ b/contrib/llvm/lib/Transforms/IPO/PartialInlining.cpp @@ -30,7 +30,7 @@ namespace { struct PartialInliner : public ModulePass { virtual void getAnalysisUsage(AnalysisUsage &AU) const { } static char ID; // Pass identification, replacement for typeid - PartialInliner() : ModulePass(&ID) {} + PartialInliner() : ModulePass(ID) {} bool runOnModule(Module& M); @@ -40,7 +40,8 @@ namespace { } char PartialInliner::ID = 0; -static RegisterPass<PartialInliner> X("partial-inliner", "Partial Inliner"); +INITIALIZE_PASS(PartialInliner, "partial-inliner", + "Partial Inliner", false, false); ModulePass* llvm::createPartialInliningPass() { return new PartialInliner(); } @@ -67,7 +68,8 @@ Function* PartialInliner::unswitchFunction(Function* F) { // Clone the function, so that we can hack away on it. ValueMap<const Value*, Value*> VMap; - Function* duplicateFunction = CloneFunction(F, VMap); + Function* duplicateFunction = CloneFunction(F, VMap, + /*ModuleLevelChanges=*/false); duplicateFunction->setLinkage(GlobalValue::InternalLinkage); F->getParent()->getFunctionList().push_back(duplicateFunction); BasicBlock* newEntryBlock = cast<BasicBlock>(VMap[entryBlock]); @@ -159,7 +161,7 @@ bool PartialInliner::runOnModule(Module& M) { bool recursive = false; for (Function::use_iterator UI = currFunc->use_begin(), UE = currFunc->use_end(); UI != UE; ++UI) - if (Instruction* I = dyn_cast<Instruction>(UI)) + if (Instruction* I = dyn_cast<Instruction>(*UI)) if (I->getParent()->getParent() == currFunc) { recursive = true; break; diff --git a/contrib/llvm/lib/Transforms/IPO/PartialSpecialization.cpp b/contrib/llvm/lib/Transforms/IPO/PartialSpecialization.cpp index 58e1448..4a99a41 100644 --- a/contrib/llvm/lib/Transforms/IPO/PartialSpecialization.cpp +++ b/contrib/llvm/lib/Transforms/IPO/PartialSpecialization.cpp @@ -50,14 +50,14 @@ namespace { int scanDistribution(Function&, int, std::map<Constant*, int>&); public : static char ID; // Pass identification, replacement for typeid - PartSpec() : ModulePass(&ID) {} + PartSpec() : ModulePass(ID) {} bool runOnModule(Module &M); }; } char PartSpec::ID = 0; -static RegisterPass<PartSpec> -X("partialspecialization", "Partial Specialization"); +INITIALIZE_PASS(PartSpec, "partialspecialization", + "Partial Specialization", false, false); // Specialize F by replacing the arguments (keys) in replacements with the // constants (values). Replace all calls to F with those constants with @@ -74,7 +74,8 @@ SpecializeFunction(Function* F, deleted[arg->getArgNo()] = arg; } - Function* NF = CloneFunction(F, replacements); + Function* NF = CloneFunction(F, replacements, + /*ModuleLevelChanges=*/false); NF->setLinkage(GlobalValue::InternalLinkage); F->getParent()->getFunctionList().push_back(NF); @@ -82,10 +83,10 @@ SpecializeFunction(Function* F, ii != ee; ) { Value::use_iterator i = ii; ++ii; - if (isa<CallInst>(i) || isa<InvokeInst>(i)) { - CallSite CS(cast<Instruction>(i)); + User *U = *i; + CallSite CS(U); + if (CS) { if (CS.getCalledFunction() == F) { - SmallVector<Value*, 6> args; // Assemble the non-specialized arguments for the updated callsite. // In the process, make sure that the specialized arguments are @@ -105,13 +106,13 @@ SpecializeFunction(Function* F, } } Value* NCall; - if (CallInst *CI = dyn_cast<CallInst>(i)) { + if (CallInst *CI = dyn_cast<CallInst>(U)) { NCall = CallInst::Create(NF, args.begin(), args.end(), CI->getName(), CI); cast<CallInst>(NCall)->setTailCall(CI->isTailCall()); cast<CallInst>(NCall)->setCallingConv(CI->getCallingConv()); } else { - InvokeInst *II = cast<InvokeInst>(i); + InvokeInst *II = cast<InvokeInst>(U); NCall = InvokeInst::Create(NF, II->getNormalDest(), II->getUnwindDest(), args.begin(), args.end(), @@ -123,8 +124,7 @@ SpecializeFunction(Function* F, ++numReplaced; } } - next_use: - ; + next_use:; } return NF; } @@ -174,14 +174,14 @@ void PartSpec::scanForInterest(Function& F, InterestingArgVector& args) { ui != ue; ++ui) { bool interesting = false; - - if (isa<CmpInst>(ui)) interesting = true; - else if (isa<CallInst>(ui)) + User *U = *ui; + if (isa<CmpInst>(U)) interesting = true; + else if (isa<CallInst>(U)) interesting = ui->getOperand(0) == ii; - else if (isa<InvokeInst>(ui)) + else if (isa<InvokeInst>(U)) interesting = ui->getOperand(0) == ii; - else if (isa<SwitchInst>(ui)) interesting = true; - else if (isa<BranchInst>(ui)) interesting = true; + else if (isa<SwitchInst>(U)) interesting = true; + else if (isa<BranchInst>(U)) interesting = true; if (interesting) { args.push_back(std::distance(F.arg_begin(), ii)); @@ -196,14 +196,16 @@ int PartSpec::scanDistribution(Function& F, int arg, std::map<Constant*, int>& dist) { bool hasIndirect = false; int total = 0; - for(Value::use_iterator ii = F.use_begin(), ee = F.use_end(); - ii != ee; ++ii) - if ((isa<CallInst>(ii) || isa<InvokeInst>(ii)) - && ii->getOperand(0) == &F) { - ++dist[dyn_cast<Constant>(ii->getOperand(arg + 1))]; + for (Value::use_iterator ii = F.use_begin(), ee = F.use_end(); + ii != ee; ++ii) { + User *U = *ii; + CallSite CS(U); + if (CS && CS.getCalledFunction() == &F) { + ++dist[dyn_cast<Constant>(CS.getArgument(arg))]; ++total; } else hasIndirect = true; + } // Preserve the original address taken function even if all other uses // will be specialized. diff --git a/contrib/llvm/lib/Transforms/IPO/PruneEH.cpp b/contrib/llvm/lib/Transforms/IPO/PruneEH.cpp index de6099c..09ac76f 100644 --- a/contrib/llvm/lib/Transforms/IPO/PruneEH.cpp +++ b/contrib/llvm/lib/Transforms/IPO/PruneEH.cpp @@ -37,7 +37,7 @@ STATISTIC(NumUnreach, "Number of noreturn calls optimized"); namespace { struct PruneEH : public CallGraphSCCPass { static char ID; // Pass identification, replacement for typeid - PruneEH() : CallGraphSCCPass(&ID) {} + PruneEH() : CallGraphSCCPass(ID) {} // runOnSCC - Analyze the SCC, performing the transformation if possible. bool runOnSCC(CallGraphSCC &SCC); @@ -48,8 +48,8 @@ namespace { } char PruneEH::ID = 0; -static RegisterPass<PruneEH> -X("prune-eh", "Remove unused exception handling info"); +INITIALIZE_PASS(PruneEH, "prune-eh", + "Remove unused exception handling info", false, false); Pass *llvm::createPruneEHPass() { return new PruneEH(); } diff --git a/contrib/llvm/lib/Transforms/IPO/StripDeadPrototypes.cpp b/contrib/llvm/lib/Transforms/IPO/StripDeadPrototypes.cpp index 4566a76..ee10ad0 100644 --- a/contrib/llvm/lib/Transforms/IPO/StripDeadPrototypes.cpp +++ b/contrib/llvm/lib/Transforms/IPO/StripDeadPrototypes.cpp @@ -29,15 +29,15 @@ namespace { class StripDeadPrototypesPass : public ModulePass { public: static char ID; // Pass identification, replacement for typeid - StripDeadPrototypesPass() : ModulePass(&ID) { } + StripDeadPrototypesPass() : ModulePass(ID) { } virtual bool runOnModule(Module &M); }; } // end anonymous namespace char StripDeadPrototypesPass::ID = 0; -static RegisterPass<StripDeadPrototypesPass> -X("strip-dead-prototypes", "Strip Unused Function Prototypes"); +INITIALIZE_PASS(StripDeadPrototypesPass, "strip-dead-prototypes", + "Strip Unused Function Prototypes", false, false); bool StripDeadPrototypesPass::runOnModule(Module &M) { bool MadeChange = false; diff --git a/contrib/llvm/lib/Transforms/IPO/StripSymbols.cpp b/contrib/llvm/lib/Transforms/IPO/StripSymbols.cpp index 12e8db8..20b7b8f 100644 --- a/contrib/llvm/lib/Transforms/IPO/StripSymbols.cpp +++ b/contrib/llvm/lib/Transforms/IPO/StripSymbols.cpp @@ -39,7 +39,7 @@ namespace { public: static char ID; // Pass identification, replacement for typeid explicit StripSymbols(bool ODI = false) - : ModulePass(&ID), OnlyDebugInfo(ODI) {} + : ModulePass(ID), OnlyDebugInfo(ODI) {} virtual bool runOnModule(Module &M); @@ -52,7 +52,7 @@ namespace { public: static char ID; // Pass identification, replacement for typeid explicit StripNonDebugSymbols() - : ModulePass(&ID) {} + : ModulePass(ID) {} virtual bool runOnModule(Module &M); @@ -65,7 +65,7 @@ namespace { public: static char ID; // Pass identification, replacement for typeid explicit StripDebugDeclare() - : ModulePass(&ID) {} + : ModulePass(ID) {} virtual bool runOnModule(Module &M); @@ -78,7 +78,7 @@ namespace { public: static char ID; // Pass identification, replacement for typeid explicit StripDeadDebugInfo() - : ModulePass(&ID) {} + : ModulePass(ID) {} virtual bool runOnModule(Module &M); @@ -89,32 +89,33 @@ namespace { } char StripSymbols::ID = 0; -static RegisterPass<StripSymbols> -X("strip", "Strip all symbols from a module"); +INITIALIZE_PASS(StripSymbols, "strip", + "Strip all symbols from a module", false, false); ModulePass *llvm::createStripSymbolsPass(bool OnlyDebugInfo) { return new StripSymbols(OnlyDebugInfo); } char StripNonDebugSymbols::ID = 0; -static RegisterPass<StripNonDebugSymbols> -Y("strip-nondebug", "Strip all symbols, except dbg symbols, from a module"); +INITIALIZE_PASS(StripNonDebugSymbols, "strip-nondebug", + "Strip all symbols, except dbg symbols, from a module", + false, false); ModulePass *llvm::createStripNonDebugSymbolsPass() { return new StripNonDebugSymbols(); } char StripDebugDeclare::ID = 0; -static RegisterPass<StripDebugDeclare> -Z("strip-debug-declare", "Strip all llvm.dbg.declare intrinsics"); +INITIALIZE_PASS(StripDebugDeclare, "strip-debug-declare", + "Strip all llvm.dbg.declare intrinsics", false, false); ModulePass *llvm::createStripDebugDeclarePass() { return new StripDebugDeclare(); } char StripDeadDebugInfo::ID = 0; -static RegisterPass<StripDeadDebugInfo> -A("strip-dead-debug-info", "Strip debug info for unused symbols"); +INITIALIZE_PASS(StripDeadDebugInfo, "strip-dead-debug-info", + "Strip debug info for unused symbols", false, false); ModulePass *llvm::createStripDeadDebugInfoPass() { return new StripDeadDebugInfo(); @@ -254,14 +255,15 @@ static bool StripDebugInfo(Module &M) { } } - unsigned MDDbgKind = M.getMDKindID("dbg"); for (Module::iterator MI = M.begin(), ME = M.end(); MI != ME; ++MI) for (Function::iterator FI = MI->begin(), FE = MI->end(); FI != FE; ++FI) for (BasicBlock::iterator BI = FI->begin(), BE = FI->end(); BI != BE; ++BI) { - Changed = true; // FIXME: Only set if there was debug metadata. - BI->setMetadata(MDDbgKind, 0); + if (!BI->getDebugLoc().isUnknown()) { + Changed = true; + BI->setDebugLoc(DebugLoc()); + } } return Changed; @@ -348,8 +350,8 @@ bool StripDeadDebugInfo::runOnModule(Module &M) { for (SmallVector<MDNode *, 8>::iterator I = MDs.begin(), E = MDs.end(); I != E; ++I) { - if (M.getGlobalVariable(DIGlobalVariable(*I).getGlobal()->getName(), - true)) { + GlobalVariable *GV = DIGlobalVariable(*I).getGlobal(); + if (GV && M.getGlobalVariable(GV->getName(), true)) { if (!NMD) NMD = M.getOrInsertNamedMetadata("llvm.dbg.gv"); NMD->addOperand(*I); diff --git a/contrib/llvm/lib/Transforms/IPO/StructRetPromotion.cpp b/contrib/llvm/lib/Transforms/IPO/StructRetPromotion.cpp index a74686f..b82b03f 100644 --- a/contrib/llvm/lib/Transforms/IPO/StructRetPromotion.cpp +++ b/contrib/llvm/lib/Transforms/IPO/StructRetPromotion.cpp @@ -1,4 +1,4 @@ -//===-- StructRetPromotion.cpp - Promote sret arguments ------------------===// +//===-- StructRetPromotion.cpp - Promote sret arguments -------------------===// // // The LLVM Compiler Infrastructure // @@ -50,20 +50,19 @@ namespace { virtual bool runOnSCC(CallGraphSCC &SCC); static char ID; // Pass identification, replacement for typeid - SRETPromotion() : CallGraphSCCPass(&ID) {} + SRETPromotion() : CallGraphSCCPass(ID) {} private: CallGraphNode *PromoteReturn(CallGraphNode *CGN); bool isSafeToUpdateAllCallers(Function *F); Function *cloneFunctionBody(Function *F, const StructType *STy); CallGraphNode *updateCallSites(Function *F, Function *NF); - bool nestedStructType(const StructType *STy); }; } char SRETPromotion::ID = 0; -static RegisterPass<SRETPromotion> -X("sretpromotion", "Promote sret arguments to multiple ret values"); +INITIALIZE_PASS(SRETPromotion, "sretpromotion", + "Promote sret arguments to multiple ret values", false, false); Pass *llvm::createStructRetPromotionPass() { return new SRETPromotion(); @@ -156,7 +155,7 @@ bool SRETPromotion::isSafeToUpdateAllCallers(Function *F) { FnUseI != FnUseE; ++FnUseI) { // The function is passed in as an argument to (possibly) another function, // we can't change it! - CallSite CS = CallSite::get(*FnUseI); + CallSite CS(*FnUseI); Instruction *Call = CS.getInstruction(); // The function is used by something else than a call or invoke instruction, // we can't change it! @@ -187,7 +186,7 @@ bool SRETPromotion::isSafeToUpdateAllCallers(Function *F) { return false; for (Value::use_iterator GEPI = GEP->use_begin(), GEPE = GEP->use_end(); GEPI != GEPE; ++GEPI) - if (!isa<LoadInst>(GEPI)) + if (!isa<LoadInst>(*GEPI)) return false; } // Any other FirstArg users make this function unsuitable for sret @@ -271,7 +270,7 @@ CallGraphNode *SRETPromotion::updateCallSites(Function *F, Function *NF) { CallGraphNode *NF_CGN = CG.getOrInsertFunction(NF); while (!F->use_empty()) { - CallSite CS = CallSite::get(*F->use_begin()); + CallSite CS(*F->use_begin()); Instruction *Call = CS.getInstruction(); const AttrListPtr &PAL = F->getAttributes(); @@ -351,14 +350,3 @@ CallGraphNode *SRETPromotion::updateCallSites(Function *F, Function *NF) { return NF_CGN; } -/// nestedStructType - Return true if STy includes any -/// other aggregate types -bool SRETPromotion::nestedStructType(const StructType *STy) { - unsigned Num = STy->getNumElements(); - for (unsigned i = 0; i < Num; i++) { - const Type *Ty = STy->getElementType(i); - if (!Ty->isSingleValueType() && !Ty->isVoidTy()) - return true; - } - return false; -} |