diff options
Diffstat (limited to 'lib/Transforms/IPO')
-rw-r--r-- | lib/Transforms/IPO/ArgumentPromotion.cpp | 74 | ||||
-rw-r--r-- | lib/Transforms/IPO/ConstantMerge.cpp | 8 | ||||
-rw-r--r-- | lib/Transforms/IPO/DeadArgumentElimination.cpp | 112 | ||||
-rw-r--r-- | lib/Transforms/IPO/ExtractGV.cpp | 14 | ||||
-rw-r--r-- | lib/Transforms/IPO/FunctionAttrs.cpp | 35 | ||||
-rw-r--r-- | lib/Transforms/IPO/GlobalDCE.cpp | 4 | ||||
-rw-r--r-- | lib/Transforms/IPO/GlobalOpt.cpp | 167 | ||||
-rw-r--r-- | lib/Transforms/IPO/IPConstantPropagation.cpp | 6 | ||||
-rw-r--r-- | lib/Transforms/IPO/InlineAlways.cpp | 82 | ||||
-rw-r--r-- | lib/Transforms/IPO/InlineSimple.cpp | 72 | ||||
-rw-r--r-- | lib/Transforms/IPO/Inliner.cpp | 70 | ||||
-rw-r--r-- | lib/Transforms/IPO/Internalize.cpp | 20 | ||||
-rw-r--r-- | lib/Transforms/IPO/LLVMBuild.txt | 2 | ||||
-rw-r--r-- | lib/Transforms/IPO/LoopExtractor.cpp | 4 | ||||
-rw-r--r-- | lib/Transforms/IPO/MergeFunctions.cpp | 28 | ||||
-rw-r--r-- | lib/Transforms/IPO/PartialInlining.cpp | 4 | ||||
-rw-r--r-- | lib/Transforms/IPO/PassManagerBuilder.cpp | 14 | ||||
-rw-r--r-- | lib/Transforms/IPO/PruneEH.cpp | 24 | ||||
-rw-r--r-- | lib/Transforms/IPO/StripDeadPrototypes.cpp | 2 | ||||
-rw-r--r-- | lib/Transforms/IPO/StripSymbols.cpp | 12 |
20 files changed, 467 insertions, 287 deletions
diff --git a/lib/Transforms/IPO/ArgumentPromotion.cpp b/lib/Transforms/IPO/ArgumentPromotion.cpp index 2132e0a5fe..e6fa4edf61 100644 --- a/lib/Transforms/IPO/ArgumentPromotion.cpp +++ b/lib/Transforms/IPO/ArgumentPromotion.cpp @@ -36,12 +36,12 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Analysis/CallGraph.h" -#include "llvm/CallGraphSCCPass.h" -#include "llvm/Constants.h" -#include "llvm/DerivedTypes.h" -#include "llvm/Instructions.h" -#include "llvm/LLVMContext.h" -#include "llvm/Module.h" +#include "llvm/Analysis/CallGraphSCCPass.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" #include "llvm/Support/CFG.h" #include "llvm/Support/CallSite.h" #include "llvm/Support/Debug.h" @@ -153,8 +153,8 @@ CallGraphNode *ArgPromotion::PromoteArguments(CallGraphNode *CGN) { SmallPtrSet<Argument*, 8> ArgsToPromote; SmallPtrSet<Argument*, 8> ByValArgsToTransform; for (unsigned i = 0; i != PointerArgs.size(); ++i) { - bool isByVal=F->getParamAttributes(PointerArgs[i].second+1). - hasAttribute(Attributes::ByVal); + bool isByVal=F->getAttributes(). + hasAttribute(PointerArgs[i].second+1, Attribute::ByVal); Argument *PtrArg = PointerArgs[i].first; Type *AgTy = cast<PointerType>(PtrArg->getType())->getElementType(); @@ -511,17 +511,16 @@ CallGraphNode *ArgPromotion::DoPromotion(Function *F, // what the new GEP/Load instructions we are inserting look like. std::map<IndicesVector, LoadInst*> OriginalLoads; - // Attributes - Keep track of the parameter attributes for the arguments + // Attribute - Keep track of the parameter attributes for the arguments // that we are *not* promoting. For the ones that we do promote, the parameter // attributes are lost - SmallVector<AttributeWithIndex, 8> AttributesVec; + SmallVector<AttributeSet, 8> AttributesVec; const AttributeSet &PAL = F->getAttributes(); // Add any return attributes. - Attributes attrs = PAL.getRetAttributes(); - if (attrs.hasAttributes()) - AttributesVec.push_back(AttributeWithIndex::get(AttributeSet::ReturnIndex, - attrs)); + if (PAL.hasAttributes(AttributeSet::ReturnIndex)) + AttributesVec.push_back(AttributeSet::get(F->getContext(), + PAL.getRetAttributes())); // First, determine the new argument list unsigned ArgIndex = 1; @@ -537,9 +536,12 @@ CallGraphNode *ArgPromotion::DoPromotion(Function *F, } else if (!ArgsToPromote.count(I)) { // Unchanged argument Params.push_back(I->getType()); - Attributes attrs = PAL.getParamAttributes(ArgIndex); - if (attrs.hasAttributes()) - AttributesVec.push_back(AttributeWithIndex::get(Params.size(), attrs)); + AttributeSet attrs = PAL.getParamAttributes(ArgIndex); + if (attrs.hasAttributes(ArgIndex)) { + AttrBuilder B(attrs, ArgIndex); + AttributesVec. + push_back(AttributeSet::get(F->getContext(), Params.size(), B)); + } } else if (I->use_empty()) { // Dead argument (which are always marked as promotable) ++NumArgumentsDead; @@ -591,10 +593,9 @@ CallGraphNode *ArgPromotion::DoPromotion(Function *F, } // Add any function attributes. - attrs = PAL.getFnAttributes(); - if (attrs.hasAttributes()) - AttributesVec.push_back(AttributeWithIndex::get(AttributeSet::FunctionIndex, - attrs)); + if (PAL.hasAttributes(AttributeSet::FunctionIndex)) + AttributesVec.push_back(AttributeSet::get(FTy->getContext(), + PAL.getFnAttributes())); Type *RetTy = FTy->getReturnType(); @@ -639,10 +640,9 @@ CallGraphNode *ArgPromotion::DoPromotion(Function *F, const AttributeSet &CallPAL = CS.getAttributes(); // Add any return attributes. - Attributes attrs = CallPAL.getRetAttributes(); - if (attrs.hasAttributes()) - AttributesVec.push_back(AttributeWithIndex::get(AttributeSet::ReturnIndex, - attrs)); + if (CallPAL.hasAttributes(AttributeSet::ReturnIndex)) + AttributesVec.push_back(AttributeSet::get(F->getContext(), + CallPAL.getRetAttributes())); // Loop over the operands, inserting GEP and loads in the caller as // appropriate. @@ -653,10 +653,11 @@ CallGraphNode *ArgPromotion::DoPromotion(Function *F, if (!ArgsToPromote.count(I) && !ByValArgsToTransform.count(I)) { Args.push_back(*AI); // Unmodified argument - Attributes Attrs = CallPAL.getParamAttributes(ArgIndex); - if (Attrs.hasAttributes()) - AttributesVec.push_back(AttributeWithIndex::get(Args.size(), Attrs)); - + if (CallPAL.hasAttributes(ArgIndex)) { + AttrBuilder B(CallPAL, ArgIndex); + AttributesVec. + push_back(AttributeSet::get(F->getContext(), Args.size(), B)); + } } else if (ByValArgsToTransform.count(I)) { // Emit a GEP and load for each element of the struct. Type *AgTy = cast<PointerType>(I->getType())->getElementType(); @@ -715,16 +716,17 @@ CallGraphNode *ArgPromotion::DoPromotion(Function *F, // Push any varargs arguments on the list. for (; AI != CS.arg_end(); ++AI, ++ArgIndex) { Args.push_back(*AI); - Attributes Attrs = CallPAL.getParamAttributes(ArgIndex); - if (Attrs.hasAttributes()) - AttributesVec.push_back(AttributeWithIndex::get(Args.size(), Attrs)); + if (CallPAL.hasAttributes(ArgIndex)) { + AttrBuilder B(CallPAL, ArgIndex); + AttributesVec. + push_back(AttributeSet::get(F->getContext(), Args.size(), B)); + } } // Add any function attributes. - attrs = CallPAL.getFnAttributes(); - if (attrs.hasAttributes()) - AttributesVec.push_back(AttributeWithIndex::get(AttributeSet::FunctionIndex, - attrs)); + if (CallPAL.hasAttributes(AttributeSet::FunctionIndex)) + AttributesVec.push_back(AttributeSet::get(Call->getContext(), + CallPAL.getFnAttributes())); Instruction *New; if (InvokeInst *II = dyn_cast<InvokeInst>(Call)) { diff --git a/lib/Transforms/IPO/ConstantMerge.cpp b/lib/Transforms/IPO/ConstantMerge.cpp index d30eeaf7d3..8336d3ad34 100644 --- a/lib/Transforms/IPO/ConstantMerge.cpp +++ b/lib/Transforms/IPO/ConstantMerge.cpp @@ -23,10 +23,10 @@ #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/Statistic.h" -#include "llvm/Constants.h" -#include "llvm/DataLayout.h" -#include "llvm/DerivedTypes.h" -#include "llvm/Module.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Module.h" #include "llvm/Pass.h" using namespace llvm; diff --git a/lib/Transforms/IPO/DeadArgumentElimination.cpp b/lib/Transforms/IPO/DeadArgumentElimination.cpp index 6236a04fc2..49ef1e75f1 100644 --- a/lib/Transforms/IPO/DeadArgumentElimination.cpp +++ b/lib/Transforms/IPO/DeadArgumentElimination.cpp @@ -23,15 +23,15 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Statistic.h" #include "llvm/ADT/StringExtras.h" -#include "llvm/CallingConv.h" -#include "llvm/Constant.h" #include "llvm/DIBuilder.h" #include "llvm/DebugInfo.h" -#include "llvm/DerivedTypes.h" -#include "llvm/Instructions.h" -#include "llvm/IntrinsicInst.h" -#include "llvm/LLVMContext.h" -#include "llvm/Module.h" +#include "llvm/IR/CallingConv.h" +#include "llvm/IR/Constant.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" #include "llvm/Pass.h" #include "llvm/Support/CallSite.h" #include "llvm/Support/Debug.h" @@ -272,14 +272,13 @@ bool DAE::DeleteDeadVarargs(Function &Fn) { // Drop any attributes that were on the vararg arguments. AttributeSet PAL = CS.getAttributes(); - if (!PAL.isEmpty() && PAL.getSlot(PAL.getNumSlots() - 1).Index > NumArgs) { - SmallVector<AttributeWithIndex, 8> AttributesVec; - for (unsigned i = 0; PAL.getSlot(i).Index <= NumArgs; ++i) - AttributesVec.push_back(PAL.getSlot(i)); - Attributes FnAttrs = PAL.getFnAttributes(); - if (FnAttrs.hasAttributes()) - AttributesVec.push_back(AttributeWithIndex::get(AttributeSet::FunctionIndex, - FnAttrs)); + if (!PAL.isEmpty() && PAL.getSlotIndex(PAL.getNumSlots() - 1) > NumArgs) { + SmallVector<AttributeSet, 8> AttributesVec; + for (unsigned i = 0; PAL.getSlotIndex(i) <= NumArgs; ++i) + AttributesVec.push_back(PAL.getSlotAttributes(i)); + if (PAL.hasAttributes(AttributeSet::FunctionIndex)) + AttributesVec.push_back(AttributeSet::get(Fn.getContext(), + PAL.getFnAttributes())); PAL = AttributeSet::get(Fn.getContext(), AttributesVec); } @@ -351,7 +350,7 @@ bool DAE::RemoveDeadArgumentsFromCallers(Function &Fn) if (Fn.use_empty()) return false; - llvm::SmallVector<unsigned, 8> UnusedArgs; + SmallVector<unsigned, 8> UnusedArgs; for (Function::arg_iterator I = Fn.arg_begin(), E = Fn.arg_end(); I != E; ++I) { Argument *Arg = I; @@ -697,15 +696,10 @@ bool DAE::RemoveDeadStuffFromFunction(Function *F) { std::vector<Type*> Params; // Set up to build a new list of parameter attributes. - SmallVector<AttributeWithIndex, 8> AttributesVec; + SmallVector<AttributeSet, 8> AttributesVec; const AttributeSet &PAL = F->getAttributes(); - // The existing function return attributes. - Attributes RAttrs = PAL.getRetAttributes(); - Attributes FnAttrs = PAL.getFnAttributes(); - // Find out the new return value. - Type *RetTy = FTy->getReturnType(); Type *NRetTy = NULL; unsigned RetCount = NumRetVals(F); @@ -759,22 +753,29 @@ bool DAE::RemoveDeadStuffFromFunction(Function *F) { assert(NRetTy && "No new return type found?"); + // The existing function return attributes. + AttributeSet RAttrs = PAL.getRetAttributes(); + // Remove any incompatible attributes, but only if we removed all return // values. Otherwise, ensure that we don't have any conflicting attributes // here. Currently, this should not be possible, but special handling might be // required when new return value attributes are added. if (NRetTy->isVoidTy()) RAttrs = - Attributes::get(NRetTy->getContext(), AttrBuilder(RAttrs). - removeAttributes(Attributes::typeIncompatible(NRetTy))); + AttributeSet::get(NRetTy->getContext(), AttributeSet::ReturnIndex, + AttrBuilder(RAttrs, AttributeSet::ReturnIndex). + removeAttributes(AttributeFuncs:: + typeIncompatible(NRetTy, AttributeSet::ReturnIndex), + AttributeSet::ReturnIndex)); else - assert(!AttrBuilder(RAttrs). - hasAttributes(Attributes::typeIncompatible(NRetTy)) && + assert(!AttrBuilder(RAttrs, AttributeSet::ReturnIndex). + hasAttributes(AttributeFuncs:: + typeIncompatible(NRetTy, AttributeSet::ReturnIndex), + AttributeSet::ReturnIndex) && "Return attributes no longer compatible?"); - if (RAttrs.hasAttributes()) - AttributesVec.push_back(AttributeWithIndex::get(AttributeSet::ReturnIndex, - RAttrs)); + if (RAttrs.hasAttributes(AttributeSet::ReturnIndex)) + AttributesVec.push_back(AttributeSet::get(NRetTy->getContext(), RAttrs)); // Remember which arguments are still alive. SmallVector<bool, 10> ArgAlive(FTy->getNumParams(), false); @@ -791,9 +792,11 @@ bool DAE::RemoveDeadStuffFromFunction(Function *F) { // Get the original parameter attributes (skipping the first one, that is // for the return value. - Attributes Attrs = PAL.getParamAttributes(i + 1); - if (Attrs.hasAttributes()) - AttributesVec.push_back(AttributeWithIndex::get(Params.size(), Attrs)); + if (PAL.hasAttributes(i + 1)) { + AttrBuilder B(PAL, i + 1); + AttributesVec. + push_back(AttributeSet::get(F->getContext(), Params.size(), B)); + } } else { ++NumArgumentsEliminated; DEBUG(dbgs() << "DAE - Removing argument " << i << " (" << I->getName() @@ -801,9 +804,9 @@ bool DAE::RemoveDeadStuffFromFunction(Function *F) { } } - if (FnAttrs.hasAttributes()) - AttributesVec.push_back(AttributeWithIndex::get(AttributeSet::FunctionIndex, - FnAttrs)); + if (PAL.hasAttributes(AttributeSet::FunctionIndex)) + AttributesVec.push_back(AttributeSet::get(F->getContext(), + PAL.getFnAttributes())); // Reconstruct the AttributesList based on the vector we constructed. AttributeSet NewPAL = AttributeSet::get(F->getContext(), AttributesVec); @@ -836,15 +839,18 @@ bool DAE::RemoveDeadStuffFromFunction(Function *F) { const AttributeSet &CallPAL = CS.getAttributes(); // The call return attributes. - Attributes RAttrs = CallPAL.getRetAttributes(); - Attributes FnAttrs = CallPAL.getFnAttributes(); + AttributeSet RAttrs = CallPAL.getRetAttributes(); + // Adjust in case the function was changed to return void. RAttrs = - Attributes::get(NF->getContext(), AttrBuilder(RAttrs). - removeAttributes(Attributes::typeIncompatible(NF->getReturnType()))); - if (RAttrs.hasAttributes()) - AttributesVec.push_back(AttributeWithIndex::get(AttributeSet::ReturnIndex, - RAttrs)); + AttributeSet::get(NF->getContext(), AttributeSet::ReturnIndex, + AttrBuilder(RAttrs, AttributeSet::ReturnIndex). + removeAttributes(AttributeFuncs:: + typeIncompatible(NF->getReturnType(), + AttributeSet::ReturnIndex), + AttributeSet::ReturnIndex)); + if (RAttrs.hasAttributes(AttributeSet::ReturnIndex)) + AttributesVec.push_back(AttributeSet::get(NF->getContext(), RAttrs)); // Declare these outside of the loops, so we can reuse them for the second // loop, which loops the varargs. @@ -856,22 +862,26 @@ bool DAE::RemoveDeadStuffFromFunction(Function *F) { if (ArgAlive[i]) { Args.push_back(*I); // Get original parameter attributes, but skip return attributes. - Attributes Attrs = CallPAL.getParamAttributes(i + 1); - if (Attrs.hasAttributes()) - AttributesVec.push_back(AttributeWithIndex::get(Args.size(), Attrs)); + if (CallPAL.hasAttributes(i + 1)) { + AttrBuilder B(CallPAL, i + 1); + AttributesVec. + push_back(AttributeSet::get(F->getContext(), Args.size(), B)); + } } // Push any varargs arguments on the list. Don't forget their attributes. for (CallSite::arg_iterator E = CS.arg_end(); I != E; ++I, ++i) { Args.push_back(*I); - Attributes Attrs = CallPAL.getParamAttributes(i + 1); - if (Attrs.hasAttributes()) - AttributesVec.push_back(AttributeWithIndex::get(Args.size(), Attrs)); + if (CallPAL.hasAttributes(i + 1)) { + AttrBuilder B(CallPAL, i + 1); + AttributesVec. + push_back(AttributeSet::get(F->getContext(), Args.size(), B)); + } } - if (FnAttrs.hasAttributes()) - AttributesVec.push_back(AttributeWithIndex::get(AttributeSet::FunctionIndex, - FnAttrs)); + if (CallPAL.hasAttributes(AttributeSet::FunctionIndex)) + AttributesVec.push_back(AttributeSet::get(Call->getContext(), + CallPAL.getFnAttributes())); // Reconstruct the AttributesList based on the vector we constructed. AttributeSet NewCallPAL = AttributeSet::get(F->getContext(), AttributesVec); diff --git a/lib/Transforms/IPO/ExtractGV.cpp b/lib/Transforms/IPO/ExtractGV.cpp index f8d0491bf8..fa3d72ddcf 100644 --- a/lib/Transforms/IPO/ExtractGV.cpp +++ b/lib/Transforms/IPO/ExtractGV.cpp @@ -13,10 +13,10 @@ #include "llvm/Transforms/IPO.h" #include "llvm/ADT/SetVector.h" -#include "llvm/Constants.h" -#include "llvm/Instructions.h" -#include "llvm/LLVMContext.h" -#include "llvm/Module.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" #include "llvm/Pass.h" #include <algorithm> using namespace llvm; @@ -60,7 +60,7 @@ namespace { continue; } - bool Local = I->hasLocalLinkage(); + bool Local = I->isDiscardableIfUnused(); if (Local) I->setVisibility(GlobalValue::HiddenVisibility); @@ -80,7 +80,7 @@ namespace { continue; } - bool Local = I->hasLocalLinkage(); + bool Local = I->isDiscardableIfUnused(); if (Local) I->setVisibility(GlobalValue::HiddenVisibility); @@ -97,7 +97,7 @@ namespace { Module::alias_iterator CurI = I; ++I; - if (CurI->hasLocalLinkage()) { + if (CurI->isDiscardableIfUnused()) { CurI->setVisibility(GlobalValue::HiddenVisibility); CurI->setLinkage(GlobalValue::ExternalLinkage); } diff --git a/lib/Transforms/IPO/FunctionAttrs.cpp b/lib/Transforms/IPO/FunctionAttrs.cpp index 685833da1a..a75212a386 100644 --- a/lib/Transforms/IPO/FunctionAttrs.cpp +++ b/lib/Transforms/IPO/FunctionAttrs.cpp @@ -26,11 +26,11 @@ #include "llvm/ADT/Statistic.h" #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Analysis/CallGraph.h" +#include "llvm/Analysis/CallGraphSCCPass.h" #include "llvm/Analysis/CaptureTracking.h" -#include "llvm/CallGraphSCCPass.h" -#include "llvm/GlobalVariable.h" -#include "llvm/IntrinsicInst.h" -#include "llvm/LLVMContext.h" +#include "llvm/IR/GlobalVariable.h" +#include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/LLVMContext.h" #include "llvm/Support/InstIterator.h" using namespace llvm; @@ -213,16 +213,15 @@ bool FunctionAttrs::AddReadAttrs(const CallGraphSCC &SCC) { // Clear out any existing attributes. AttrBuilder B; - B.addAttribute(Attributes::ReadOnly) - .addAttribute(Attributes::ReadNone); - F->removeAttribute(AttributeSet::FunctionIndex, - Attributes::get(F->getContext(), B)); + B.addAttribute(Attribute::ReadOnly) + .addAttribute(Attribute::ReadNone); + F->removeAttributes(AttributeSet::FunctionIndex, + AttributeSet::get(F->getContext(), + AttributeSet::FunctionIndex, B)); // Add in the new attribute. - B.clear(); - B.addAttribute(ReadsMemory ? Attributes::ReadOnly : Attributes::ReadNone); F->addAttribute(AttributeSet::FunctionIndex, - Attributes::get(F->getContext(), B)); + ReadsMemory ? Attribute::ReadOnly : Attribute::ReadNone); if (ReadsMemory) ++NumReadOnly; @@ -358,7 +357,7 @@ bool FunctionAttrs::AddNoCaptureAttrs(const CallGraphSCC &SCC) { ArgumentGraph AG; AttrBuilder B; - B.addAttribute(Attributes::NoCapture); + B.addAttribute(Attribute::NoCapture); // Check each function in turn, determining which pointer arguments are not // captured. @@ -381,7 +380,7 @@ bool FunctionAttrs::AddNoCaptureAttrs(const CallGraphSCC &SCC) { for (Function::arg_iterator A = F->arg_begin(), E = F->arg_end(); A != E; ++A) { if (A->getType()->isPointerTy() && !A->hasNoCaptureAttr()) { - A->addAttr(Attributes::get(F->getContext(), B)); + A->addAttr(AttributeSet::get(F->getContext(), A->getArgNo() + 1, B)); ++NumNoCapture; Changed = true; } @@ -396,7 +395,7 @@ bool FunctionAttrs::AddNoCaptureAttrs(const CallGraphSCC &SCC) { if (!Tracker.Captured) { if (Tracker.Uses.empty()) { // If it's trivially not captured, mark it nocapture now. - A->addAttr(Attributes::get(F->getContext(), B)); + A->addAttr(AttributeSet::get(F->getContext(), A->getArgNo()+1, B)); ++NumNoCapture; Changed = true; } else { @@ -431,7 +430,9 @@ bool FunctionAttrs::AddNoCaptureAttrs(const CallGraphSCC &SCC) { ArgumentSCC[0]->Uses[0] == ArgumentSCC[0]) { ArgumentSCC[0]-> Definition-> - addAttr(Attributes::get(ArgumentSCC[0]->Definition->getContext(), B)); + addAttr(AttributeSet::get(ArgumentSCC[0]->Definition->getContext(), + ArgumentSCC[0]->Definition->getArgNo() + 1, + B)); ++NumNoCapture; Changed = true; } @@ -473,7 +474,7 @@ bool FunctionAttrs::AddNoCaptureAttrs(const CallGraphSCC &SCC) { for (unsigned i = 0, e = ArgumentSCC.size(); i != e; ++i) { Argument *A = ArgumentSCC[i]->Definition; - A->addAttr(Attributes::get(A->getContext(), B)); + A->addAttr(AttributeSet::get(A->getContext(), A->getArgNo() + 1, B)); ++NumNoCapture; Changed = true; } @@ -530,7 +531,7 @@ bool FunctionAttrs::IsFunctionMallocLike(Function *F, case Instruction::Call: case Instruction::Invoke: { CallSite CS(RVI); - if (CS.paramHasAttr(0, Attributes::NoAlias)) + if (CS.paramHasAttr(0, Attribute::NoAlias)) break; if (CS.getCalledFunction() && SCCNodes.count(CS.getCalledFunction())) diff --git a/lib/Transforms/IPO/GlobalDCE.cpp b/lib/Transforms/IPO/GlobalDCE.cpp index b2c819de2b..dc99492990 100644 --- a/lib/Transforms/IPO/GlobalDCE.cpp +++ b/lib/Transforms/IPO/GlobalDCE.cpp @@ -19,8 +19,8 @@ #include "llvm/Transforms/IPO.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/Statistic.h" -#include "llvm/Constants.h" -#include "llvm/Module.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/Module.h" #include "llvm/Pass.h" using namespace llvm; diff --git a/lib/Transforms/IPO/GlobalOpt.cpp b/lib/Transforms/IPO/GlobalOpt.cpp index 20f9de5a83..2b9d6670ca 100644 --- a/lib/Transforms/IPO/GlobalOpt.cpp +++ b/lib/Transforms/IPO/GlobalOpt.cpp @@ -22,14 +22,14 @@ #include "llvm/ADT/Statistic.h" #include "llvm/Analysis/ConstantFolding.h" #include "llvm/Analysis/MemoryBuiltins.h" -#include "llvm/CallingConv.h" -#include "llvm/Constants.h" -#include "llvm/DataLayout.h" -#include "llvm/DerivedTypes.h" -#include "llvm/Instructions.h" -#include "llvm/IntrinsicInst.h" -#include "llvm/Module.h" -#include "llvm/Operator.h" +#include "llvm/IR/CallingConv.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/Operator.h" #include "llvm/Pass.h" #include "llvm/Support/CallSite.h" #include "llvm/Support/Debug.h" @@ -448,8 +448,8 @@ static bool CleanupPointerRootUsers(GlobalVariable *GV, Dead[i].second->eraseFromParent(); Instruction *I = Dead[i].first; do { - if (isAllocationFn(I, TLI)) - break; + if (isAllocationFn(I, TLI)) + break; Instruction *J = dyn_cast<Instruction>(I->getOperand(0)); if (!J) break; @@ -1825,7 +1825,8 @@ static bool TryToShrinkGlobalToBoolean(GlobalVariable *GV, Constant *OtherVal) { GlobalValue::InternalLinkage, ConstantInt::getFalse(GV->getContext()), GV->getName()+".b", - GV->getThreadLocalMode()); + GV->getThreadLocalMode(), + GV->getType()->getAddressSpace()); GV->getParent()->getGlobalList().insert(GV, NewGV); Constant *InitVal = GV->getInitializer(); @@ -1845,10 +1846,10 @@ static bool TryToShrinkGlobalToBoolean(GlobalVariable *GV, Constant *OtherVal) { bool StoringOther = SI->getOperand(0) == OtherVal; // Only do this if we weren't storing a loaded value. Value *StoreVal; - if (StoringOther || SI->getOperand(0) == InitVal) + if (StoringOther || SI->getOperand(0) == InitVal) { StoreVal = ConstantInt::get(Type::getInt1Ty(GV->getContext()), StoringOther); - else { + } else { // Otherwise, we are storing a previously loaded copy. To do this, // change the copy from copying the original value to just copying the // bool. @@ -1887,6 +1888,9 @@ static bool TryToShrinkGlobalToBoolean(GlobalVariable *GV, Constant *OtherVal) { UI->eraseFromParent(); } + // Retain the name of the old global variable. People who are debugging their + // programs may expect these variables to be named the same. + NewGV->takeName(GV); GV->eraseFromParent(); return true; } @@ -1989,7 +1993,7 @@ bool GlobalOpt::ProcessInternalGlobal(GlobalVariable *GV, return Changed; } else if (GS.StoredType <= GlobalStatus::isInitializerStored) { - DEBUG(dbgs() << "MARKING CONSTANT: " << *GV); + DEBUG(dbgs() << "MARKING CONSTANT: " << *GV << "\n"); GV->setConstant(true); // Clean up any obviously simplifiable users now. @@ -2067,12 +2071,12 @@ static void ChangeCalleesToFastCall(Function *F) { static AttributeSet StripNest(LLVMContext &C, const AttributeSet &Attrs) { for (unsigned i = 0, e = Attrs.getNumSlots(); i != e; ++i) { - if (!Attrs.getSlot(i).Attrs.hasAttribute(Attributes::Nest)) + unsigned Index = Attrs.getSlotIndex(i); + if (!Attrs.getSlotAttributes(i).hasAttribute(Index, Attribute::Nest)) continue; // There can be only one. - return Attrs.removeAttr(C, Attrs.getSlot(i).Index, - Attributes::get(C, Attributes::Nest)); + return Attrs.removeAttribute(C, Index, Attribute::Nest); } return Attrs; @@ -2113,7 +2117,7 @@ bool GlobalOpt::OptimizeFunctions(Module &M) { Changed = true; } - if (F->getAttributes().hasAttrSomewhere(Attributes::Nest) && + if (F->getAttributes().hasAttrSomewhere(Attribute::Nest) && !F->hasAddressTaken()) { // The function is not used by a trampoline intrinsic, so it is safe // to remove the 'nest' attribute. @@ -2584,24 +2588,38 @@ bool Evaluator::EvaluateBlock(BasicBlock::iterator CurInst, while (1) { Constant *InstResult = 0; + DEBUG(dbgs() << "Evaluating Instruction: " << *CurInst << "\n"); + if (StoreInst *SI = dyn_cast<StoreInst>(CurInst)) { - if (!SI->isSimple()) return false; // no volatile/atomic accesses. + if (!SI->isSimple()) { + DEBUG(dbgs() << "Store is not simple! Can not evaluate.\n"); + return false; // no volatile/atomic accesses. + } Constant *Ptr = getVal(SI->getOperand(1)); - if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Ptr)) + if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Ptr)) { + DEBUG(dbgs() << "Folding constant ptr expression: " << *Ptr); Ptr = ConstantFoldConstantExpression(CE, TD, TLI); - if (!isSimpleEnoughPointerToCommit(Ptr)) + DEBUG(dbgs() << "; To: " << *Ptr << "\n"); + } + if (!isSimpleEnoughPointerToCommit(Ptr)) { // If this is too complex for us to commit, reject it. + DEBUG(dbgs() << "Pointer is too complex for us to evaluate store."); return false; + } Constant *Val = getVal(SI->getOperand(0)); // If this might be too difficult for the backend to handle (e.g. the addr // of one global variable divided by another) then we can't commit it. - if (!isSimpleEnoughValueToCommit(Val, SimpleConstants, TD)) + if (!isSimpleEnoughValueToCommit(Val, SimpleConstants, TD)) { + DEBUG(dbgs() << "Store value is too complex to evaluate store. " << *Val + << "\n"); return false; + } - if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Ptr)) + if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Ptr)) { if (CE->getOpcode() == Instruction::BitCast) { + DEBUG(dbgs() << "Attempting to resolve bitcast on constant ptr.\n"); // If we're evaluating a store through a bitcast, then we need // to pull the bitcast off the pointer type and push it onto the // stored value. @@ -2630,6 +2648,8 @@ bool Evaluator::EvaluateBlock(BasicBlock::iterator CurInst, // If we can't improve the situation by introspecting NewTy, // we have to give up. } else { + DEBUG(dbgs() << "Failed to bitcast constant ptr, can not " + "evaluate.\n"); return false; } } @@ -2637,25 +2657,36 @@ bool Evaluator::EvaluateBlock(BasicBlock::iterator CurInst, // If we found compatible types, go ahead and push the bitcast // onto the stored value. Val = ConstantExpr::getBitCast(Val, NewTy); + + DEBUG(dbgs() << "Evaluated bitcast: " << *Val << "\n"); } + } MutatedMemory[Ptr] = Val; } else if (BinaryOperator *BO = dyn_cast<BinaryOperator>(CurInst)) { InstResult = ConstantExpr::get(BO->getOpcode(), getVal(BO->getOperand(0)), getVal(BO->getOperand(1))); + DEBUG(dbgs() << "Found a BinaryOperator! Simplifying: " << *InstResult + << "\n"); } else if (CmpInst *CI = dyn_cast<CmpInst>(CurInst)) { InstResult = ConstantExpr::getCompare(CI->getPredicate(), getVal(CI->getOperand(0)), getVal(CI->getOperand(1))); + DEBUG(dbgs() << "Found a CmpInst! Simplifying: " << *InstResult + << "\n"); } else if (CastInst *CI = dyn_cast<CastInst>(CurInst)) { InstResult = ConstantExpr::getCast(CI->getOpcode(), getVal(CI->getOperand(0)), CI->getType()); + DEBUG(dbgs() << "Found a Cast! Simplifying: " << *InstResult + << "\n"); } else if (SelectInst *SI = dyn_cast<SelectInst>(CurInst)) { InstResult = ConstantExpr::getSelect(getVal(SI->getOperand(0)), getVal(SI->getOperand(1)), getVal(SI->getOperand(2))); + DEBUG(dbgs() << "Found a Select! Simplifying: " << *InstResult + << "\n"); } else if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(CurInst)) { Constant *P = getVal(GEP->getOperand(0)); SmallVector<Constant*, 8> GEPOps; @@ -2665,41 +2696,70 @@ bool Evaluator::EvaluateBlock(BasicBlock::iterator CurInst, InstResult = ConstantExpr::getGetElementPtr(P, GEPOps, cast<GEPOperator>(GEP)->isInBounds()); + DEBUG(dbgs() << "Found a GEP! Simplifying: " << *InstResult + << "\n"); } else if (LoadInst *LI = dyn_cast<LoadInst>(CurInst)) { - if (!LI->isSimple()) return false; // no volatile/atomic accesses. + + if (!LI->isSimple()) { + DEBUG(dbgs() << "Found a Load! Not a simple load, can not evaluate.\n"); + return false; // no volatile/atomic accesses. + } + Constant *Ptr = getVal(LI->getOperand(0)); - if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Ptr)) + if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Ptr)) { Ptr = ConstantFoldConstantExpression(CE, TD, TLI); + DEBUG(dbgs() << "Found a constant pointer expression, constant " + "folding: " << *Ptr << "\n"); + } InstResult = ComputeLoadResult(Ptr); - if (InstResult == 0) return false; // Could not evaluate load. + if (InstResult == 0) { + DEBUG(dbgs() << "Failed to compute load result. Can not evaluate load." + "\n"); + return false; // Could not evaluate load. + } + + DEBUG(dbgs() << "Evaluated load: " << *InstResult << "\n"); } else if (AllocaInst *AI = dyn_cast<AllocaInst>(CurInst)) { - if (AI->isArrayAllocation()) return false; // Cannot handle array allocs. + if (AI->isArrayAllocation()) { + DEBUG(dbgs() << "Found an array alloca. Can not evaluate.\n"); + return false; // Cannot handle array allocs. + } Type *Ty = AI->getType()->getElementType(); AllocaTmps.push_back(new GlobalVariable(Ty, false, GlobalValue::InternalLinkage, UndefValue::get(Ty), AI->getName())); InstResult = AllocaTmps.back(); + DEBUG(dbgs() << "Found an alloca. Result: " << *InstResult << "\n"); } else if (isa<CallInst>(CurInst) || isa<InvokeInst>(CurInst)) { CallSite CS(CurInst); // Debug info can safely be ignored here. if (isa<DbgInfoIntrinsic>(CS.getInstruction())) { + DEBUG(dbgs() << "Ignoring debug info.\n"); ++CurInst; continue; } // Cannot handle inline asm. - if (isa<InlineAsm>(CS.getCalledValue())) return false; + if (isa<InlineAsm>(CS.getCalledValue())) { + DEBUG(dbgs() << "Found inline asm, can not evaluate.\n"); + return false; + } if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(CS.getInstruction())) { if (MemSetInst *MSI = dyn_cast<MemSetInst>(II)) { - if (MSI->isVolatile()) return false; + if (MSI->isVolatile()) { + DEBUG(dbgs() << "Can not optimize a volatile memset " << + "intrinsic.\n"); + return false; + } Constant *Ptr = getVal(MSI->getDest()); Constant *Val = getVal(MSI->getValue()); Constant *DestVal = ComputeLoadResult(getVal(Ptr)); if (Val->isNullValue() && DestVal && DestVal->isNullValue()) { // This memset is a no-op. + DEBUG(dbgs() << "Ignoring no-op memset.\n"); ++CurInst; continue; } @@ -2707,6 +2767,7 @@ bool Evaluator::EvaluateBlock(BasicBlock::iterator CurInst, if (II->getIntrinsicID() == Intrinsic::lifetime_start || II->getIntrinsicID() == Intrinsic::lifetime_end) { + DEBUG(dbgs() << "Ignoring lifetime intrinsic.\n"); ++CurInst; continue; } @@ -2714,8 +2775,10 @@ bool Evaluator::EvaluateBlock(BasicBlock::iterator CurInst, if (II->getIntrinsicID() == Intrinsic::invariant_start) { // We don't insert an entry into Values, as it doesn't have a // meaningful return value. - if (!II->use_empty()) + if (!II->use_empty()) { + DEBUG(dbgs() << "Found unused invariant_start. Cant evaluate.\n"); return false; + } ConstantInt *Size = cast<ConstantInt>(II->getArgOperand(0)); Value *PtrArg = getVal(II->getArgOperand(1)); Value *Ptr = PtrArg->stripPointerCasts(); @@ -2723,20 +2786,30 @@ bool Evaluator::EvaluateBlock(BasicBlock::iterator CurInst, Type *ElemTy = cast<PointerType>(GV->getType())->getElementType(); if (!Size->isAllOnesValue() && Size->getValue().getLimitedValue() >= - TD->getTypeStoreSize(ElemTy)) + TD->getTypeStoreSize(ElemTy)) { Invariants.insert(GV); + DEBUG(dbgs() << "Found a global var that is an invariant: " << *GV + << "\n"); + } else { + DEBUG(dbgs() << "Found a global var, but can not treat it as an " + "invariant.\n"); + } } // Continue even if we do nothing. ++CurInst; continue; } + + DEBUG(dbgs() << "Unknown intrinsic. Can not evaluate.\n"); return false; } // Resolve function pointers. Function *Callee = dyn_cast<Function>(getVal(CS.getCalledValue())); - if (!Callee || Callee->mayBeOverridden()) + if (!Callee || Callee->mayBeOverridden()) { + DEBUG(dbgs() << "Can not resolve function pointer.\n"); return false; // Cannot resolve. + } SmallVector<Constant*, 8> Formals; for (User::op_iterator i = CS.arg_begin(), e = CS.arg_end(); i != e; ++i) @@ -2746,22 +2819,38 @@ bool Evaluator::EvaluateBlock(BasicBlock::iterator CurInst, // If this is a function we can constant fold, do it. if (Constant *C = ConstantFoldCall(Callee, Formals, TLI)) { InstResult = C; + DEBUG(dbgs() << "Constant folded function call. Result: " << + *InstResult << "\n"); } else { + DEBUG(dbgs() << "Can not constant fold function call.\n"); return false; } } else { - if (Callee->getFunctionType()->isVarArg()) + if (Callee->getFunctionType()->isVarArg()) { + DEBUG(dbgs() << "Can not constant fold vararg function call.\n"); return false; + } - Constant *RetVal; + Constant *RetVal = 0; // Execute the call, if successful, use the return value. ValueStack.push_back(new DenseMap<Value*, Constant*>); - if (!EvaluateFunction(Callee, RetVal, Formals)) + if (!EvaluateFunction(Callee, RetVal, Formals)) { + DEBUG(dbgs() << "Failed to evaluate function.\n"); return false; + } delete ValueStack.pop_back_val(); InstResult = RetVal; + + if (InstResult != NULL) { + DEBUG(dbgs() << "Successfully evaluated function. Result: " << + InstResult << "\n\n"); + } else { + DEBUG(dbgs() << "Successfully evaluated function. Result: 0\n\n"); + } } } else if (isa<TerminatorInst>(CurInst)) { + DEBUG(dbgs() << "Found a terminator instruction.\n"); + if (BranchInst *BI = dyn_cast<BranchInst>(CurInst)) { if (BI->isUnconditional()) { NextBB = BI->getSuccessor(0); @@ -2787,13 +2876,17 @@ bool Evaluator::EvaluateBlock(BasicBlock::iterator CurInst, NextBB = 0; } else { // invoke, unwind, resume, unreachable. + DEBUG(dbgs() << "Can not handle terminator."); return false; // Cannot handle this terminator. } // We succeeded at evaluating this block! + DEBUG(dbgs() << "Successfully evaluated block.\n"); return true; } else { // Did not know how to evaluate this! + DEBUG(dbgs() << "Failed to evaluate block due to unhandled instruction." + "\n"); return false; } @@ -2807,6 +2900,7 @@ bool Evaluator::EvaluateBlock(BasicBlock::iterator CurInst, // If we just processed an invoke, we finished evaluating the block. if (InvokeInst *II = dyn_cast<InvokeInst>(CurInst)) { NextBB = II->getNormalDest(); + DEBUG(dbgs() << "Found an invoke instruction. Finished Block.\n\n"); return true; } @@ -2845,6 +2939,8 @@ bool Evaluator::EvaluateFunction(Function *F, Constant *&RetVal, while (1) { BasicBlock *NextBB = 0; // Initialized to avoid compiler warnings. + DEBUG(dbgs() << "Trying to evaluate BB: " << *CurBB << "\n"); + if (!EvaluateBlock(CurInst, NextBB)) return false; @@ -2924,6 +3020,7 @@ bool GlobalOpt::OptimizeGlobalCtorsList(GlobalVariable *&GCL) { } break; } + DEBUG(dbgs() << "Optimizing Global Constructor: " << *F << "\n"); // We cannot simplify external ctor functions. if (F->empty()) continue; diff --git a/lib/Transforms/IPO/IPConstantPropagation.cpp b/lib/Transforms/IPO/IPConstantPropagation.cpp index 252b5b0584..4ac1dfc096 100644 --- a/lib/Transforms/IPO/IPConstantPropagation.cpp +++ b/lib/Transforms/IPO/IPConstantPropagation.cpp @@ -20,9 +20,9 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Statistic.h" #include "llvm/Analysis/ValueTracking.h" -#include "llvm/Constants.h" -#include "llvm/Instructions.h" -#include "llvm/Module.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/Module.h" #include "llvm/Pass.h" #include "llvm/Support/CallSite.h" using namespace llvm; diff --git a/lib/Transforms/IPO/InlineAlways.cpp b/lib/Transforms/IPO/InlineAlways.cpp index 5b8832e5d7..a0095dad1a 100644 --- a/lib/Transforms/IPO/InlineAlways.cpp +++ b/lib/Transforms/IPO/InlineAlways.cpp @@ -17,48 +17,54 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/Analysis/CallGraph.h" #include "llvm/Analysis/InlineCost.h" -#include "llvm/CallingConv.h" -#include "llvm/DataLayout.h" -#include "llvm/Instructions.h" -#include "llvm/IntrinsicInst.h" -#include "llvm/Module.h" +#include "llvm/IR/CallingConv.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/Type.h" #include "llvm/Support/CallSite.h" #include "llvm/Transforms/IPO/InlinerPass.h" -#include "llvm/Type.h" using namespace llvm; namespace { - // AlwaysInliner only inlines functions that are mark as "always inline". - class AlwaysInliner : public Inliner { - InlineCostAnalyzer CA; - public: - // Use extremely low threshold. - AlwaysInliner() : Inliner(ID, -2000000000, /*InsertLifetime*/true) { - initializeAlwaysInlinerPass(*PassRegistry::getPassRegistry()); - } - AlwaysInliner(bool InsertLifetime) : Inliner(ID, -2000000000, - InsertLifetime) { - initializeAlwaysInlinerPass(*PassRegistry::getPassRegistry()); - } - static char ID; // Pass identification, replacement for typeid - virtual InlineCost getInlineCost(CallSite CS); - - using llvm::Pass::doInitialization; - using llvm::Pass::doFinalization; - - virtual bool doFinalization(CallGraph &CG) { - return removeDeadFunctions(CG, /*AlwaysInlineOnly=*/true); - } - virtual bool doInitialization(CallGraph &CG); - }; +/// \brief Inliner pass which only handles "always inline" functions. +class AlwaysInliner : public Inliner { + InlineCostAnalysis *ICA; + +public: + // Use extremely low threshold. + AlwaysInliner() : Inliner(ID, -2000000000, /*InsertLifetime*/ true), ICA(0) { + initializeAlwaysInlinerPass(*PassRegistry::getPassRegistry()); + } + + AlwaysInliner(bool InsertLifetime) + : Inliner(ID, -2000000000, InsertLifetime), ICA(0) { + initializeAlwaysInlinerPass(*PassRegistry::getPassRegistry()); + } + + static char ID; // Pass identification, replacement for typeid + + virtual InlineCost getInlineCost(CallSite CS); + + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + virtual bool runOnSCC(CallGraphSCC &SCC); + + using llvm::Pass::doFinalization; + virtual bool doFinalization(CallGraph &CG) { + return removeDeadFunctions(CG, /*AlwaysInlineOnly=*/ true); + } +}; + } char AlwaysInliner::ID = 0; INITIALIZE_PASS_BEGIN(AlwaysInliner, "always-inline", "Inliner for always_inline functions", false, false) INITIALIZE_AG_DEPENDENCY(CallGraph) +INITIALIZE_PASS_DEPENDENCY(InlineCostAnalysis) INITIALIZE_PASS_END(AlwaysInliner, "always-inline", "Inliner for always_inline functions", false, false) @@ -87,16 +93,20 @@ InlineCost AlwaysInliner::getInlineCost(CallSite CS) { // that are viable for inlining. FIXME: We shouldn't even get here for // declarations. if (Callee && !Callee->isDeclaration() && - Callee->getFnAttributes().hasAttribute(Attributes::AlwaysInline) && - CA.isInlineViable(*Callee)) + Callee->getAttributes().hasAttribute(AttributeSet::FunctionIndex, + Attribute::AlwaysInline) && + ICA->isInlineViable(*Callee)) return InlineCost::getAlways(); return InlineCost::getNever(); } -// doInitialization - Initializes the vector of functions that have not -// been annotated with the "always inline" attribute. -bool AlwaysInliner::doInitialization(CallGraph &CG) { - CA.setDataLayout(getAnalysisIfAvailable<DataLayout>()); - return false; +bool AlwaysInliner::runOnSCC(CallGraphSCC &SCC) { + ICA = &getAnalysis<InlineCostAnalysis>(); + return Inliner::runOnSCC(SCC); +} + +void AlwaysInliner::getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired<InlineCostAnalysis>(); + Inliner::getAnalysisUsage(AU); } diff --git a/lib/Transforms/IPO/InlineSimple.cpp b/lib/Transforms/IPO/InlineSimple.cpp index 9c5feba08b..a4f7026041 100644 --- a/lib/Transforms/IPO/InlineSimple.cpp +++ b/lib/Transforms/IPO/InlineSimple.cpp @@ -15,42 +15,54 @@ #include "llvm/Transforms/IPO.h" #include "llvm/Analysis/CallGraph.h" #include "llvm/Analysis/InlineCost.h" -#include "llvm/CallingConv.h" -#include "llvm/DataLayout.h" -#include "llvm/Instructions.h" -#include "llvm/IntrinsicInst.h" -#include "llvm/Module.h" +#include "llvm/IR/CallingConv.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/Type.h" #include "llvm/Support/CallSite.h" #include "llvm/Transforms/IPO/InlinerPass.h" -#include "llvm/Type.h" using namespace llvm; namespace { - class SimpleInliner : public Inliner { - InlineCostAnalyzer CA; - public: - SimpleInliner() : Inliner(ID) { - initializeSimpleInlinerPass(*PassRegistry::getPassRegistry()); - } - SimpleInliner(int Threshold) : Inliner(ID, Threshold, - /*InsertLifetime*/true) { - initializeSimpleInlinerPass(*PassRegistry::getPassRegistry()); - } - static char ID; // Pass identification, replacement for typeid - InlineCost getInlineCost(CallSite CS) { - return CA.getInlineCost(CS, getInlineThreshold(CS)); - } - using llvm::Pass::doInitialization; - virtual bool doInitialization(CallGraph &CG); - }; -} +/// \brief Actaul inliner pass implementation. +/// +/// The common implementation of the inlining logic is shared between this +/// inliner pass and the always inliner pass. The two passes use different cost +/// analyses to determine when to inline. +class SimpleInliner : public Inliner { + InlineCostAnalysis *ICA; + +public: + SimpleInliner() : Inliner(ID), ICA(0) { + initializeSimpleInlinerPass(*PassRegistry::getPassRegistry()); + } + + SimpleInliner(int Threshold) + : Inliner(ID, Threshold, /*InsertLifetime*/ true), ICA(0) { + initializeSimpleInlinerPass(*PassRegistry::getPassRegistry()); + } + + static char ID; // Pass identification, replacement for typeid + + InlineCost getInlineCost(CallSite CS) { + return ICA->getInlineCost(CS, getInlineThreshold(CS)); + } + + virtual bool runOnSCC(CallGraphSCC &SCC); + virtual void getAnalysisUsage(AnalysisUsage &AU) const; +}; + +} // end anonymous namespace char SimpleInliner::ID = 0; INITIALIZE_PASS_BEGIN(SimpleInliner, "inline", "Function Integration/Inlining", false, false) INITIALIZE_AG_DEPENDENCY(CallGraph) +INITIALIZE_PASS_DEPENDENCY(InlineCostAnalysis) INITIALIZE_PASS_END(SimpleInliner, "inline", "Function Integration/Inlining", false, false) @@ -60,10 +72,12 @@ Pass *llvm::createFunctionInliningPass(int Threshold) { return new SimpleInliner(Threshold); } -// doInitialization - Initializes the vector of functions that have been -// annotated with the noinline attribute. -bool SimpleInliner::doInitialization(CallGraph &CG) { - CA.setDataLayout(getAnalysisIfAvailable<DataLayout>()); - return false; +bool SimpleInliner::runOnSCC(CallGraphSCC &SCC) { + ICA = &getAnalysis<InlineCostAnalysis>(); + return Inliner::runOnSCC(SCC); } +void SimpleInliner::getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired<InlineCostAnalysis>(); + Inliner::getAnalysisUsage(AU); +} diff --git a/lib/Transforms/IPO/Inliner.cpp b/lib/Transforms/IPO/Inliner.cpp index bd8fa66d52..663ddb75f4 100644 --- a/lib/Transforms/IPO/Inliner.cpp +++ b/lib/Transforms/IPO/Inliner.cpp @@ -19,10 +19,10 @@ #include "llvm/ADT/Statistic.h" #include "llvm/Analysis/CallGraph.h" #include "llvm/Analysis/InlineCost.h" -#include "llvm/DataLayout.h" -#include "llvm/Instructions.h" -#include "llvm/IntrinsicInst.h" -#include "llvm/Module.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/Module.h" #include "llvm/Support/CallSite.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" @@ -64,14 +64,48 @@ Inliner::Inliner(char &ID, int Threshold, bool InsertLifetime) /// getAnalysisUsage - For this class, we declare that we require and preserve /// the call graph. If the derived class implements this method, it should /// always explicitly call the implementation here. -void Inliner::getAnalysisUsage(AnalysisUsage &Info) const { - CallGraphSCCPass::getAnalysisUsage(Info); +void Inliner::getAnalysisUsage(AnalysisUsage &AU) const { + CallGraphSCCPass::getAnalysisUsage(AU); } typedef DenseMap<ArrayType*, std::vector<AllocaInst*> > InlinedArrayAllocasTy; +/// \brief If the inlined function had a higher stack protection level than the +/// calling function, then bump up the caller's stack protection level. +static void AdjustCallerSSPLevel(Function *Caller, Function *Callee) { + // If upgrading the SSP attribute, clear out the old SSP Attributes first. + // Having multiple SSP attributes doesn't actually hurt, but it adds useless + // clutter to the IR. + AttrBuilder B; + B.addAttribute(Attribute::StackProtect) + .addAttribute(Attribute::StackProtectStrong); + AttributeSet OldSSPAttr = AttributeSet::get(Caller->getContext(), + AttributeSet::FunctionIndex, + B); + AttributeSet CallerAttr = Caller->getAttributes(), + CalleeAttr = Callee->getAttributes(); + + if (CalleeAttr.hasAttribute(AttributeSet::FunctionIndex, + Attribute::StackProtectReq)) { + Caller->removeAttributes(AttributeSet::FunctionIndex, OldSSPAttr); + Caller->addFnAttr(Attribute::StackProtectReq); + } else if (CalleeAttr.hasAttribute(AttributeSet::FunctionIndex, + Attribute::StackProtectStrong) && + !CallerAttr.hasAttribute(AttributeSet::FunctionIndex, + Attribute::StackProtectReq)) { + Caller->removeAttributes(AttributeSet::FunctionIndex, OldSSPAttr); + Caller->addFnAttr(Attribute::StackProtectStrong); + } else if (CalleeAttr.hasAttribute(AttributeSet::FunctionIndex, + Attribute::StackProtect) && + !CallerAttr.hasAttribute(AttributeSet::FunctionIndex, + Attribute::StackProtectReq) && + !CallerAttr.hasAttribute(AttributeSet::FunctionIndex, + Attribute::StackProtectStrong)) + Caller->addFnAttr(Attribute::StackProtect); +} + /// InlineCallIfPossible - If it is possible to inline the specified call site, /// do so and update the CallGraph for this operation. /// @@ -91,13 +125,7 @@ static bool InlineCallIfPossible(CallSite CS, InlineFunctionInfo &IFI, if (!InlineFunction(CS, IFI, InsertLifetime)) return false; - // If the inlined function had a higher stack protection level than the - // calling function, then bump up the caller's stack protection level. - if (Callee->getFnAttributes().hasAttribute(Attributes::StackProtectReq)) - Caller->addFnAttr(Attributes::StackProtectReq); - else if (Callee->getFnAttributes().hasAttribute(Attributes::StackProtect) && - !Caller->getFnAttributes().hasAttribute(Attributes::StackProtectReq)) - Caller->addFnAttr(Attributes::StackProtect); + AdjustCallerSSPLevel(Caller, Callee); // Look at all of the allocas that we inlined through this call site. If we // have already inlined other allocas through other calls into this function, @@ -209,16 +237,21 @@ unsigned Inliner::getInlineThreshold(CallSite CS) const { // would decrease the threshold. Function *Caller = CS.getCaller(); bool OptSize = Caller && !Caller->isDeclaration() && - Caller->getFnAttributes().hasAttribute(Attributes::OptimizeForSize); + Caller->getAttributes().hasAttribute(AttributeSet::FunctionIndex, + Attribute::OptimizeForSize); if (!(InlineLimit.getNumOccurrences() > 0) && OptSize && OptSizeThreshold < thres) thres = OptSizeThreshold; - // Listen to the inlinehint attribute when it would increase the threshold. + // Listen to the inlinehint attribute when it would increase the threshold + // and the caller does not need to minimize its size. Function *Callee = CS.getCalledFunction(); bool InlineHint = Callee && !Callee->isDeclaration() && - Callee->getFnAttributes().hasAttribute(Attributes::InlineHint); - if (InlineHint && HintThreshold > thres) + Callee->getAttributes().hasAttribute(AttributeSet::FunctionIndex, + Attribute::InlineHint); + if (InlineHint && HintThreshold > thres + && !Caller->getAttributes().hasAttribute(AttributeSet::FunctionIndex, + Attribute::MinSize)) thres = HintThreshold; return thres; @@ -534,7 +567,8 @@ bool Inliner::removeDeadFunctions(CallGraph &CG, bool AlwaysInlineOnly) { // about always-inline functions. This is a bit of a hack to share code // between here and the InlineAlways pass. if (AlwaysInlineOnly && - !F->getFnAttributes().hasAttribute(Attributes::AlwaysInline)) + !F->getAttributes().hasAttribute(AttributeSet::FunctionIndex, + Attribute::AlwaysInline)) continue; // If the only remaining users of the function are dead constants, remove diff --git a/lib/Transforms/IPO/Internalize.cpp b/lib/Transforms/IPO/Internalize.cpp index b2cd3a765a..4bfab5b0af 100644 --- a/lib/Transforms/IPO/Internalize.cpp +++ b/lib/Transforms/IPO/Internalize.cpp @@ -17,7 +17,7 @@ #include "llvm/Transforms/IPO.h" #include "llvm/ADT/Statistic.h" #include "llvm/Analysis/CallGraph.h" -#include "llvm/Module.h" +#include "llvm/IR/Module.h" #include "llvm/Pass.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" @@ -48,8 +48,10 @@ namespace { public: static char ID; // Pass identification, replacement for typeid explicit InternalizePass(); - explicit InternalizePass(const std::vector <const char *>& exportList); + explicit InternalizePass(ArrayRef<const char *> exportList); void LoadFile(const char *Filename); + void ClearExportList(); + void AddToExportList(const std::string &val); virtual bool runOnModule(Module &M); virtual void getAnalysisUsage(AnalysisUsage &AU) const { @@ -72,10 +74,10 @@ InternalizePass::InternalizePass() ExternalNames.insert(APIList.begin(), APIList.end()); } -InternalizePass::InternalizePass(const std::vector<const char *>&exportList) +InternalizePass::InternalizePass(ArrayRef<const char *> exportList) : ModulePass(ID){ initializeInternalizePassPass(*PassRegistry::getPassRegistry()); - for(std::vector<const char *>::const_iterator itr = exportList.begin(); + for(ArrayRef<const char *>::const_iterator itr = exportList.begin(); itr != exportList.end(); itr++) { ExternalNames.insert(*itr); } @@ -97,6 +99,14 @@ void InternalizePass::LoadFile(const char *Filename) { } } +void InternalizePass::ClearExportList() { + ExternalNames.clear(); +} + +void InternalizePass::AddToExportList(const std::string &val) { + ExternalNames.insert(val); +} + bool InternalizePass::runOnModule(Module &M) { CallGraph *CG = getAnalysisIfAvailable<CallGraph>(); CallGraphNode *ExternalNode = CG ? CG->getExternalCallingNode() : 0; @@ -173,6 +183,6 @@ ModulePass *llvm::createInternalizePass() { return new InternalizePass(); } -ModulePass *llvm::createInternalizePass(const std::vector <const char *> &el) { +ModulePass *llvm::createInternalizePass(ArrayRef<const char *> el) { return new InternalizePass(el); } diff --git a/lib/Transforms/IPO/LLVMBuild.txt b/lib/Transforms/IPO/LLVMBuild.txt index b18c9150f4..124cbb6f05 100644 --- a/lib/Transforms/IPO/LLVMBuild.txt +++ b/lib/Transforms/IPO/LLVMBuild.txt @@ -20,4 +20,4 @@ type = Library name = IPO parent = Transforms library_name = ipo -required_libraries = Analysis Core IPA InstCombine Scalar Vectorize Support Target TransformUtils +required_libraries = Analysis Core IPA InstCombine Scalar Vectorize Support Target TransformUtils ObjCARC diff --git a/lib/Transforms/IPO/LoopExtractor.cpp b/lib/Transforms/IPO/LoopExtractor.cpp index af04d054ed..8282a8e6fa 100644 --- a/lib/Transforms/IPO/LoopExtractor.cpp +++ b/lib/Transforms/IPO/LoopExtractor.cpp @@ -19,8 +19,8 @@ #include "llvm/ADT/Statistic.h" #include "llvm/Analysis/Dominators.h" #include "llvm/Analysis/LoopPass.h" -#include "llvm/Instructions.h" -#include "llvm/Module.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/Module.h" #include "llvm/Pass.h" #include "llvm/Support/CommandLine.h" #include "llvm/Transforms/Scalar.h" diff --git a/lib/Transforms/IPO/MergeFunctions.cpp b/lib/Transforms/IPO/MergeFunctions.cpp index 70345b8334..892100f058 100644 --- a/lib/Transforms/IPO/MergeFunctions.cpp +++ b/lib/Transforms/IPO/MergeFunctions.cpp @@ -50,14 +50,14 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/Statistic.h" -#include "llvm/Constants.h" -#include "llvm/DataLayout.h" -#include "llvm/IRBuilder.h" -#include "llvm/InlineAsm.h" -#include "llvm/Instructions.h" -#include "llvm/LLVMContext.h" -#include "llvm/Module.h" -#include "llvm/Operator.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/InlineAsm.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/Operator.h" #include "llvm/Pass.h" #include "llvm/Support/CallSite.h" #include "llvm/Support/Debug.h" @@ -346,13 +346,11 @@ 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(GEP1->idx_begin(), GEP1->idx_end()); - SmallVector<Value *, 8> Indices2(GEP2->idx_begin(), GEP2->idx_end()); - uint64_t Offset1 = TD->getIndexedOffset(GEP1->getPointerOperandType(), - Indices1); - uint64_t Offset2 = TD->getIndexedOffset(GEP2->getPointerOperandType(), - Indices2); + unsigned BitWidth = TD ? TD->getPointerSizeInBits() : 1; + APInt Offset1(BitWidth, 0), Offset2(BitWidth, 0); + if (TD && + GEP1->accumulateConstantOffset(*TD, Offset1) && + GEP2->accumulateConstantOffset(*TD, Offset2)) { return Offset1 == Offset2; } diff --git a/lib/Transforms/IPO/PartialInlining.cpp b/lib/Transforms/IPO/PartialInlining.cpp index 6bd9c8372e..fa518cb0ab 100644 --- a/lib/Transforms/IPO/PartialInlining.cpp +++ b/lib/Transforms/IPO/PartialInlining.cpp @@ -16,8 +16,8 @@ #include "llvm/Transforms/IPO.h" #include "llvm/ADT/Statistic.h" #include "llvm/Analysis/Dominators.h" -#include "llvm/Instructions.h" -#include "llvm/Module.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/Module.h" #include "llvm/Pass.h" #include "llvm/Support/CFG.h" #include "llvm/Transforms/Utils/Cloning.h" diff --git a/lib/Transforms/IPO/PassManagerBuilder.cpp b/lib/Transforms/IPO/PassManagerBuilder.cpp index a9a9f2eece..027a9f2a68 100644 --- a/lib/Transforms/IPO/PassManagerBuilder.cpp +++ b/lib/Transforms/IPO/PassManagerBuilder.cpp @@ -18,8 +18,6 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/Analysis/Passes.h" #include "llvm/Analysis/Verifier.h" -#include "llvm/DefaultPasses.h" -#include "llvm/PassManager.h" #include "llvm/PassManager.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ManagedStatic.h" @@ -188,7 +186,7 @@ void PassManagerBuilder::populateModulePassManager(PassManagerBase &MPM) { MPM.add(createLoopIdiomPass()); // Recognize idioms like memset. MPM.add(createLoopDeletionPass()); // Delete dead loops - if (LoopVectorize && OptLevel > 1) + if (LoopVectorize && OptLevel > 2) MPM.add(createLoopVectorizePass()); if (!DisableUnrollLoops) @@ -216,6 +214,10 @@ void PassManagerBuilder::populateModulePassManager(PassManagerBase &MPM) { MPM.add(createGVNPass()); // Remove redundancies else MPM.add(createEarlyCSEPass()); // Catch trivial redundancies + + // BBVectorize may have significantly shortened a loop body; unroll again. + if (!DisableUnrollLoops) + MPM.add(createLoopUnrollPass()); } MPM.add(createAggressiveDCEPass()); // Delete dead instructions @@ -389,9 +391,9 @@ LLVMPassManagerBuilderPopulateModulePassManager(LLVMPassManagerBuilderRef PMB, void LLVMPassManagerBuilderPopulateLTOPassManager(LLVMPassManagerBuilderRef PMB, LLVMPassManagerRef PM, - bool Internalize, - bool RunInliner) { + LLVMBool Internalize, + LLVMBool RunInliner) { PassManagerBuilder *Builder = unwrap(PMB); PassManagerBase *LPM = unwrap(PM); - Builder->populateLTOPassManager(*LPM, Internalize, RunInliner); + Builder->populateLTOPassManager(*LPM, Internalize != 0, RunInliner != 0); } diff --git a/lib/Transforms/IPO/PruneEH.cpp b/lib/Transforms/IPO/PruneEH.cpp index 19f34837c7..73d9323195 100644 --- a/lib/Transforms/IPO/PruneEH.cpp +++ b/lib/Transforms/IPO/PruneEH.cpp @@ -20,12 +20,12 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Statistic.h" #include "llvm/Analysis/CallGraph.h" -#include "llvm/CallGraphSCCPass.h" -#include "llvm/Constants.h" -#include "llvm/Function.h" -#include "llvm/Instructions.h" -#include "llvm/IntrinsicInst.h" -#include "llvm/LLVMContext.h" +#include "llvm/Analysis/CallGraphSCCPass.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/LLVMContext.h" #include "llvm/Support/CFG.h" #include <algorithm> using namespace llvm; @@ -140,15 +140,17 @@ bool PruneEH::runOnSCC(CallGraphSCC &SCC) { AttrBuilder NewAttributes; if (!SCCMightUnwind) - NewAttributes.addAttribute(Attributes::NoUnwind); + NewAttributes.addAttribute(Attribute::NoUnwind); if (!SCCMightReturn) - NewAttributes.addAttribute(Attributes::NoReturn); + NewAttributes.addAttribute(Attribute::NoReturn); Function *F = (*I)->getFunction(); const AttributeSet &PAL = F->getAttributes(); - const AttributeSet &NPAL = PAL.addAttr(F->getContext(), ~0, - Attributes::get(F->getContext(), - NewAttributes)); + const AttributeSet &NPAL = + PAL.addAttributes(F->getContext(), AttributeSet::FunctionIndex, + AttributeSet::get(F->getContext(), + AttributeSet::FunctionIndex, + NewAttributes)); if (PAL != NPAL) { MadeChange = true; F->setAttributes(NPAL); diff --git a/lib/Transforms/IPO/StripDeadPrototypes.cpp b/lib/Transforms/IPO/StripDeadPrototypes.cpp index 80cb869f02..f00830aada 100644 --- a/lib/Transforms/IPO/StripDeadPrototypes.cpp +++ b/lib/Transforms/IPO/StripDeadPrototypes.cpp @@ -17,7 +17,7 @@ #define DEBUG_TYPE "strip-dead-prototypes" #include "llvm/Transforms/IPO.h" #include "llvm/ADT/Statistic.h" -#include "llvm/Module.h" +#include "llvm/IR/Module.h" #include "llvm/Pass.h" using namespace llvm; diff --git a/lib/Transforms/IPO/StripSymbols.cpp b/lib/Transforms/IPO/StripSymbols.cpp index ad915d716f..5f8681ff45 100644 --- a/lib/Transforms/IPO/StripSymbols.cpp +++ b/lib/Transforms/IPO/StripSymbols.cpp @@ -23,15 +23,15 @@ #include "llvm/Transforms/IPO.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallPtrSet.h" -#include "llvm/Constants.h" #include "llvm/DebugInfo.h" -#include "llvm/DerivedTypes.h" -#include "llvm/Instructions.h" -#include "llvm/Module.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/TypeFinder.h" +#include "llvm/IR/ValueSymbolTable.h" #include "llvm/Pass.h" #include "llvm/Transforms/Utils/Local.h" -#include "llvm/TypeFinder.h" -#include "llvm/ValueSymbolTable.h" using namespace llvm; namespace { |