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 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. 18 // 19 //===----------------------------------------------------------------------===// 20 21 #define DEBUG_TYPE "functionattrs" 22 #include "llvm/Transforms/IPO.h" 23 #include "llvm/ADT/SCCIterator.h" 24 #include "llvm/ADT/SetVector.h" 25 #include "llvm/ADT/SmallSet.h" 26 #include "llvm/ADT/Statistic.h" 27 #include "llvm/Analysis/AliasAnalysis.h" 28 #include "llvm/Analysis/CallGraph.h" 29 #include "llvm/Analysis/CallGraphSCCPass.h" 30 #include "llvm/Analysis/CaptureTracking.h" 31 #include "llvm/IR/GlobalVariable.h" 32 #include "llvm/IR/IntrinsicInst.h" 33 #include "llvm/IR/LLVMContext.h" 34 #include "llvm/Support/InstIterator.h" 35 using namespace llvm; 36 37 STATISTIC(NumReadNone, "Number of functions marked readnone"); 38 STATISTIC(NumReadOnly, "Number of functions marked readonly"); 39 STATISTIC(NumNoCapture, "Number of arguments marked nocapture"); 40 STATISTIC(NumNoAlias, "Number of function returns marked noalias"); 41 42 namespace { 43 struct FunctionAttrs : public CallGraphSCCPass { 44 static char ID; // Pass identification, replacement for typeid 45 FunctionAttrs() : CallGraphSCCPass(ID), AA(0) { 46 initializeFunctionAttrsPass(*PassRegistry::getPassRegistry()); 47 } 48 49 // runOnSCC - Analyze the SCC, performing the transformation if possible. 50 bool runOnSCC(CallGraphSCC &SCC); 51 52 // AddReadAttrs - Deduce readonly/readnone attributes for the SCC. 53 bool AddReadAttrs(const CallGraphSCC &SCC); 54 55 // AddNoCaptureAttrs - Deduce nocapture attributes for the SCC. 56 bool AddNoCaptureAttrs(const CallGraphSCC &SCC); 57 58 // IsFunctionMallocLike - Does this function allocate new memory? 59 bool IsFunctionMallocLike(Function *F, 60 SmallPtrSet<Function*, 8> &) const; 61 62 // AddNoAliasAttrs - Deduce noalias attributes for the SCC. 63 bool AddNoAliasAttrs(const CallGraphSCC &SCC); 64 65 virtual void getAnalysisUsage(AnalysisUsage &AU) const { 66 AU.setPreservesCFG(); 67 AU.addRequired<AliasAnalysis>(); 68 CallGraphSCCPass::getAnalysisUsage(AU); 69 } 70 71 private: 72 AliasAnalysis *AA; 73 }; 74 } 75 76 char FunctionAttrs::ID = 0; 77 INITIALIZE_PASS_BEGIN(FunctionAttrs, "functionattrs", 78 "Deduce function attributes", false, false) 79 INITIALIZE_AG_DEPENDENCY(CallGraph) 80 INITIALIZE_PASS_END(FunctionAttrs, "functionattrs", 81 "Deduce function attributes", false, false) 82 83 Pass *llvm::createFunctionAttrsPass() { return new FunctionAttrs(); } 84 85 86 /// AddReadAttrs - Deduce readonly/readnone attributes for the SCC. 87 bool FunctionAttrs::AddReadAttrs(const CallGraphSCC &SCC) { 88 SmallPtrSet<Function*, 8> SCCNodes; 89 90 // Fill SCCNodes with the elements of the SCC. Used for quickly 91 // looking up whether a given CallGraphNode is in this SCC. 92 for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I) 93 SCCNodes.insert((*I)->getFunction()); 94 95 // Check if any of the functions in the SCC read or write memory. If they 96 // write memory then they can't be marked readnone or readonly. 97 bool ReadsMemory = false; 98 for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I) { 99 Function *F = (*I)->getFunction(); 100 101 if (F == 0) 102 // External node - may write memory. Just give up. 103 return false; 104 105 AliasAnalysis::ModRefBehavior MRB = AA->getModRefBehavior(F); 106 if (MRB == AliasAnalysis::DoesNotAccessMemory) 107 // Already perfect! 108 continue; 109 110 // Definitions with weak linkage may be overridden at linktime with 111 // something that writes memory, so treat them like declarations. 112 if (F->isDeclaration() || F->mayBeOverridden()) { 113 if (!AliasAnalysis::onlyReadsMemory(MRB)) 114 // May write memory. Just give up. 115 return false; 116 117 ReadsMemory = true; 118 continue; 119 } 120 121 // Scan the function body for instructions that may read or write memory. 122 for (inst_iterator II = inst_begin(F), E = inst_end(F); II != E; ++II) { 123 Instruction *I = &*II; 124 125 // Some instructions can be ignored even if they read or write memory. 126 // Detect these now, skipping to the next instruction if one is found. 127 CallSite CS(cast<Value>(I)); 128 if (CS) { 129 // Ignore calls to functions in the same SCC. 130 if (CS.getCalledFunction() && SCCNodes.count(CS.getCalledFunction())) 131 continue; 132 AliasAnalysis::ModRefBehavior MRB = AA->getModRefBehavior(CS); 133 // If the call doesn't access arbitrary memory, we may be able to 134 // figure out something. 135 if (AliasAnalysis::onlyAccessesArgPointees(MRB)) { 136 // If the call does access argument pointees, check each argument. 137 if (AliasAnalysis::doesAccessArgPointees(MRB)) 138 // Check whether all pointer arguments point to local memory, and 139 // ignore calls that only access local memory. 140 for (CallSite::arg_iterator CI = CS.arg_begin(), CE = CS.arg_end(); 141 CI != CE; ++CI) { 142 Value *Arg = *CI; 143 if (Arg->getType()->isPointerTy()) { 144 AliasAnalysis::Location Loc(Arg, 145 AliasAnalysis::UnknownSize, 146 I->getMetadata(LLVMContext::MD_tbaa)); 147 if (!AA->pointsToConstantMemory(Loc, /*OrLocal=*/true)) { 148 if (MRB & AliasAnalysis::Mod) 149 // Writes non-local memory. Give up. 150 return false; 151 if (MRB & AliasAnalysis::Ref) 152 // Ok, it reads non-local memory. 153 ReadsMemory = true; 154 } 155 } 156 } 157 continue; 158 } 159 // The call could access any memory. If that includes writes, give up. 160 if (MRB & AliasAnalysis::Mod) 161 return false; 162 // If it reads, note it. 163 if (MRB & AliasAnalysis::Ref) 164 ReadsMemory = true; 165 continue; 166 } else if (LoadInst *LI = dyn_cast<LoadInst>(I)) { 167 // Ignore non-volatile loads from local memory. (Atomic is okay here.) 168 if (!LI->isVolatile()) { 169 AliasAnalysis::Location Loc = AA->getLocation(LI); 170 if (AA->pointsToConstantMemory(Loc, /*OrLocal=*/true)) 171 continue; 172 } 173 } else if (StoreInst *SI = dyn_cast<StoreInst>(I)) { 174 // Ignore non-volatile stores to local memory. (Atomic is okay here.) 175 if (!SI->isVolatile()) { 176 AliasAnalysis::Location Loc = AA->getLocation(SI); 177 if (AA->pointsToConstantMemory(Loc, /*OrLocal=*/true)) 178 continue; 179 } 180 } else if (VAArgInst *VI = dyn_cast<VAArgInst>(I)) { 181 // Ignore vaargs on local memory. 182 AliasAnalysis::Location Loc = AA->getLocation(VI); 183 if (AA->pointsToConstantMemory(Loc, /*OrLocal=*/true)) 184 continue; 185 } 186 187 // Any remaining instructions need to be taken seriously! Check if they 188 // read or write memory. 189 if (I->mayWriteToMemory()) 190 // Writes memory. Just give up. 191 return false; 192 193 // If this instruction may read memory, remember that. 194 ReadsMemory |= I->mayReadFromMemory(); 195 } 196 } 197 198 // Success! Functions in this SCC do not access memory, or only read memory. 199 // Give them the appropriate attribute. 200 bool MadeChange = false; 201 for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I) { 202 Function *F = (*I)->getFunction(); 203 204 if (F->doesNotAccessMemory()) 205 // Already perfect! 206 continue; 207 208 if (F->onlyReadsMemory() && ReadsMemory) 209 // No change. 210 continue; 211 212 MadeChange = true; 213 214 // Clear out any existing attributes. 215 AttrBuilder B; 216 B.addAttribute(Attribute::ReadOnly) 217 .addAttribute(Attribute::ReadNone); 218 F->removeAttributes(AttributeSet::FunctionIndex, 219 AttributeSet::get(F->getContext(), 220 AttributeSet::FunctionIndex, B)); 221 222 // Add in the new attribute. 223 F->addAttribute(AttributeSet::FunctionIndex, 224 ReadsMemory ? Attribute::ReadOnly : Attribute::ReadNone); 225 226 if (ReadsMemory) 227 ++NumReadOnly; 228 else 229 ++NumReadNone; 230 } 231 232 return MadeChange; 233 } 234 235 namespace { 236 // For a given pointer Argument, this retains a list of Arguments of functions 237 // in the same SCC that the pointer data flows into. We use this to build an 238 // SCC of the arguments. 239 struct ArgumentGraphNode { 240 Argument *Definition; 241 SmallVector<ArgumentGraphNode*, 4> Uses; 242 }; 243 244 class ArgumentGraph { 245 // We store pointers to ArgumentGraphNode objects, so it's important that 246 // that they not move around upon insert. 247 typedef std::map<Argument*, ArgumentGraphNode> ArgumentMapTy; 248 249 ArgumentMapTy ArgumentMap; 250 251 // There is no root node for the argument graph, in fact: 252 // void f(int *x, int *y) { if (...) f(x, y); } 253 // is an example where the graph is disconnected. The SCCIterator requires a 254 // single entry point, so we maintain a fake ("synthetic") root node that 255 // uses every node. Because the graph is directed and nothing points into 256 // the root, it will not participate in any SCCs (except for its own). 257 ArgumentGraphNode SyntheticRoot; 258 259 public: 260 ArgumentGraph() { SyntheticRoot.Definition = 0; } 261 262 typedef SmallVectorImpl<ArgumentGraphNode*>::iterator iterator; 263 264 iterator begin() { return SyntheticRoot.Uses.begin(); } 265 iterator end() { return SyntheticRoot.Uses.end(); } 266 ArgumentGraphNode *getEntryNode() { return &SyntheticRoot; } 267 268 ArgumentGraphNode *operator[](Argument *A) { 269 ArgumentGraphNode &Node = ArgumentMap[A]; 270 Node.Definition = A; 271 SyntheticRoot.Uses.push_back(&Node); 272 return &Node; 273 } 274 }; 275 276 // This tracker checks whether callees are in the SCC, and if so it does not 277 // consider that a capture, instead adding it to the "Uses" list and 278 // continuing with the analysis. 279 struct ArgumentUsesTracker : public CaptureTracker { 280 ArgumentUsesTracker(const SmallPtrSet<Function*, 8> &SCCNodes) 281 : Captured(false), SCCNodes(SCCNodes) {} 282 283 void tooManyUses() { Captured = true; } 284 285 bool captured(Use *U) { 286 CallSite CS(U->getUser()); 287 if (!CS.getInstruction()) { Captured = true; return true; } 288 289 Function *F = CS.getCalledFunction(); 290 if (!F || !SCCNodes.count(F)) { Captured = true; return true; } 291 292 Function::arg_iterator AI = F->arg_begin(), AE = F->arg_end(); 293 for (CallSite::arg_iterator PI = CS.arg_begin(), PE = CS.arg_end(); 294 PI != PE; ++PI, ++AI) { 295 if (AI == AE) { 296 assert(F->isVarArg() && "More params than args in non-varargs call"); 297 Captured = true; 298 return true; 299 } 300 if (PI == U) { 301 Uses.push_back(AI); 302 break; 303 } 304 } 305 assert(!Uses.empty() && "Capturing call-site captured nothing?"); 306 return false; 307 } 308 309 bool Captured; // True only if certainly captured (used outside our SCC). 310 SmallVector<Argument*, 4> Uses; // Uses within our SCC. 311 312 const SmallPtrSet<Function*, 8> &SCCNodes; 313 }; 314 } 315 316 namespace llvm { 317 template<> struct GraphTraits<ArgumentGraphNode*> { 318 typedef ArgumentGraphNode NodeType; 319 typedef SmallVectorImpl<ArgumentGraphNode*>::iterator ChildIteratorType; 320 321 static inline NodeType *getEntryNode(NodeType *A) { return A; } 322 static inline ChildIteratorType child_begin(NodeType *N) { 323 return N->Uses.begin(); 324 } 325 static inline ChildIteratorType child_end(NodeType *N) { 326 return N->Uses.end(); 327 } 328 }; 329 template<> struct GraphTraits<ArgumentGraph*> 330 : public GraphTraits<ArgumentGraphNode*> { 331 static NodeType *getEntryNode(ArgumentGraph *AG) { 332 return AG->getEntryNode(); 333 } 334 static ChildIteratorType nodes_begin(ArgumentGraph *AG) { 335 return AG->begin(); 336 } 337 static ChildIteratorType nodes_end(ArgumentGraph *AG) { 338 return AG->end(); 339 } 340 }; 341 } 342 343 /// AddNoCaptureAttrs - Deduce nocapture attributes for the SCC. 344 bool FunctionAttrs::AddNoCaptureAttrs(const CallGraphSCC &SCC) { 345 bool Changed = false; 346 347 SmallPtrSet<Function*, 8> SCCNodes; 348 349 // Fill SCCNodes with the elements of the SCC. Used for quickly 350 // looking up whether a given CallGraphNode is in this SCC. 351 for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I) { 352 Function *F = (*I)->getFunction(); 353 if (F && !F->isDeclaration() && !F->mayBeOverridden()) 354 SCCNodes.insert(F); 355 } 356 357 ArgumentGraph AG; 358 359 AttrBuilder B; 360 B.addAttribute(Attribute::NoCapture); 361 362 // Check each function in turn, determining which pointer arguments are not 363 // captured. 364 for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I) { 365 Function *F = (*I)->getFunction(); 366 367 if (F == 0) 368 // External node - only a problem for arguments that we pass to it. 369 continue; 370 371 // Definitions with weak linkage may be overridden at linktime with 372 // something that captures pointers, so treat them like declarations. 373 if (F->isDeclaration() || F->mayBeOverridden()) 374 continue; 375 376 // Functions that are readonly (or readnone) and nounwind and don't return 377 // a value can't capture arguments. Don't analyze them. 378 if (F->onlyReadsMemory() && F->doesNotThrow() && 379 F->getReturnType()->isVoidTy()) { 380 for (Function::arg_iterator A = F->arg_begin(), E = F->arg_end(); 381 A != E; ++A) { 382 if (A->getType()->isPointerTy() && !A->hasNoCaptureAttr()) { 383 A->addAttr(AttributeSet::get(F->getContext(), A->getArgNo() + 1, B)); 384 ++NumNoCapture; 385 Changed = true; 386 } 387 } 388 continue; 389 } 390 391 for (Function::arg_iterator A = F->arg_begin(), E = F->arg_end(); A!=E; ++A) 392 if (A->getType()->isPointerTy() && !A->hasNoCaptureAttr()) { 393 ArgumentUsesTracker Tracker(SCCNodes); 394 PointerMayBeCaptured(A, &Tracker); 395 if (!Tracker.Captured) { 396 if (Tracker.Uses.empty()) { 397 // If it's trivially not captured, mark it nocapture now. 398 A->addAttr(AttributeSet::get(F->getContext(), A->getArgNo()+1, B)); 399 ++NumNoCapture; 400 Changed = true; 401 } else { 402 // If it's not trivially captured and not trivially not captured, 403 // then it must be calling into another function in our SCC. Save 404 // its particulars for Argument-SCC analysis later. 405 ArgumentGraphNode *Node = AG[A]; 406 for (SmallVectorImpl<Argument*>::iterator UI = Tracker.Uses.begin(), 407 UE = Tracker.Uses.end(); UI != UE; ++UI) 408 Node->Uses.push_back(AG[*UI]); 409 } 410 } 411 // Otherwise, it's captured. Don't bother doing SCC analysis on it. 412 } 413 } 414 415 // The graph we've collected is partial because we stopped scanning for 416 // argument uses once we solved the argument trivially. These partial nodes 417 // show up as ArgumentGraphNode objects with an empty Uses list, and for 418 // these nodes the final decision about whether they capture has already been 419 // made. If the definition doesn't have a 'nocapture' attribute by now, it 420 // captures. 421 422 for (scc_iterator<ArgumentGraph*> I = scc_begin(&AG), E = scc_end(&AG); 423 I != E; ++I) { 424 std::vector<ArgumentGraphNode*> &ArgumentSCC = *I; 425 if (ArgumentSCC.size() == 1) { 426 if (!ArgumentSCC[0]->Definition) continue; // synthetic root node 427 428 // eg. "void f(int* x) { if (...) f(x); }" 429 if (ArgumentSCC[0]->Uses.size() == 1 && 430 ArgumentSCC[0]->Uses[0] == ArgumentSCC[0]) { 431 ArgumentSCC[0]-> 432 Definition-> 433 addAttr(AttributeSet::get(ArgumentSCC[0]->Definition->getContext(), 434 ArgumentSCC[0]->Definition->getArgNo() + 1, 435 B)); 436 ++NumNoCapture; 437 Changed = true; 438 } 439 continue; 440 } 441 442 bool SCCCaptured = false; 443 for (std::vector<ArgumentGraphNode*>::iterator I = ArgumentSCC.begin(), 444 E = ArgumentSCC.end(); I != E && !SCCCaptured; ++I) { 445 ArgumentGraphNode *Node = *I; 446 if (Node->Uses.empty()) { 447 if (!Node->Definition->hasNoCaptureAttr()) 448 SCCCaptured = true; 449 } 450 } 451 if (SCCCaptured) continue; 452 453 SmallPtrSet<Argument*, 8> ArgumentSCCNodes; 454 // Fill ArgumentSCCNodes with the elements of the ArgumentSCC. Used for 455 // quickly looking up whether a given Argument is in this ArgumentSCC. 456 for (std::vector<ArgumentGraphNode*>::iterator I = ArgumentSCC.begin(), 457 E = ArgumentSCC.end(); I != E; ++I) { 458 ArgumentSCCNodes.insert((*I)->Definition); 459 } 460 461 for (std::vector<ArgumentGraphNode*>::iterator I = ArgumentSCC.begin(), 462 E = ArgumentSCC.end(); I != E && !SCCCaptured; ++I) { 463 ArgumentGraphNode *N = *I; 464 for (SmallVectorImpl<ArgumentGraphNode*>::iterator UI = N->Uses.begin(), 465 UE = N->Uses.end(); UI != UE; ++UI) { 466 Argument *A = (*UI)->Definition; 467 if (A->hasNoCaptureAttr() || ArgumentSCCNodes.count(A)) 468 continue; 469 SCCCaptured = true; 470 break; 471 } 472 } 473 if (SCCCaptured) continue; 474 475 for (unsigned i = 0, e = ArgumentSCC.size(); i != e; ++i) { 476 Argument *A = ArgumentSCC[i]->Definition; 477 A->addAttr(AttributeSet::get(A->getContext(), A->getArgNo() + 1, B)); 478 ++NumNoCapture; 479 Changed = true; 480 } 481 } 482 483 return Changed; 484 } 485 486 /// IsFunctionMallocLike - A function is malloc-like if it returns either null 487 /// or a pointer that doesn't alias any other pointer visible to the caller. 488 bool FunctionAttrs::IsFunctionMallocLike(Function *F, 489 SmallPtrSet<Function*, 8> &SCCNodes) const { 490 SmallSetVector<Value *, 8> FlowsToReturn; 491 for (Function::iterator I = F->begin(), E = F->end(); I != E; ++I) 492 if (ReturnInst *Ret = dyn_cast<ReturnInst>(I->getTerminator())) 493 FlowsToReturn.insert(Ret->getReturnValue()); 494 495 for (unsigned i = 0; i != FlowsToReturn.size(); ++i) { 496 Value *RetVal = FlowsToReturn[i]; 497 498 if (Constant *C = dyn_cast<Constant>(RetVal)) { 499 if (!C->isNullValue() && !isa<UndefValue>(C)) 500 return false; 501 502 continue; 503 } 504 505 if (isa<Argument>(RetVal)) 506 return false; 507 508 if (Instruction *RVI = dyn_cast<Instruction>(RetVal)) 509 switch (RVI->getOpcode()) { 510 // Extend the analysis by looking upwards. 511 case Instruction::BitCast: 512 case Instruction::GetElementPtr: 513 FlowsToReturn.insert(RVI->getOperand(0)); 514 continue; 515 case Instruction::Select: { 516 SelectInst *SI = cast<SelectInst>(RVI); 517 FlowsToReturn.insert(SI->getTrueValue()); 518 FlowsToReturn.insert(SI->getFalseValue()); 519 continue; 520 } 521 case Instruction::PHI: { 522 PHINode *PN = cast<PHINode>(RVI); 523 for (int i = 0, e = PN->getNumIncomingValues(); i != e; ++i) 524 FlowsToReturn.insert(PN->getIncomingValue(i)); 525 continue; 526 } 527 528 // Check whether the pointer came from an allocation. 529 case Instruction::Alloca: 530 break; 531 case Instruction::Call: 532 case Instruction::Invoke: { 533 CallSite CS(RVI); 534 if (CS.paramHasAttr(0, Attribute::NoAlias)) 535 break; 536 if (CS.getCalledFunction() && 537 SCCNodes.count(CS.getCalledFunction())) 538 break; 539 } // fall-through 540 default: 541 return false; // Did not come from an allocation. 542 } 543 544 if (PointerMayBeCaptured(RetVal, false, /*StoreCaptures=*/false)) 545 return false; 546 } 547 548 return true; 549 } 550 551 /// AddNoAliasAttrs - Deduce noalias attributes for the SCC. 552 bool FunctionAttrs::AddNoAliasAttrs(const CallGraphSCC &SCC) { 553 SmallPtrSet<Function*, 8> SCCNodes; 554 555 // Fill SCCNodes with the elements of the SCC. Used for quickly 556 // looking up whether a given CallGraphNode is in this SCC. 557 for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I) 558 SCCNodes.insert((*I)->getFunction()); 559 560 // Check each function in turn, determining which functions return noalias 561 // pointers. 562 for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I) { 563 Function *F = (*I)->getFunction(); 564 565 if (F == 0) 566 // External node - skip it; 567 return false; 568 569 // Already noalias. 570 if (F->doesNotAlias(0)) 571 continue; 572 573 // Definitions with weak linkage may be overridden at linktime, so 574 // treat them like declarations. 575 if (F->isDeclaration() || F->mayBeOverridden()) 576 return false; 577 578 // We annotate noalias return values, which are only applicable to 579 // pointer types. 580 if (!F->getReturnType()->isPointerTy()) 581 continue; 582 583 if (!IsFunctionMallocLike(F, SCCNodes)) 584 return false; 585 } 586 587 bool MadeChange = false; 588 for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I) { 589 Function *F = (*I)->getFunction(); 590 if (F->doesNotAlias(0) || !F->getReturnType()->isPointerTy()) 591 continue; 592 593 F->setDoesNotAlias(0); 594 ++NumNoAlias; 595 MadeChange = true; 596 } 597 598 return MadeChange; 599 } 600 601 bool FunctionAttrs::runOnSCC(CallGraphSCC &SCC) { 602 AA = &getAnalysis<AliasAnalysis>(); 603 604 bool Changed = AddReadAttrs(SCC); 605 Changed |= AddNoCaptureAttrs(SCC); 606 Changed |= AddNoAliasAttrs(SCC); 607 return Changed; 608 } 609