ScopedNoAliasAA.cpp 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  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. #include "llvm/ADT/SmallPtrSet.h"
  35. #include "llvm/Analysis/AliasAnalysis.h"
  36. #include "llvm/Analysis/Passes.h"
  37. #include "llvm/IR/Constants.h"
  38. #include "llvm/IR/LLVMContext.h"
  39. #include "llvm/IR/Metadata.h"
  40. #include "llvm/IR/Module.h"
  41. #include "llvm/Pass.h"
  42. #include "llvm/Support/CommandLine.h"
  43. using namespace llvm;
  44. // A handy option for disabling scoped no-alias functionality. The same effect
  45. // can also be achieved by stripping the associated metadata tags from IR, but
  46. // this option is sometimes more convenient.
  47. static cl::opt<bool>
  48. EnableScopedNoAlias("enable-scoped-noalias", cl::init(true));
  49. namespace {
  50. /// AliasScopeNode - This is a simple wrapper around an MDNode which provides
  51. /// a higher-level interface by hiding the details of how alias analysis
  52. /// information is encoded in its operands.
  53. class AliasScopeNode {
  54. const MDNode *Node;
  55. public:
  56. AliasScopeNode() : Node(0) {}
  57. explicit AliasScopeNode(const MDNode *N) : Node(N) {}
  58. /// getNode - Get the MDNode for this AliasScopeNode.
  59. const MDNode *getNode() const { return Node; }
  60. /// getDomain - Get the MDNode for this AliasScopeNode's domain.
  61. const MDNode *getDomain() const {
  62. if (Node->getNumOperands() < 2)
  63. return nullptr;
  64. return dyn_cast_or_null<MDNode>(Node->getOperand(1));
  65. }
  66. };
  67. /// ScopedNoAliasAA - This is a simple alias analysis
  68. /// implementation that uses scoped-noalias metadata to answer queries.
  69. class ScopedNoAliasAA : public ImmutablePass, public AliasAnalysis {
  70. public:
  71. static char ID; // Class identification, replacement for typeinfo
  72. ScopedNoAliasAA() : ImmutablePass(ID) {
  73. initializeScopedNoAliasAAPass(*PassRegistry::getPassRegistry());
  74. }
  75. bool doInitialization(Module &M) override;
  76. /// getAdjustedAnalysisPointer - This method is used when a pass implements
  77. /// an analysis interface through multiple inheritance. If needed, it
  78. /// should override this to adjust the this pointer as needed for the
  79. /// specified pass info.
  80. void *getAdjustedAnalysisPointer(const void *PI) override {
  81. if (PI == &AliasAnalysis::ID)
  82. return (AliasAnalysis*)this;
  83. return this;
  84. }
  85. protected:
  86. bool mayAliasInScopes(const MDNode *Scopes, const MDNode *NoAlias) const;
  87. void collectMDInDomain(const MDNode *List, const MDNode *Domain,
  88. SmallPtrSetImpl<const MDNode *> &Nodes) const;
  89. private:
  90. void getAnalysisUsage(AnalysisUsage &AU) const override;
  91. AliasResult alias(const MemoryLocation &LocA,
  92. const MemoryLocation &LocB) override;
  93. bool pointsToConstantMemory(const MemoryLocation &Loc, bool OrLocal) override;
  94. ModRefBehavior getModRefBehavior(ImmutableCallSite CS) override;
  95. ModRefBehavior getModRefBehavior(const Function *F) override;
  96. ModRefResult getModRefInfo(ImmutableCallSite CS,
  97. const MemoryLocation &Loc) override;
  98. ModRefResult getModRefInfo(ImmutableCallSite CS1,
  99. ImmutableCallSite CS2) override;
  100. };
  101. } // End of anonymous namespace
  102. // Register this pass...
  103. char ScopedNoAliasAA::ID = 0;
  104. INITIALIZE_AG_PASS(ScopedNoAliasAA, AliasAnalysis, "scoped-noalias",
  105. "Scoped NoAlias Alias Analysis", false, true, false)
  106. ImmutablePass *llvm::createScopedNoAliasAAPass() {
  107. return new ScopedNoAliasAA();
  108. }
  109. bool ScopedNoAliasAA::doInitialization(Module &M) {
  110. InitializeAliasAnalysis(this, &M.getDataLayout());
  111. return true;
  112. }
  113. void
  114. ScopedNoAliasAA::getAnalysisUsage(AnalysisUsage &AU) const {
  115. AU.setPreservesAll();
  116. AliasAnalysis::getAnalysisUsage(AU);
  117. }
  118. void
  119. ScopedNoAliasAA::collectMDInDomain(const MDNode *List, const MDNode *Domain,
  120. SmallPtrSetImpl<const MDNode *> &Nodes) const {
  121. for (unsigned i = 0, ie = List->getNumOperands(); i != ie; ++i)
  122. if (const MDNode *MD = dyn_cast<MDNode>(List->getOperand(i)))
  123. if (AliasScopeNode(MD).getDomain() == Domain)
  124. Nodes.insert(MD);
  125. }
  126. bool
  127. ScopedNoAliasAA::mayAliasInScopes(const MDNode *Scopes,
  128. const MDNode *NoAlias) const {
  129. if (!Scopes || !NoAlias)
  130. return true;
  131. // Collect the set of scope domains relevant to the noalias scopes.
  132. SmallPtrSet<const MDNode *, 16> Domains;
  133. for (unsigned i = 0, ie = NoAlias->getNumOperands(); i != ie; ++i)
  134. if (const MDNode *NAMD = dyn_cast<MDNode>(NoAlias->getOperand(i)))
  135. if (const MDNode *Domain = AliasScopeNode(NAMD).getDomain())
  136. Domains.insert(Domain);
  137. // We alias unless, for some domain, the set of noalias scopes in that domain
  138. // is a superset of the set of alias scopes in that domain.
  139. for (const MDNode *Domain : Domains) {
  140. SmallPtrSet<const MDNode *, 16> NANodes, ScopeNodes;
  141. collectMDInDomain(NoAlias, Domain, NANodes);
  142. collectMDInDomain(Scopes, Domain, ScopeNodes);
  143. if (!ScopeNodes.size())
  144. continue;
  145. // To not alias, all of the nodes in ScopeNodes must be in NANodes.
  146. bool FoundAll = true;
  147. for (const MDNode *SMD : ScopeNodes)
  148. if (!NANodes.count(SMD)) {
  149. FoundAll = false;
  150. break;
  151. }
  152. if (FoundAll)
  153. return false;
  154. }
  155. return true;
  156. }
  157. AliasResult ScopedNoAliasAA::alias(const MemoryLocation &LocA,
  158. const MemoryLocation &LocB) {
  159. if (!EnableScopedNoAlias)
  160. return AliasAnalysis::alias(LocA, LocB);
  161. // Get the attached MDNodes.
  162. const MDNode *AScopes = LocA.AATags.Scope,
  163. *BScopes = LocB.AATags.Scope;
  164. const MDNode *ANoAlias = LocA.AATags.NoAlias,
  165. *BNoAlias = LocB.AATags.NoAlias;
  166. if (!mayAliasInScopes(AScopes, BNoAlias))
  167. return NoAlias;
  168. if (!mayAliasInScopes(BScopes, ANoAlias))
  169. return NoAlias;
  170. // If they may alias, chain to the next AliasAnalysis.
  171. return AliasAnalysis::alias(LocA, LocB);
  172. }
  173. bool ScopedNoAliasAA::pointsToConstantMemory(const MemoryLocation &Loc,
  174. bool OrLocal) {
  175. return AliasAnalysis::pointsToConstantMemory(Loc, OrLocal);
  176. }
  177. AliasAnalysis::ModRefBehavior
  178. ScopedNoAliasAA::getModRefBehavior(ImmutableCallSite CS) {
  179. return AliasAnalysis::getModRefBehavior(CS);
  180. }
  181. AliasAnalysis::ModRefBehavior
  182. ScopedNoAliasAA::getModRefBehavior(const Function *F) {
  183. return AliasAnalysis::getModRefBehavior(F);
  184. }
  185. AliasAnalysis::ModRefResult
  186. ScopedNoAliasAA::getModRefInfo(ImmutableCallSite CS,
  187. const MemoryLocation &Loc) {
  188. if (!EnableScopedNoAlias)
  189. return AliasAnalysis::getModRefInfo(CS, Loc);
  190. if (!mayAliasInScopes(Loc.AATags.Scope, CS.getInstruction()->getMetadata(
  191. LLVMContext::MD_noalias)))
  192. return NoModRef;
  193. if (!mayAliasInScopes(
  194. CS.getInstruction()->getMetadata(LLVMContext::MD_alias_scope),
  195. Loc.AATags.NoAlias))
  196. return NoModRef;
  197. return AliasAnalysis::getModRefInfo(CS, Loc);
  198. }
  199. AliasAnalysis::ModRefResult
  200. ScopedNoAliasAA::getModRefInfo(ImmutableCallSite CS1, ImmutableCallSite CS2) {
  201. if (!EnableScopedNoAlias)
  202. return AliasAnalysis::getModRefInfo(CS1, CS2);
  203. if (!mayAliasInScopes(
  204. CS1.getInstruction()->getMetadata(LLVMContext::MD_alias_scope),
  205. CS2.getInstruction()->getMetadata(LLVMContext::MD_noalias)))
  206. return NoModRef;
  207. if (!mayAliasInScopes(
  208. CS2.getInstruction()->getMetadata(LLVMContext::MD_alias_scope),
  209. CS1.getInstruction()->getMetadata(LLVMContext::MD_noalias)))
  210. return NoModRef;
  211. return AliasAnalysis::getModRefInfo(CS1, CS2);
  212. }