LLVM API Documentation
00001 //===- ScopedNoAliasAA.cpp - Scoped No-Alias Alias Analysis ---------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file defines the ScopedNoAlias alias-analysis pass, which implements 00011 // metadata-based scoped no-alias support. 00012 // 00013 // Alias-analysis scopes are defined by an id (which can be a string or some 00014 // other metadata node), a domain node, and an optional descriptive string. 00015 // A domain is defined by an id (which can be a string or some other metadata 00016 // node), and an optional descriptive string. 00017 // 00018 // !dom0 = metadata !{ metadata !"domain of foo()" } 00019 // !scope1 = metadata !{ metadata !scope1, metadata !dom0, metadata !"scope 1" } 00020 // !scope2 = metadata !{ metadata !scope2, metadata !dom0, metadata !"scope 2" } 00021 // 00022 // Loads and stores can be tagged with an alias-analysis scope, and also, with 00023 // a noalias tag for a specific scope: 00024 // 00025 // ... = load %ptr1, !alias.scope !{ !scope1 } 00026 // ... = load %ptr2, !alias.scope !{ !scope1, !scope2 }, !noalias !{ !scope1 } 00027 // 00028 // When evaluating an aliasing query, if one of the instructions is associated 00029 // has a set of noalias scopes in some domain that is superset of the alias 00030 // scopes in that domain of some other instruction, then the two memory 00031 // accesses are assumed not to alias. 00032 // 00033 //===----------------------------------------------------------------------===// 00034 00035 #include "llvm/ADT/SmallPtrSet.h" 00036 #include "llvm/Analysis/Passes.h" 00037 #include "llvm/Analysis/AliasAnalysis.h" 00038 #include "llvm/IR/Constants.h" 00039 #include "llvm/IR/LLVMContext.h" 00040 #include "llvm/IR/Metadata.h" 00041 #include "llvm/IR/Module.h" 00042 #include "llvm/Pass.h" 00043 #include "llvm/Support/CommandLine.h" 00044 using namespace llvm; 00045 00046 // A handy option for disabling scoped no-alias functionality. The same effect 00047 // can also be achieved by stripping the associated metadata tags from IR, but 00048 // this option is sometimes more convenient. 00049 static cl::opt<bool> 00050 EnableScopedNoAlias("enable-scoped-noalias", cl::init(true)); 00051 00052 namespace { 00053 /// AliasScopeNode - This is a simple wrapper around an MDNode which provides 00054 /// a higher-level interface by hiding the details of how alias analysis 00055 /// information is encoded in its operands. 00056 class AliasScopeNode { 00057 const MDNode *Node; 00058 00059 public: 00060 AliasScopeNode() : Node(0) {} 00061 explicit AliasScopeNode(const MDNode *N) : Node(N) {} 00062 00063 /// getNode - Get the MDNode for this AliasScopeNode. 00064 const MDNode *getNode() const { return Node; } 00065 00066 /// getDomain - Get the MDNode for this AliasScopeNode's domain. 00067 const MDNode *getDomain() const { 00068 if (Node->getNumOperands() < 2) 00069 return nullptr; 00070 return dyn_cast_or_null<MDNode>(Node->getOperand(1)); 00071 } 00072 }; 00073 00074 /// ScopedNoAliasAA - This is a simple alias analysis 00075 /// implementation that uses scoped-noalias metadata to answer queries. 00076 class ScopedNoAliasAA : public ImmutablePass, public AliasAnalysis { 00077 public: 00078 static char ID; // Class identification, replacement for typeinfo 00079 ScopedNoAliasAA() : ImmutablePass(ID) { 00080 initializeScopedNoAliasAAPass(*PassRegistry::getPassRegistry()); 00081 } 00082 00083 void initializePass() override { InitializeAliasAnalysis(this); } 00084 00085 /// getAdjustedAnalysisPointer - This method is used when a pass implements 00086 /// an analysis interface through multiple inheritance. If needed, it 00087 /// should override this to adjust the this pointer as needed for the 00088 /// specified pass info. 00089 void *getAdjustedAnalysisPointer(const void *PI) override { 00090 if (PI == &AliasAnalysis::ID) 00091 return (AliasAnalysis*)this; 00092 return this; 00093 } 00094 00095 protected: 00096 bool mayAliasInScopes(const MDNode *Scopes, const MDNode *NoAlias) const; 00097 void collectMDInDomain(const MDNode *List, const MDNode *Domain, 00098 SmallPtrSetImpl<const MDNode *> &Nodes) const; 00099 00100 private: 00101 void getAnalysisUsage(AnalysisUsage &AU) const override; 00102 AliasResult alias(const Location &LocA, const Location &LocB) override; 00103 bool pointsToConstantMemory(const Location &Loc, bool OrLocal) override; 00104 ModRefBehavior getModRefBehavior(ImmutableCallSite CS) override; 00105 ModRefBehavior getModRefBehavior(const Function *F) override; 00106 ModRefResult getModRefInfo(ImmutableCallSite CS, 00107 const Location &Loc) override; 00108 ModRefResult getModRefInfo(ImmutableCallSite CS1, 00109 ImmutableCallSite CS2) override; 00110 }; 00111 } // End of anonymous namespace 00112 00113 // Register this pass... 00114 char ScopedNoAliasAA::ID = 0; 00115 INITIALIZE_AG_PASS(ScopedNoAliasAA, AliasAnalysis, "scoped-noalias", 00116 "Scoped NoAlias Alias Analysis", false, true, false) 00117 00118 ImmutablePass *llvm::createScopedNoAliasAAPass() { 00119 return new ScopedNoAliasAA(); 00120 } 00121 00122 void 00123 ScopedNoAliasAA::getAnalysisUsage(AnalysisUsage &AU) const { 00124 AU.setPreservesAll(); 00125 AliasAnalysis::getAnalysisUsage(AU); 00126 } 00127 00128 void 00129 ScopedNoAliasAA::collectMDInDomain(const MDNode *List, const MDNode *Domain, 00130 SmallPtrSetImpl<const MDNode *> &Nodes) const { 00131 for (unsigned i = 0, ie = List->getNumOperands(); i != ie; ++i) 00132 if (const MDNode *MD = dyn_cast<MDNode>(List->getOperand(i))) 00133 if (AliasScopeNode(MD).getDomain() == Domain) 00134 Nodes.insert(MD); 00135 } 00136 00137 bool 00138 ScopedNoAliasAA::mayAliasInScopes(const MDNode *Scopes, 00139 const MDNode *NoAlias) const { 00140 if (!Scopes || !NoAlias) 00141 return true; 00142 00143 // Collect the set of scope domains relevant to the noalias scopes. 00144 SmallPtrSet<const MDNode *, 16> Domains; 00145 for (unsigned i = 0, ie = NoAlias->getNumOperands(); i != ie; ++i) 00146 if (const MDNode *NAMD = dyn_cast<MDNode>(NoAlias->getOperand(i))) 00147 if (const MDNode *Domain = AliasScopeNode(NAMD).getDomain()) 00148 Domains.insert(Domain); 00149 00150 // We alias unless, for some domain, the set of noalias scopes in that domain 00151 // is a superset of the set of alias scopes in that domain. 00152 for (const MDNode *Domain : Domains) { 00153 SmallPtrSet<const MDNode *, 16> NANodes, ScopeNodes; 00154 collectMDInDomain(NoAlias, Domain, NANodes); 00155 collectMDInDomain(Scopes, Domain, ScopeNodes); 00156 if (!ScopeNodes.size()) 00157 continue; 00158 00159 // To not alias, all of the nodes in ScopeNodes must be in NANodes. 00160 bool FoundAll = true; 00161 for (const MDNode *SMD : ScopeNodes) 00162 if (!NANodes.count(SMD)) { 00163 FoundAll = false; 00164 break; 00165 } 00166 00167 if (FoundAll) 00168 return false; 00169 } 00170 00171 return true; 00172 } 00173 00174 AliasAnalysis::AliasResult 00175 ScopedNoAliasAA::alias(const Location &LocA, const Location &LocB) { 00176 if (!EnableScopedNoAlias) 00177 return AliasAnalysis::alias(LocA, LocB); 00178 00179 // Get the attached MDNodes. 00180 const MDNode *AScopes = LocA.AATags.Scope, 00181 *BScopes = LocB.AATags.Scope; 00182 00183 const MDNode *ANoAlias = LocA.AATags.NoAlias, 00184 *BNoAlias = LocB.AATags.NoAlias; 00185 00186 if (!mayAliasInScopes(AScopes, BNoAlias)) 00187 return NoAlias; 00188 00189 if (!mayAliasInScopes(BScopes, ANoAlias)) 00190 return NoAlias; 00191 00192 // If they may alias, chain to the next AliasAnalysis. 00193 return AliasAnalysis::alias(LocA, LocB); 00194 } 00195 00196 bool ScopedNoAliasAA::pointsToConstantMemory(const Location &Loc, 00197 bool OrLocal) { 00198 return AliasAnalysis::pointsToConstantMemory(Loc, OrLocal); 00199 } 00200 00201 AliasAnalysis::ModRefBehavior 00202 ScopedNoAliasAA::getModRefBehavior(ImmutableCallSite CS) { 00203 return AliasAnalysis::getModRefBehavior(CS); 00204 } 00205 00206 AliasAnalysis::ModRefBehavior 00207 ScopedNoAliasAA::getModRefBehavior(const Function *F) { 00208 return AliasAnalysis::getModRefBehavior(F); 00209 } 00210 00211 AliasAnalysis::ModRefResult 00212 ScopedNoAliasAA::getModRefInfo(ImmutableCallSite CS, const Location &Loc) { 00213 if (!EnableScopedNoAlias) 00214 return AliasAnalysis::getModRefInfo(CS, Loc); 00215 00216 if (!mayAliasInScopes(Loc.AATags.Scope, 00217 CS.getInstruction()->getMetadata(LLVMContext::MD_noalias))) 00218 return NoModRef; 00219 00220 if (!mayAliasInScopes( 00221 CS.getInstruction()->getMetadata(LLVMContext::MD_alias_scope), 00222 Loc.AATags.NoAlias)) 00223 return NoModRef; 00224 00225 return AliasAnalysis::getModRefInfo(CS, Loc); 00226 } 00227 00228 AliasAnalysis::ModRefResult 00229 ScopedNoAliasAA::getModRefInfo(ImmutableCallSite CS1, ImmutableCallSite CS2) { 00230 if (!EnableScopedNoAlias) 00231 return AliasAnalysis::getModRefInfo(CS1, CS2); 00232 00233 if (!mayAliasInScopes( 00234 CS1.getInstruction()->getMetadata(LLVMContext::MD_alias_scope), 00235 CS2.getInstruction()->getMetadata(LLVMContext::MD_noalias))) 00236 return NoModRef; 00237 00238 if (!mayAliasInScopes( 00239 CS2.getInstruction()->getMetadata(LLVMContext::MD_alias_scope), 00240 CS1.getInstruction()->getMetadata(LLVMContext::MD_noalias))) 00241 return NoModRef; 00242 00243 return AliasAnalysis::getModRefInfo(CS1, CS2); 00244 } 00245