ScopedNoAliasAA.cpp 8.9 KB

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