LLVM API Documentation

ScopedNoAliasAA.cpp
Go to the documentation of this file.
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