1 //===- ScopedNoAliasAA.cpp - Scoped No-Alias Alias Analysis ---------------===// 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 defines the ScopedNoAlias alias-analysis pass, which implements 11 // metadata-based scoped no-alias support. 12 // 13 // Alias-analysis scopes are defined by an id (which can be a string or some 14 // other metadata node), a domain node, and an optional descriptive string. 15 // A domain is defined by an id (which can be a string or some other metadata 16 // node), and an optional descriptive string. 17 // 18 // !dom0 = metadata !{ metadata !"domain of foo()" } 19 // !scope1 = metadata !{ metadata !scope1, metadata !dom0, metadata !"scope 1" } 20 // !scope2 = metadata !{ metadata !scope2, metadata !dom0, metadata !"scope 2" } 21 // 22 // Loads and stores can be tagged with an alias-analysis scope, and also, with 23 // a noalias tag for a specific scope: 24 // 25 // ... = load %ptr1, !alias.scope !{ !scope1 } 26 // ... = load %ptr2, !alias.scope !{ !scope1, !scope2 }, !noalias !{ !scope1 } 27 // 28 // When evaluating an aliasing query, if one of the instructions is associated 29 // has a set of noalias scopes in some domain that is superset of the alias 30 // scopes in that domain of some other instruction, then the two memory 31 // accesses are assumed not to alias. 32 // 33 //===----------------------------------------------------------------------===// 34 35 #include "llvm/ADT/SmallPtrSet.h" 36 #include "llvm/Analysis/Passes.h" 37 #include "llvm/Analysis/AliasAnalysis.h" 38 #include "llvm/IR/Constants.h" 39 #include "llvm/IR/LLVMContext.h" 40 #include "llvm/IR/Metadata.h" 41 #include "llvm/IR/Module.h" 42 #include "llvm/Pass.h" 43 #include "llvm/Support/CommandLine.h" 44 using namespace llvm; 45 46 // A handy option for disabling scoped no-alias functionality. The same effect 47 // can also be achieved by stripping the associated metadata tags from IR, but 48 // this option is sometimes more convenient. 49 static cl::opt<bool> 50 EnableScopedNoAlias("enable-scoped-noalias", cl::init(true)); 51 52 namespace { 53 /// AliasScopeNode - This is a simple wrapper around an MDNode which provides 54 /// a higher-level interface by hiding the details of how alias analysis 55 /// information is encoded in its operands. 56 class AliasScopeNode { 57 const MDNode *Node; 58 59 public: 60 AliasScopeNode() : Node(0) {} 61 explicit AliasScopeNode(const MDNode *N) : Node(N) {} 62 63 /// getNode - Get the MDNode for this AliasScopeNode. 64 const MDNode *getNode() const { return Node; } 65 66 /// getDomain - Get the MDNode for this AliasScopeNode's domain. 67 const MDNode *getDomain() const { 68 if (Node->getNumOperands() < 2) 69 return nullptr; 70 return dyn_cast_or_null<MDNode>(Node->getOperand(1)); 71 } 72 }; 73 74 /// ScopedNoAliasAA - This is a simple alias analysis 75 /// implementation that uses scoped-noalias metadata to answer queries. 76 class ScopedNoAliasAA : public ImmutablePass, public AliasAnalysis { 77 public: 78 static char ID; // Class identification, replacement for typeinfo 79 ScopedNoAliasAA() : ImmutablePass(ID) { 80 initializeScopedNoAliasAAPass(*PassRegistry::getPassRegistry()); 81 } 82 83 virtual void initializePass() { 84 InitializeAliasAnalysis(this); 85 } 86 87 /// getAdjustedAnalysisPointer - This method is used when a pass implements 88 /// an analysis interface through multiple inheritance. If needed, it 89 /// should override this to adjust the this pointer as needed for the 90 /// specified pass info. 91 virtual void *getAdjustedAnalysisPointer(const void *PI) { 92 if (PI == &AliasAnalysis::ID) 93 return (AliasAnalysis*)this; 94 return this; 95 } 96 97 protected: 98 bool mayAliasInScopes(const MDNode *Scopes, const MDNode *NoAlias) const; 99 void collectMDInDomain(const MDNode *List, const MDNode *Domain, 100 SmallPtrSetImpl<const MDNode *> &Nodes) const; 101 102 private: 103 virtual void getAnalysisUsage(AnalysisUsage &AU) const; 104 virtual AliasResult alias(const Location &LocA, const Location &LocB); 105 virtual bool pointsToConstantMemory(const Location &Loc, bool OrLocal); 106 virtual ModRefBehavior getModRefBehavior(ImmutableCallSite CS); 107 virtual ModRefBehavior getModRefBehavior(const Function *F); 108 virtual ModRefResult getModRefInfo(ImmutableCallSite CS, 109 const Location &Loc); 110 virtual ModRefResult getModRefInfo(ImmutableCallSite CS1, 111 ImmutableCallSite CS2); 112 }; 113 } // End of anonymous namespace 114 115 // Register this pass... 116 char ScopedNoAliasAA::ID = 0; 117 INITIALIZE_AG_PASS(ScopedNoAliasAA, AliasAnalysis, "scoped-noalias", 118 "Scoped NoAlias Alias Analysis", false, true, false) 119 120 ImmutablePass *llvm::createScopedNoAliasAAPass() { 121 return new ScopedNoAliasAA(); 122 } 123 124 void 125 ScopedNoAliasAA::getAnalysisUsage(AnalysisUsage &AU) const { 126 AU.setPreservesAll(); 127 AliasAnalysis::getAnalysisUsage(AU); 128 } 129 130 void 131 ScopedNoAliasAA::collectMDInDomain(const MDNode *List, const MDNode *Domain, 132 SmallPtrSetImpl<const MDNode *> &Nodes) const { 133 for (unsigned i = 0, ie = List->getNumOperands(); i != ie; ++i) 134 if (const MDNode *MD = dyn_cast<MDNode>(List->getOperand(i))) 135 if (AliasScopeNode(MD).getDomain() == Domain) 136 Nodes.insert(MD); 137 } 138 139 bool 140 ScopedNoAliasAA::mayAliasInScopes(const MDNode *Scopes, 141 const MDNode *NoAlias) const { 142 if (!Scopes || !NoAlias) 143 return true; 144 145 // Collect the set of scope domains relevant to the noalias scopes. 146 SmallPtrSet<const MDNode *, 16> Domains; 147 for (unsigned i = 0, ie = NoAlias->getNumOperands(); i != ie; ++i) 148 if (const MDNode *NAMD = dyn_cast<MDNode>(NoAlias->getOperand(i))) 149 if (const MDNode *Domain = AliasScopeNode(NAMD).getDomain()) 150 Domains.insert(Domain); 151 152 // We alias unless, for some domain, the set of noalias scopes in that domain 153 // is a superset of the set of alias scopes in that domain. 154 for (const MDNode *Domain : Domains) { 155 SmallPtrSet<const MDNode *, 16> NANodes, ScopeNodes; 156 collectMDInDomain(NoAlias, Domain, NANodes); 157 collectMDInDomain(Scopes, Domain, ScopeNodes); 158 if (!ScopeNodes.size()) 159 continue; 160 161 // To not alias, all of the nodes in ScopeNodes must be in NANodes. 162 bool FoundAll = true; 163 for (const MDNode *SMD : ScopeNodes) 164 if (!NANodes.count(SMD)) { 165 FoundAll = false; 166 break; 167 } 168 169 if (FoundAll) 170 return false; 171 } 172 173 return true; 174 } 175 176 AliasAnalysis::AliasResult 177 ScopedNoAliasAA::alias(const Location &LocA, const Location &LocB) { 178 if (!EnableScopedNoAlias) 179 return AliasAnalysis::alias(LocA, LocB); 180 181 // Get the attached MDNodes. 182 const MDNode *AScopes = LocA.AATags.Scope, 183 *BScopes = LocB.AATags.Scope; 184 185 const MDNode *ANoAlias = LocA.AATags.NoAlias, 186 *BNoAlias = LocB.AATags.NoAlias; 187 188 if (!mayAliasInScopes(AScopes, BNoAlias)) 189 return NoAlias; 190 191 if (!mayAliasInScopes(BScopes, ANoAlias)) 192 return NoAlias; 193 194 // If they may alias, chain to the next AliasAnalysis. 195 return AliasAnalysis::alias(LocA, LocB); 196 } 197 198 bool ScopedNoAliasAA::pointsToConstantMemory(const Location &Loc, 199 bool OrLocal) { 200 return AliasAnalysis::pointsToConstantMemory(Loc, OrLocal); 201 } 202 203 AliasAnalysis::ModRefBehavior 204 ScopedNoAliasAA::getModRefBehavior(ImmutableCallSite CS) { 205 return AliasAnalysis::getModRefBehavior(CS); 206 } 207 208 AliasAnalysis::ModRefBehavior 209 ScopedNoAliasAA::getModRefBehavior(const Function *F) { 210 return AliasAnalysis::getModRefBehavior(F); 211 } 212 213 AliasAnalysis::ModRefResult 214 ScopedNoAliasAA::getModRefInfo(ImmutableCallSite CS, const Location &Loc) { 215 if (!EnableScopedNoAlias) 216 return AliasAnalysis::getModRefInfo(CS, Loc); 217 218 if (!mayAliasInScopes(Loc.AATags.Scope, 219 CS.getInstruction()->getMetadata(LLVMContext::MD_noalias))) 220 return NoModRef; 221 222 if (!mayAliasInScopes( 223 CS.getInstruction()->getMetadata(LLVMContext::MD_alias_scope), 224 Loc.AATags.NoAlias)) 225 return NoModRef; 226 227 return AliasAnalysis::getModRefInfo(CS, Loc); 228 } 229 230 AliasAnalysis::ModRefResult 231 ScopedNoAliasAA::getModRefInfo(ImmutableCallSite CS1, ImmutableCallSite CS2) { 232 if (!EnableScopedNoAlias) 233 return AliasAnalysis::getModRefInfo(CS1, CS2); 234 235 if (!mayAliasInScopes( 236 CS1.getInstruction()->getMetadata(LLVMContext::MD_alias_scope), 237 CS2.getInstruction()->getMetadata(LLVMContext::MD_noalias))) 238 return NoModRef; 239 240 if (!mayAliasInScopes( 241 CS2.getInstruction()->getMetadata(LLVMContext::MD_alias_scope), 242 CS1.getInstruction()->getMetadata(LLVMContext::MD_noalias))) 243 return NoModRef; 244 245 return AliasAnalysis::getModRefInfo(CS1, CS2); 246 } 247 248