diff options
Diffstat (limited to 'lib/Transforms/IPO/FunctionAttrs.cpp')
-rw-r--r-- | lib/Transforms/IPO/FunctionAttrs.cpp | 38 |
1 files changed, 20 insertions, 18 deletions
diff --git a/lib/Transforms/IPO/FunctionAttrs.cpp b/lib/Transforms/IPO/FunctionAttrs.cpp index e831524..7edaa7f 100644 --- a/lib/Transforms/IPO/FunctionAttrs.cpp +++ b/lib/Transforms/IPO/FunctionAttrs.cpp @@ -26,6 +26,7 @@ #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Analysis/CallGraph.h" #include "llvm/Analysis/CaptureTracking.h" +#include "llvm/Analysis/MallocHelper.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/Statistic.h" #include "llvm/ADT/UniqueVector.h" @@ -44,7 +45,7 @@ namespace { FunctionAttrs() : CallGraphSCCPass(&ID) {} // runOnSCC - Analyze the SCC, performing the transformation if possible. - bool runOnSCC(const std::vector<CallGraphNode *> &SCC); + bool runOnSCC(std::vector<CallGraphNode *> &SCC); // AddReadAttrs - Deduce readonly/readnone attributes for the SCC. bool AddReadAttrs(const std::vector<CallGraphNode *> &SCC); @@ -54,7 +55,7 @@ namespace { // IsFunctionMallocLike - Does this function allocate new memory? bool IsFunctionMallocLike(Function *F, - SmallPtrSet<CallGraphNode*, 8> &) const; + SmallPtrSet<Function*, 8> &) const; // AddNoAliasAttrs - Deduce noalias attributes for the SCC. bool AddNoAliasAttrs(const std::vector<CallGraphNode *> &SCC); @@ -93,13 +94,12 @@ bool FunctionAttrs::PointsToLocalMemory(Value *V) { /// AddReadAttrs - Deduce readonly/readnone attributes for the SCC. bool FunctionAttrs::AddReadAttrs(const std::vector<CallGraphNode *> &SCC) { - SmallPtrSet<CallGraphNode*, 8> SCCNodes; - CallGraph &CG = getAnalysis<CallGraph>(); + SmallPtrSet<Function*, 8> SCCNodes; // Fill SCCNodes with the elements of the SCC. Used for quickly // looking up whether a given CallGraphNode is in this SCC. for (unsigned i = 0, e = SCC.size(); i != e; ++i) - SCCNodes.insert(SCC[i]); + SCCNodes.insert(SCC[i]->getFunction()); // Check if any of the functions in the SCC read or write memory. If they // write memory then they can't be marked readnone or readonly. @@ -133,9 +133,9 @@ bool FunctionAttrs::AddReadAttrs(const std::vector<CallGraphNode *> &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()) { + if (CS.getInstruction() && CS.getCalledFunction()) { // Ignore calls to functions in the same SCC. - if (SCCNodes.count(CG[CS.getCalledFunction()])) + if (SCCNodes.count(CS.getCalledFunction())) continue; } else if (LoadInst *LI = dyn_cast<LoadInst>(I)) { // Ignore loads from local memory. @@ -154,7 +154,7 @@ bool FunctionAttrs::AddReadAttrs(const std::vector<CallGraphNode *> &SCC) { return false; if (isa<MallocInst>(I)) - // MallocInst claims not to write memory! PR3754. + // malloc claims not to write memory! PR3754. return false; // If this instruction may read memory, remember that. @@ -226,9 +226,7 @@ bool FunctionAttrs::AddNoCaptureAttrs(const std::vector<CallGraphNode *> &SCC) { /// IsFunctionMallocLike - A function is malloc-like if it returns either null /// or a pointer that doesn't alias any other pointer visible to the caller. bool FunctionAttrs::IsFunctionMallocLike(Function *F, - SmallPtrSet<CallGraphNode*, 8> &SCCNodes) const { - CallGraph &CG = getAnalysis<CallGraph>(); - + SmallPtrSet<Function*, 8> &SCCNodes) const { UniqueVector<Value *> FlowsToReturn; for (Function::iterator I = F->begin(), E = F->end(); I != E; ++I) if (ReturnInst *Ret = dyn_cast<ReturnInst>(I->getTerminator())) @@ -250,32 +248,36 @@ bool FunctionAttrs::IsFunctionMallocLike(Function *F, if (Instruction *RVI = dyn_cast<Instruction>(RetVal)) switch (RVI->getOpcode()) { // Extend the analysis by looking upwards. - case Instruction::GetElementPtr: case Instruction::BitCast: + case Instruction::GetElementPtr: FlowsToReturn.insert(RVI->getOperand(0)); continue; case Instruction::Select: { SelectInst *SI = cast<SelectInst>(RVI); FlowsToReturn.insert(SI->getTrueValue()); FlowsToReturn.insert(SI->getFalseValue()); - } continue; + continue; + } case Instruction::PHI: { PHINode *PN = cast<PHINode>(RVI); for (int i = 0, e = PN->getNumIncomingValues(); i != e; ++i) FlowsToReturn.insert(PN->getIncomingValue(i)); - } continue; + continue; + } // Check whether the pointer came from an allocation. case Instruction::Alloca: case Instruction::Malloc: break; case Instruction::Call: + if (isMalloc(RVI)) + break; case Instruction::Invoke: { CallSite CS(RVI); if (CS.paramHasAttr(0, Attribute::NoAlias)) break; if (CS.getCalledFunction() && - SCCNodes.count(CG[CS.getCalledFunction()])) + SCCNodes.count(CS.getCalledFunction())) break; } // fall-through default: @@ -291,12 +293,12 @@ bool FunctionAttrs::IsFunctionMallocLike(Function *F, /// AddNoAliasAttrs - Deduce noalias attributes for the SCC. bool FunctionAttrs::AddNoAliasAttrs(const std::vector<CallGraphNode *> &SCC) { - SmallPtrSet<CallGraphNode*, 8> SCCNodes; + SmallPtrSet<Function*, 8> SCCNodes; // Fill SCCNodes with the elements of the SCC. Used for quickly // looking up whether a given CallGraphNode is in this SCC. for (unsigned i = 0, e = SCC.size(); i != e; ++i) - SCCNodes.insert(SCC[i]); + SCCNodes.insert(SCC[i]->getFunction()); // Check each function in turn, determining which functions return noalias // pointers. @@ -339,7 +341,7 @@ bool FunctionAttrs::AddNoAliasAttrs(const std::vector<CallGraphNode *> &SCC) { return MadeChange; } -bool FunctionAttrs::runOnSCC(const std::vector<CallGraphNode *> &SCC) { +bool FunctionAttrs::runOnSCC(std::vector<CallGraphNode *> &SCC) { bool Changed = AddReadAttrs(SCC); Changed |= AddNoCaptureAttrs(SCC); Changed |= AddNoAliasAttrs(SCC); |