| Duncan Sands | 44c8cd9 | 2008-12-31 16:14:43 +0000 | [diff] [blame] | 1 | //===- FunctionAttrs.cpp - Pass which marks functions readnone or readonly ===// | 
|  | 2 | // | 
|  | 3 | //                     The LLVM Compiler Infrastructure | 
|  | 4 | // | 
|  | 5 | // This file is distributed under the University of Illinois Open Source | 
|  | 6 | // License. See LICENSE.TXT for details. | 
|  | 7 | // | 
|  | 8 | //===----------------------------------------------------------------------===// | 
|  | 9 | // | 
|  | 10 | // This file implements a simple interprocedural pass which walks the | 
|  | 11 | // call-graph, looking for functions which do not access or only read | 
| Duncan Sands | cefc860 | 2009-01-02 11:46:24 +0000 | [diff] [blame] | 12 | // non-local memory, and marking them readnone/readonly.  In addition, | 
|  | 13 | // it marks function arguments (of pointer type) 'nocapture' if a call | 
|  | 14 | // to the function does not create any copies of the pointer value that | 
|  | 15 | // outlive the call.  This more or less means that the pointer is only | 
|  | 16 | // dereferenced, and not returned from the function or stored in a global. | 
|  | 17 | // This pass is implemented as a bottom-up traversal of the call-graph. | 
| Duncan Sands | 44c8cd9 | 2008-12-31 16:14:43 +0000 | [diff] [blame] | 18 | // | 
|  | 19 | //===----------------------------------------------------------------------===// | 
|  | 20 |  | 
|  | 21 | #define DEBUG_TYPE "functionattrs" | 
|  | 22 | #include "llvm/Transforms/IPO.h" | 
|  | 23 | #include "llvm/CallGraphSCCPass.h" | 
|  | 24 | #include "llvm/GlobalVariable.h" | 
| Devang Patel | cc40a61 | 2009-03-03 00:28:44 +0000 | [diff] [blame] | 25 | #include "llvm/IntrinsicInst.h" | 
| Nick Lewycky | fbed86a | 2009-03-08 06:20:47 +0000 | [diff] [blame] | 26 | #include "llvm/Analysis/AliasAnalysis.h" | 
| Duncan Sands | 44c8cd9 | 2008-12-31 16:14:43 +0000 | [diff] [blame] | 27 | #include "llvm/Analysis/CallGraph.h" | 
| Duncan Sands | e0aa0d6 | 2009-01-18 12:19:30 +0000 | [diff] [blame] | 28 | #include "llvm/Analysis/CaptureTracking.h" | 
| Duncan Sands | b193a37 | 2009-01-02 11:54:37 +0000 | [diff] [blame] | 29 | #include "llvm/ADT/SmallSet.h" | 
| Duncan Sands | 44c8cd9 | 2008-12-31 16:14:43 +0000 | [diff] [blame] | 30 | #include "llvm/ADT/Statistic.h" | 
| Nick Lewycky | fbed86a | 2009-03-08 06:20:47 +0000 | [diff] [blame] | 31 | #include "llvm/ADT/UniqueVector.h" | 
| Duncan Sands | 44c8cd9 | 2008-12-31 16:14:43 +0000 | [diff] [blame] | 32 | #include "llvm/Support/Compiler.h" | 
|  | 33 | #include "llvm/Support/InstIterator.h" | 
|  | 34 | using namespace llvm; | 
|  | 35 |  | 
|  | 36 | STATISTIC(NumReadNone, "Number of functions marked readnone"); | 
|  | 37 | STATISTIC(NumReadOnly, "Number of functions marked readonly"); | 
|  | 38 | STATISTIC(NumNoCapture, "Number of arguments marked nocapture"); | 
| Nick Lewycky | fbed86a | 2009-03-08 06:20:47 +0000 | [diff] [blame] | 39 | STATISTIC(NumNoAlias, "Number of function returns marked noalias"); | 
| Duncan Sands | 44c8cd9 | 2008-12-31 16:14:43 +0000 | [diff] [blame] | 40 |  | 
|  | 41 | namespace { | 
|  | 42 | struct VISIBILITY_HIDDEN FunctionAttrs : public CallGraphSCCPass { | 
|  | 43 | static char ID; // Pass identification, replacement for typeid | 
|  | 44 | FunctionAttrs() : CallGraphSCCPass(&ID) {} | 
|  | 45 |  | 
|  | 46 | // runOnSCC - Analyze the SCC, performing the transformation if possible. | 
|  | 47 | bool runOnSCC(const std::vector<CallGraphNode *> &SCC); | 
|  | 48 |  | 
|  | 49 | // AddReadAttrs - Deduce readonly/readnone attributes for the SCC. | 
|  | 50 | bool AddReadAttrs(const std::vector<CallGraphNode *> &SCC); | 
|  | 51 |  | 
|  | 52 | // AddNoCaptureAttrs - Deduce nocapture attributes for the SCC. | 
|  | 53 | bool AddNoCaptureAttrs(const std::vector<CallGraphNode *> &SCC); | 
|  | 54 |  | 
| Nick Lewycky | fbed86a | 2009-03-08 06:20:47 +0000 | [diff] [blame] | 55 | // IsFunctionMallocLike - Does this function allocate new memory? | 
|  | 56 | bool IsFunctionMallocLike(Function *F, | 
|  | 57 | SmallPtrSet<CallGraphNode*, 8> &) const; | 
|  | 58 |  | 
|  | 59 | // AddNoAliasAttrs - Deduce noalias attributes for the SCC. | 
|  | 60 | bool AddNoAliasAttrs(const std::vector<CallGraphNode *> &SCC); | 
|  | 61 |  | 
| Duncan Sands | 44c8cd9 | 2008-12-31 16:14:43 +0000 | [diff] [blame] | 62 | virtual void getAnalysisUsage(AnalysisUsage &AU) const { | 
|  | 63 | AU.setPreservesCFG(); | 
|  | 64 | CallGraphSCCPass::getAnalysisUsage(AU); | 
|  | 65 | } | 
|  | 66 |  | 
|  | 67 | bool PointsToLocalMemory(Value *V); | 
|  | 68 | }; | 
|  | 69 | } | 
|  | 70 |  | 
|  | 71 | char FunctionAttrs::ID = 0; | 
|  | 72 | static RegisterPass<FunctionAttrs> | 
|  | 73 | X("functionattrs", "Deduce function attributes"); | 
|  | 74 |  | 
|  | 75 | Pass *llvm::createFunctionAttrsPass() { return new FunctionAttrs(); } | 
|  | 76 |  | 
|  | 77 |  | 
|  | 78 | /// PointsToLocalMemory - Returns whether the given pointer value points to | 
|  | 79 | /// memory that is local to the function.  Global constants are considered | 
|  | 80 | /// local to all functions. | 
|  | 81 | bool FunctionAttrs::PointsToLocalMemory(Value *V) { | 
|  | 82 | V = V->getUnderlyingObject(); | 
|  | 83 | // An alloca instruction defines local memory. | 
|  | 84 | if (isa<AllocaInst>(V)) | 
|  | 85 | return true; | 
|  | 86 | // A global constant counts as local memory for our purposes. | 
|  | 87 | if (GlobalVariable *GV = dyn_cast<GlobalVariable>(V)) | 
|  | 88 | return GV->isConstant(); | 
|  | 89 | // Could look through phi nodes and selects here, but it doesn't seem | 
|  | 90 | // to be useful in practice. | 
|  | 91 | return false; | 
|  | 92 | } | 
|  | 93 |  | 
|  | 94 | /// AddReadAttrs - Deduce readonly/readnone attributes for the SCC. | 
|  | 95 | bool FunctionAttrs::AddReadAttrs(const std::vector<CallGraphNode *> &SCC) { | 
|  | 96 | SmallPtrSet<CallGraphNode*, 8> SCCNodes; | 
|  | 97 | CallGraph &CG = getAnalysis<CallGraph>(); | 
|  | 98 |  | 
|  | 99 | // Fill SCCNodes with the elements of the SCC.  Used for quickly | 
|  | 100 | // looking up whether a given CallGraphNode is in this SCC. | 
|  | 101 | for (unsigned i = 0, e = SCC.size(); i != e; ++i) | 
|  | 102 | SCCNodes.insert(SCC[i]); | 
|  | 103 |  | 
|  | 104 | // Check if any of the functions in the SCC read or write memory.  If they | 
|  | 105 | // write memory then they can't be marked readnone or readonly. | 
|  | 106 | bool ReadsMemory = false; | 
|  | 107 | for (unsigned i = 0, e = SCC.size(); i != e; ++i) { | 
|  | 108 | Function *F = SCC[i]->getFunction(); | 
|  | 109 |  | 
|  | 110 | if (F == 0) | 
|  | 111 | // External node - may write memory.  Just give up. | 
|  | 112 | return false; | 
|  | 113 |  | 
|  | 114 | if (F->doesNotAccessMemory()) | 
|  | 115 | // Already perfect! | 
|  | 116 | continue; | 
|  | 117 |  | 
|  | 118 | // Definitions with weak linkage may be overridden at linktime with | 
|  | 119 | // something that writes memory, so treat them like declarations. | 
|  | 120 | if (F->isDeclaration() || F->mayBeOverridden()) { | 
|  | 121 | if (!F->onlyReadsMemory()) | 
|  | 122 | // May write memory.  Just give up. | 
|  | 123 | return false; | 
|  | 124 |  | 
|  | 125 | ReadsMemory = true; | 
|  | 126 | continue; | 
|  | 127 | } | 
|  | 128 |  | 
|  | 129 | // Scan the function body for instructions that may read or write memory. | 
|  | 130 | for (inst_iterator II = inst_begin(F), E = inst_end(F); II != E; ++II) { | 
|  | 131 | Instruction *I = &*II; | 
|  | 132 |  | 
|  | 133 | // Some instructions can be ignored even if they read or write memory. | 
|  | 134 | // Detect these now, skipping to the next instruction if one is found. | 
|  | 135 | CallSite CS = CallSite::get(I); | 
|  | 136 | if (CS.getInstruction()) { | 
|  | 137 | // Ignore calls to functions in the same SCC. | 
|  | 138 | if (SCCNodes.count(CG[CS.getCalledFunction()])) | 
|  | 139 | continue; | 
|  | 140 | } else if (LoadInst *LI = dyn_cast<LoadInst>(I)) { | 
|  | 141 | // Ignore loads from local memory. | 
|  | 142 | if (PointsToLocalMemory(LI->getPointerOperand())) | 
|  | 143 | continue; | 
|  | 144 | } else if (StoreInst *SI = dyn_cast<StoreInst>(I)) { | 
|  | 145 | // Ignore stores to local memory. | 
|  | 146 | if (PointsToLocalMemory(SI->getPointerOperand())) | 
|  | 147 | continue; | 
|  | 148 | } | 
|  | 149 |  | 
|  | 150 | // Any remaining instructions need to be taken seriously!  Check if they | 
|  | 151 | // read or write memory. | 
|  | 152 | if (I->mayWriteToMemory()) | 
|  | 153 | // Writes memory.  Just give up. | 
|  | 154 | return false; | 
| Duncan Sands | 9759f2e | 2009-05-06 08:42:00 +0000 | [diff] [blame] | 155 |  | 
|  | 156 | if (isa<MallocInst>(I)) | 
|  | 157 | // MallocInst claims not to write memory!  PR3754. | 
|  | 158 | return false; | 
|  | 159 |  | 
| Duncan Sands | 44c8cd9 | 2008-12-31 16:14:43 +0000 | [diff] [blame] | 160 | // If this instruction may read memory, remember that. | 
|  | 161 | ReadsMemory |= I->mayReadFromMemory(); | 
|  | 162 | } | 
|  | 163 | } | 
|  | 164 |  | 
|  | 165 | // Success!  Functions in this SCC do not access memory, or only read memory. | 
|  | 166 | // Give them the appropriate attribute. | 
|  | 167 | bool MadeChange = false; | 
|  | 168 | for (unsigned i = 0, e = SCC.size(); i != e; ++i) { | 
|  | 169 | Function *F = SCC[i]->getFunction(); | 
|  | 170 |  | 
|  | 171 | if (F->doesNotAccessMemory()) | 
|  | 172 | // Already perfect! | 
|  | 173 | continue; | 
|  | 174 |  | 
|  | 175 | if (F->onlyReadsMemory() && ReadsMemory) | 
|  | 176 | // No change. | 
|  | 177 | continue; | 
|  | 178 |  | 
|  | 179 | MadeChange = true; | 
|  | 180 |  | 
|  | 181 | // Clear out any existing attributes. | 
|  | 182 | F->removeAttribute(~0, Attribute::ReadOnly | Attribute::ReadNone); | 
|  | 183 |  | 
|  | 184 | // Add in the new attribute. | 
|  | 185 | F->addAttribute(~0, ReadsMemory? Attribute::ReadOnly : Attribute::ReadNone); | 
|  | 186 |  | 
|  | 187 | if (ReadsMemory) | 
| Duncan Sands | cefc860 | 2009-01-02 11:46:24 +0000 | [diff] [blame] | 188 | ++NumReadOnly; | 
| Duncan Sands | 44c8cd9 | 2008-12-31 16:14:43 +0000 | [diff] [blame] | 189 | else | 
| Duncan Sands | cefc860 | 2009-01-02 11:46:24 +0000 | [diff] [blame] | 190 | ++NumReadNone; | 
| Duncan Sands | 44c8cd9 | 2008-12-31 16:14:43 +0000 | [diff] [blame] | 191 | } | 
|  | 192 |  | 
|  | 193 | return MadeChange; | 
|  | 194 | } | 
|  | 195 |  | 
| Duncan Sands | 44c8cd9 | 2008-12-31 16:14:43 +0000 | [diff] [blame] | 196 | /// AddNoCaptureAttrs - Deduce nocapture attributes for the SCC. | 
|  | 197 | bool FunctionAttrs::AddNoCaptureAttrs(const std::vector<CallGraphNode *> &SCC) { | 
|  | 198 | bool Changed = false; | 
|  | 199 |  | 
|  | 200 | // Check each function in turn, determining which pointer arguments are not | 
|  | 201 | // captured. | 
|  | 202 | for (unsigned i = 0, e = SCC.size(); i != e; ++i) { | 
|  | 203 | Function *F = SCC[i]->getFunction(); | 
|  | 204 |  | 
|  | 205 | if (F == 0) | 
|  | 206 | // External node - skip it; | 
|  | 207 | continue; | 
|  | 208 |  | 
|  | 209 | // Definitions with weak linkage may be overridden at linktime with | 
|  | 210 | // something that writes memory, so treat them like declarations. | 
|  | 211 | if (F->isDeclaration() || F->mayBeOverridden()) | 
|  | 212 | continue; | 
|  | 213 |  | 
|  | 214 | for (Function::arg_iterator A = F->arg_begin(), E = F->arg_end(); A!=E; ++A) | 
| Duncan Sands | df128eb | 2008-12-31 18:08:59 +0000 | [diff] [blame] | 215 | if (isa<PointerType>(A->getType()) && !A->hasNoCaptureAttr() && | 
| Duncan Sands | e0aa0d6 | 2009-01-18 12:19:30 +0000 | [diff] [blame] | 216 | !PointerMayBeCaptured(A, true)) { | 
| Duncan Sands | 44c8cd9 | 2008-12-31 16:14:43 +0000 | [diff] [blame] | 217 | A->addAttr(Attribute::NoCapture); | 
| Nick Lewycky | 7e82055 | 2009-01-02 03:46:56 +0000 | [diff] [blame] | 218 | ++NumNoCapture; | 
| Duncan Sands | 44c8cd9 | 2008-12-31 16:14:43 +0000 | [diff] [blame] | 219 | Changed = true; | 
|  | 220 | } | 
|  | 221 | } | 
|  | 222 |  | 
|  | 223 | return Changed; | 
|  | 224 | } | 
|  | 225 |  | 
| Nick Lewycky | fbed86a | 2009-03-08 06:20:47 +0000 | [diff] [blame] | 226 | /// IsFunctionMallocLike - A function is malloc-like if it returns either null | 
| Nick Lewycky | 9ec96d1 | 2009-03-08 17:08:09 +0000 | [diff] [blame] | 227 | /// or a pointer that doesn't alias any other pointer visible to the caller. | 
| Nick Lewycky | fbed86a | 2009-03-08 06:20:47 +0000 | [diff] [blame] | 228 | bool FunctionAttrs::IsFunctionMallocLike(Function *F, | 
|  | 229 | SmallPtrSet<CallGraphNode*, 8> &SCCNodes) const { | 
|  | 230 | CallGraph &CG = getAnalysis<CallGraph>(); | 
|  | 231 |  | 
|  | 232 | UniqueVector<Value *> FlowsToReturn; | 
|  | 233 | for (Function::iterator I = F->begin(), E = F->end(); I != E; ++I) | 
|  | 234 | if (ReturnInst *Ret = dyn_cast<ReturnInst>(I->getTerminator())) | 
|  | 235 | FlowsToReturn.insert(Ret->getReturnValue()); | 
|  | 236 |  | 
|  | 237 | for (unsigned i = 0; i != FlowsToReturn.size(); ++i) { | 
|  | 238 | Value *RetVal = FlowsToReturn[i+1];   // UniqueVector[0] is reserved. | 
|  | 239 |  | 
|  | 240 | if (Constant *C = dyn_cast<Constant>(RetVal)) { | 
|  | 241 | if (!C->isNullValue() && !isa<UndefValue>(C)) | 
|  | 242 | return false; | 
|  | 243 |  | 
|  | 244 | continue; | 
|  | 245 | } | 
|  | 246 |  | 
|  | 247 | if (isa<Argument>(RetVal)) | 
|  | 248 | return false; | 
|  | 249 |  | 
|  | 250 | if (Instruction *RVI = dyn_cast<Instruction>(RetVal)) | 
|  | 251 | switch (RVI->getOpcode()) { | 
|  | 252 | // Extend the analysis by looking upwards. | 
|  | 253 | case Instruction::GetElementPtr: | 
|  | 254 | case Instruction::BitCast: | 
|  | 255 | FlowsToReturn.insert(RVI->getOperand(0)); | 
|  | 256 | continue; | 
|  | 257 | case Instruction::Select: { | 
|  | 258 | SelectInst *SI = cast<SelectInst>(RVI); | 
|  | 259 | FlowsToReturn.insert(SI->getTrueValue()); | 
|  | 260 | FlowsToReturn.insert(SI->getFalseValue()); | 
|  | 261 | } continue; | 
|  | 262 | case Instruction::PHI: { | 
|  | 263 | PHINode *PN = cast<PHINode>(RVI); | 
|  | 264 | for (int i = 0, e = PN->getNumIncomingValues(); i != e; ++i) | 
|  | 265 | FlowsToReturn.insert(PN->getIncomingValue(i)); | 
|  | 266 | } continue; | 
|  | 267 |  | 
|  | 268 | // Check whether the pointer came from an allocation. | 
|  | 269 | case Instruction::Alloca: | 
|  | 270 | case Instruction::Malloc: | 
|  | 271 | break; | 
|  | 272 | case Instruction::Call: | 
|  | 273 | case Instruction::Invoke: { | 
|  | 274 | CallSite CS(RVI); | 
|  | 275 | if (CS.paramHasAttr(0, Attribute::NoAlias)) | 
|  | 276 | break; | 
|  | 277 | if (CS.getCalledFunction() && | 
|  | 278 | SCCNodes.count(CG[CS.getCalledFunction()])) | 
|  | 279 | break; | 
|  | 280 | } // fall-through | 
|  | 281 | default: | 
|  | 282 | return false;  // Did not come from an allocation. | 
|  | 283 | } | 
|  | 284 |  | 
|  | 285 | if (PointerMayBeCaptured(RetVal, false)) | 
|  | 286 | return false; | 
|  | 287 | } | 
|  | 288 |  | 
|  | 289 | return true; | 
|  | 290 | } | 
|  | 291 |  | 
|  | 292 | /// AddNoAliasAttrs - Deduce noalias attributes for the SCC. | 
|  | 293 | bool FunctionAttrs::AddNoAliasAttrs(const std::vector<CallGraphNode *> &SCC) { | 
|  | 294 | SmallPtrSet<CallGraphNode*, 8> SCCNodes; | 
|  | 295 |  | 
|  | 296 | // Fill SCCNodes with the elements of the SCC.  Used for quickly | 
|  | 297 | // looking up whether a given CallGraphNode is in this SCC. | 
|  | 298 | for (unsigned i = 0, e = SCC.size(); i != e; ++i) | 
|  | 299 | SCCNodes.insert(SCC[i]); | 
|  | 300 |  | 
| Nick Lewycky | 9ec96d1 | 2009-03-08 17:08:09 +0000 | [diff] [blame] | 301 | // Check each function in turn, determining which functions return noalias | 
|  | 302 | // pointers. | 
| Nick Lewycky | fbed86a | 2009-03-08 06:20:47 +0000 | [diff] [blame] | 303 | for (unsigned i = 0, e = SCC.size(); i != e; ++i) { | 
|  | 304 | Function *F = SCC[i]->getFunction(); | 
|  | 305 |  | 
|  | 306 | if (F == 0) | 
|  | 307 | // External node - skip it; | 
|  | 308 | return false; | 
|  | 309 |  | 
|  | 310 | // Already noalias. | 
|  | 311 | if (F->doesNotAlias(0)) | 
|  | 312 | continue; | 
|  | 313 |  | 
|  | 314 | // Definitions with weak linkage may be overridden at linktime, so | 
|  | 315 | // treat them like declarations. | 
|  | 316 | if (F->isDeclaration() || F->mayBeOverridden()) | 
|  | 317 | return false; | 
|  | 318 |  | 
|  | 319 | // We annotate noalias return values, which are only applicable to | 
|  | 320 | // pointer types. | 
|  | 321 | if (!isa<PointerType>(F->getReturnType())) | 
|  | 322 | continue; | 
|  | 323 |  | 
|  | 324 | if (!IsFunctionMallocLike(F, SCCNodes)) | 
|  | 325 | return false; | 
|  | 326 | } | 
|  | 327 |  | 
|  | 328 | bool MadeChange = false; | 
|  | 329 | for (unsigned i = 0, e = SCC.size(); i != e; ++i) { | 
|  | 330 | Function *F = SCC[i]->getFunction(); | 
|  | 331 | if (F->doesNotAlias(0) || !isa<PointerType>(F->getReturnType())) | 
|  | 332 | continue; | 
|  | 333 |  | 
|  | 334 | F->setDoesNotAlias(0); | 
|  | 335 | ++NumNoAlias; | 
|  | 336 | MadeChange = true; | 
|  | 337 | } | 
|  | 338 |  | 
|  | 339 | return MadeChange; | 
|  | 340 | } | 
|  | 341 |  | 
| Duncan Sands | 44c8cd9 | 2008-12-31 16:14:43 +0000 | [diff] [blame] | 342 | bool FunctionAttrs::runOnSCC(const std::vector<CallGraphNode *> &SCC) { | 
|  | 343 | bool Changed = AddReadAttrs(SCC); | 
|  | 344 | Changed |= AddNoCaptureAttrs(SCC); | 
| Nick Lewycky | fbed86a | 2009-03-08 06:20:47 +0000 | [diff] [blame] | 345 | Changed |= AddNoAliasAttrs(SCC); | 
| Duncan Sands | 44c8cd9 | 2008-12-31 16:14:43 +0000 | [diff] [blame] | 346 | return Changed; | 
|  | 347 | } |