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 void initializePass() override { InitializeAliasAnalysis(this); } 84 85 /// getAdjustedAnalysisPointer - This method is used when a pass implements 86 /// an analysis interface through multiple inheritance. If needed, it 87 /// should override this to adjust the this pointer as needed for the 88 /// specified pass info. 89 void *getAdjustedAnalysisPointer(const void *PI) override { 90 if (PI == &AliasAnalysis::ID) 91 return (AliasAnalysis*)this; 92 return this; 93 } 94 95 protected: 96 bool mayAliasInScopes(const MDNode *Scopes, const MDNode *NoAlias) const; 97 void collectMDInDomain(const MDNode *List, const MDNode *Domain, 98 SmallPtrSetImpl<const MDNode *> &Nodes) const; 99 100 private: 101 void getAnalysisUsage(AnalysisUsage &AU) const override; 102 AliasResult alias(const Location &LocA, const Location &LocB) override; 103 bool pointsToConstantMemory(const Location &Loc, bool OrLocal) override; 104 ModRefBehavior getModRefBehavior(ImmutableCallSite CS) override; 105 ModRefBehavior getModRefBehavior(const Function *F) override; 106 ModRefResult getModRefInfo(ImmutableCallSite CS, 107 const Location &Loc) override; 108 ModRefResult getModRefInfo(ImmutableCallSite CS1, 109 ImmutableCallSite CS2) override; 110 }; 111 } // End of anonymous namespace 112 113 // Register this pass... 114 char ScopedNoAliasAA::ID = 0; 115 INITIALIZE_AG_PASS(ScopedNoAliasAA, AliasAnalysis, "scoped-noalias", 116 "Scoped NoAlias Alias Analysis", false, true, false) 117 118 ImmutablePass *llvm::createScopedNoAliasAAPass() { 119 return new ScopedNoAliasAA(); 120 } 121 122 void 123 ScopedNoAliasAA::getAnalysisUsage(AnalysisUsage &AU) const { 124 AU.setPreservesAll(); 125 AliasAnalysis::getAnalysisUsage(AU); 126 } 127 128 void 129 ScopedNoAliasAA::collectMDInDomain(const MDNode *List, const MDNode *Domain, 130 SmallPtrSetImpl<const MDNode *> &Nodes) const { 131 for (unsigned i = 0, ie = List->getNumOperands(); i != ie; ++i) 132 if (const MDNode *MD = dyn_cast<MDNode>(List->getOperand(i))) 133 if (AliasScopeNode(MD).getDomain() == Domain) 134 Nodes.insert(MD); 135 } 136 137 bool 138 ScopedNoAliasAA::mayAliasInScopes(const MDNode *Scopes, 139 const MDNode *NoAlias) const { 140 if (!Scopes || !NoAlias) 141 return true; 142 143 // Collect the set of scope domains relevant to the noalias scopes. 144 SmallPtrSet<const MDNode *, 16> Domains; 145 for (unsigned i = 0, ie = NoAlias->getNumOperands(); i != ie; ++i) 146 if (const MDNode *NAMD = dyn_cast<MDNode>(NoAlias->getOperand(i))) 147 if (const MDNode *Domain = AliasScopeNode(NAMD).getDomain()) 148 Domains.insert(Domain); 149 150 // We alias unless, for some domain, the set of noalias scopes in that domain 151 // is a superset of the set of alias scopes in that domain. 152 for (const MDNode *Domain : Domains) { 153 SmallPtrSet<const MDNode *, 16> NANodes, ScopeNodes; 154 collectMDInDomain(NoAlias, Domain, NANodes); 155 collectMDInDomain(Scopes, Domain, ScopeNodes); 156 if (!ScopeNodes.size()) 157 continue; 158 159 // To not alias, all of the nodes in ScopeNodes must be in NANodes. 160 bool FoundAll = true; 161 for (const MDNode *SMD : ScopeNodes) 162 if (!NANodes.count(SMD)) { 163 FoundAll = false; 164 break; 165 } 166 167 if (FoundAll) 168 return false; 169 } 170 171 return true; 172 } 173 174 AliasAnalysis::AliasResult 175 ScopedNoAliasAA::alias(const Location &LocA, const Location &LocB) { 176 if (!EnableScopedNoAlias) 177 return AliasAnalysis::alias(LocA, LocB); 178 179 // Get the attached MDNodes. 180 const MDNode *AScopes = LocA.AATags.Scope, 181 *BScopes = LocB.AATags.Scope; 182 183 const MDNode *ANoAlias = LocA.AATags.NoAlias, 184 *BNoAlias = LocB.AATags.NoAlias; 185 186 if (!mayAliasInScopes(AScopes, BNoAlias)) 187 return NoAlias; 188 189 if (!mayAliasInScopes(BScopes, ANoAlias)) 190 return NoAlias; 191 192 // If they may alias, chain to the next AliasAnalysis. 193 return AliasAnalysis::alias(LocA, LocB); 194 } 195 196 bool ScopedNoAliasAA::pointsToConstantMemory(const Location &Loc, 197 bool OrLocal) { 198 return AliasAnalysis::pointsToConstantMemory(Loc, OrLocal); 199 } 200 201 AliasAnalysis::ModRefBehavior 202 ScopedNoAliasAA::getModRefBehavior(ImmutableCallSite CS) { 203 return AliasAnalysis::getModRefBehavior(CS); 204 } 205 206 AliasAnalysis::ModRefBehavior 207 ScopedNoAliasAA::getModRefBehavior(const Function *F) { 208 return AliasAnalysis::getModRefBehavior(F); 209 } 210 211 AliasAnalysis::ModRefResult 212 ScopedNoAliasAA::getModRefInfo(ImmutableCallSite CS, const Location &Loc) { 213 if (!EnableScopedNoAlias) 214 return AliasAnalysis::getModRefInfo(CS, Loc); 215 216 if (!mayAliasInScopes(Loc.AATags.Scope, 217 CS.getInstruction()->getMetadata(LLVMContext::MD_noalias))) 218 return NoModRef; 219 220 if (!mayAliasInScopes( 221 CS.getInstruction()->getMetadata(LLVMContext::MD_alias_scope), 222 Loc.AATags.NoAlias)) 223 return NoModRef; 224 225 return AliasAnalysis::getModRefInfo(CS, Loc); 226 } 227 228 AliasAnalysis::ModRefResult 229 ScopedNoAliasAA::getModRefInfo(ImmutableCallSite CS1, ImmutableCallSite CS2) { 230 if (!EnableScopedNoAlias) 231 return AliasAnalysis::getModRefInfo(CS1, CS2); 232 233 if (!mayAliasInScopes( 234 CS1.getInstruction()->getMetadata(LLVMContext::MD_alias_scope), 235 CS2.getInstruction()->getMetadata(LLVMContext::MD_noalias))) 236 return NoModRef; 237 238 if (!mayAliasInScopes( 239 CS2.getInstruction()->getMetadata(LLVMContext::MD_alias_scope), 240 CS1.getInstruction()->getMetadata(LLVMContext::MD_noalias))) 241 return NoModRef; 242 243 return AliasAnalysis::getModRefInfo(CS1, CS2); 244 } 245 246