Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. //===- llvm/Analysis/MemoryDependenceAnalysis.h - Memory Deps ---*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This file defines the MemoryDependenceAnalysis analysis pass.
  10. //
  11. //===----------------------------------------------------------------------===//
  12.  
  13. #ifndef LLVM_ANALYSIS_MEMORYDEPENDENCEANALYSIS_H
  14. #define LLVM_ANALYSIS_MEMORYDEPENDENCEANALYSIS_H
  15.  
  16. #include "llvm/ADT/DenseMap.h"
  17. #include "llvm/ADT/PointerEmbeddedInt.h"
  18. #include "llvm/ADT/PointerIntPair.h"
  19. #include "llvm/ADT/PointerSumType.h"
  20. #include "llvm/ADT/SmallPtrSet.h"
  21. #include "llvm/Analysis/MemoryLocation.h"
  22. #include "llvm/IR/PassManager.h"
  23. #include "llvm/IR/PredIteratorCache.h"
  24. #include "llvm/IR/ValueHandle.h"
  25. #include "llvm/Pass.h"
  26. #include <optional>
  27.  
  28. namespace llvm {
  29.  
  30. class AAResults;
  31. class AssumptionCache;
  32. class BatchAAResults;
  33. class DominatorTree;
  34. class PHITransAddr;
  35.  
  36. /// A memory dependence query can return one of three different answers.
  37. class MemDepResult {
  38.   enum DepType {
  39.     /// Clients of MemDep never see this.
  40.     ///
  41.     /// Entries with this marker occur in a LocalDeps map or NonLocalDeps map
  42.     /// when the instruction they previously referenced was removed from
  43.     /// MemDep.  In either case, the entry may include an instruction pointer.
  44.     /// If so, the pointer is an instruction in the block where scanning can
  45.     /// start from, saving some work.
  46.     ///
  47.     /// In a default-constructed MemDepResult object, the type will be Invalid
  48.     /// and the instruction pointer will be null.
  49.     Invalid = 0,
  50.  
  51.     /// This is a dependence on the specified instruction which clobbers the
  52.     /// desired value.  The pointer member of the MemDepResult pair holds the
  53.     /// instruction that clobbers the memory.  For example, this occurs when we
  54.     /// see a may-aliased store to the memory location we care about.
  55.     ///
  56.     /// There are several cases that may be interesting here:
  57.     ///   1. Loads are clobbered by may-alias stores.
  58.     ///   2. Loads are considered clobbered by partially-aliased loads.  The
  59.     ///      client may choose to analyze deeper into these cases.
  60.     Clobber,
  61.  
  62.     /// This is a dependence on the specified instruction which defines or
  63.     /// produces the desired memory location.  The pointer member of the
  64.     /// MemDepResult pair holds the instruction that defines the memory.
  65.     ///
  66.     /// Cases of interest:
  67.     ///   1. This could be a load or store for dependence queries on
  68.     ///      load/store.  The value loaded or stored is the produced value.
  69.     ///      Note that the pointer operand may be different than that of the
  70.     ///      queried pointer due to must aliases and phi translation. Note
  71.     ///      that the def may not be the same type as the query, the pointers
  72.     ///      may just be must aliases.
  73.     ///   2. For loads and stores, this could be an allocation instruction. In
  74.     ///      this case, the load is loading an undef value or a store is the
  75.     ///      first store to (that part of) the allocation.
  76.     ///   3. Dependence queries on calls return Def only when they are readonly
  77.     ///      calls or memory use intrinsics with identical callees and no
  78.     ///      intervening clobbers.  No validation is done that the operands to
  79.     ///      the calls are the same.
  80.     ///   4. For loads and stores, this could be a select instruction that
  81.     ///      defines pointer to this memory location. In this case, users can
  82.     ///      find non-clobbered Defs for both select values that are reaching
  83.     //       the desired memory location (there is still a guarantee that there
  84.     //       are no clobbers between analyzed memory location and select).
  85.     Def,
  86.  
  87.     /// This marker indicates that the query has no known dependency in the
  88.     /// specified block.
  89.     ///
  90.     /// More detailed state info is encoded in the upper part of the pair (i.e.
  91.     /// the Instruction*)
  92.     Other
  93.   };
  94.  
  95.   /// If DepType is "Other", the upper part of the sum type is an encoding of
  96.   /// the following more detailed type information.
  97.   enum OtherType {
  98.     /// This marker indicates that the query has no dependency in the specified
  99.     /// block.
  100.     ///
  101.     /// To find out more, the client should query other predecessor blocks.
  102.     NonLocal = 1,
  103.     /// This marker indicates that the query has no dependency in the specified
  104.     /// function.
  105.     NonFuncLocal,
  106.     /// This marker indicates that the query dependency is unknown.
  107.     Unknown
  108.   };
  109.  
  110.   using ValueTy = PointerSumType<
  111.       DepType, PointerSumTypeMember<Invalid, Instruction *>,
  112.       PointerSumTypeMember<Clobber, Instruction *>,
  113.       PointerSumTypeMember<Def, Instruction *>,
  114.       PointerSumTypeMember<Other, PointerEmbeddedInt<OtherType, 3>>>;
  115.   ValueTy Value;
  116.  
  117.   explicit MemDepResult(ValueTy V) : Value(V) {}
  118.  
  119. public:
  120.   MemDepResult() = default;
  121.  
  122.   /// get methods: These are static ctor methods for creating various
  123.   /// MemDepResult kinds.
  124.   static MemDepResult getDef(Instruction *Inst) {
  125.     assert(Inst && "Def requires inst");
  126.     return MemDepResult(ValueTy::create<Def>(Inst));
  127.   }
  128.   static MemDepResult getClobber(Instruction *Inst) {
  129.     assert(Inst && "Clobber requires inst");
  130.     return MemDepResult(ValueTy::create<Clobber>(Inst));
  131.   }
  132.   static MemDepResult getNonLocal() {
  133.     return MemDepResult(ValueTy::create<Other>(NonLocal));
  134.   }
  135.   static MemDepResult getNonFuncLocal() {
  136.     return MemDepResult(ValueTy::create<Other>(NonFuncLocal));
  137.   }
  138.   static MemDepResult getUnknown() {
  139.     return MemDepResult(ValueTy::create<Other>(Unknown));
  140.   }
  141.  
  142.   /// Tests if this MemDepResult represents a query that is an instruction
  143.   /// clobber dependency.
  144.   bool isClobber() const { return Value.is<Clobber>(); }
  145.  
  146.   /// Tests if this MemDepResult represents a query that is an instruction
  147.   /// definition dependency.
  148.   bool isDef() const { return Value.is<Def>(); }
  149.  
  150.   /// Tests if this MemDepResult represents a valid local query (Clobber/Def).
  151.   bool isLocal() const { return isClobber() || isDef(); }
  152.  
  153.   /// Tests if this MemDepResult represents a query that is transparent to the
  154.   /// start of the block, but where a non-local hasn't been done.
  155.   bool isNonLocal() const {
  156.     return Value.is<Other>() && Value.cast<Other>() == NonLocal;
  157.   }
  158.  
  159.   /// Tests if this MemDepResult represents a query that is transparent to the
  160.   /// start of the function.
  161.   bool isNonFuncLocal() const {
  162.     return Value.is<Other>() && Value.cast<Other>() == NonFuncLocal;
  163.   }
  164.  
  165.   /// Tests if this MemDepResult represents a query which cannot and/or will
  166.   /// not be computed.
  167.   bool isUnknown() const {
  168.     return Value.is<Other>() && Value.cast<Other>() == Unknown;
  169.   }
  170.  
  171.   /// If this is a normal dependency, returns the instruction that is depended
  172.   /// on.  Otherwise, returns null.
  173.   Instruction *getInst() const {
  174.     switch (Value.getTag()) {
  175.     case Invalid:
  176.       return Value.cast<Invalid>();
  177.     case Clobber:
  178.       return Value.cast<Clobber>();
  179.     case Def:
  180.       return Value.cast<Def>();
  181.     case Other:
  182.       return nullptr;
  183.     }
  184.     llvm_unreachable("Unknown discriminant!");
  185.   }
  186.  
  187.   bool operator==(const MemDepResult &M) const { return Value == M.Value; }
  188.   bool operator!=(const MemDepResult &M) const { return Value != M.Value; }
  189.   bool operator<(const MemDepResult &M) const { return Value < M.Value; }
  190.   bool operator>(const MemDepResult &M) const { return Value > M.Value; }
  191.  
  192. private:
  193.   friend class MemoryDependenceResults;
  194.  
  195.   /// Tests if this is a MemDepResult in its dirty/invalid. state.
  196.   bool isDirty() const { return Value.is<Invalid>(); }
  197.  
  198.   static MemDepResult getDirty(Instruction *Inst) {
  199.     return MemDepResult(ValueTy::create<Invalid>(Inst));
  200.   }
  201. };
  202.  
  203. /// This is an entry in the NonLocalDepInfo cache.
  204. ///
  205. /// For each BasicBlock (the BB entry) it keeps a MemDepResult.
  206. class NonLocalDepEntry {
  207.   BasicBlock *BB;
  208.   MemDepResult Result;
  209.  
  210. public:
  211.   NonLocalDepEntry(BasicBlock *bb, MemDepResult result)
  212.       : BB(bb), Result(result) {}
  213.  
  214.   // This is used for searches.
  215.   NonLocalDepEntry(BasicBlock *bb) : BB(bb) {}
  216.  
  217.   // BB is the sort key, it can't be changed.
  218.   BasicBlock *getBB() const { return BB; }
  219.  
  220.   void setResult(const MemDepResult &R) { Result = R; }
  221.  
  222.   const MemDepResult &getResult() const { return Result; }
  223.  
  224.   bool operator<(const NonLocalDepEntry &RHS) const { return BB < RHS.BB; }
  225. };
  226.  
  227. /// This is a result from a NonLocal dependence query.
  228. ///
  229. /// For each BasicBlock (the BB entry) it keeps a MemDepResult and the
  230. /// (potentially phi translated) address that was live in the block.
  231. class NonLocalDepResult {
  232.   NonLocalDepEntry Entry;
  233.   Value *Address;
  234.  
  235. public:
  236.   NonLocalDepResult(BasicBlock *bb, MemDepResult result, Value *address)
  237.       : Entry(bb, result), Address(address) {}
  238.  
  239.   // BB is the sort key, it can't be changed.
  240.   BasicBlock *getBB() const { return Entry.getBB(); }
  241.  
  242.   void setResult(const MemDepResult &R, Value *Addr) {
  243.     Entry.setResult(R);
  244.     Address = Addr;
  245.   }
  246.  
  247.   const MemDepResult &getResult() const { return Entry.getResult(); }
  248.  
  249.   /// Returns the address of this pointer in this block.
  250.   ///
  251.   /// This can be different than the address queried for the non-local result
  252.   /// because of phi translation.  This returns null if the address was not
  253.   /// available in a block (i.e. because phi translation failed) or if this is
  254.   /// a cached result and that address was deleted.
  255.   ///
  256.   /// The address is always null for a non-local 'call' dependence.
  257.   Value *getAddress() const { return Address; }
  258. };
  259.  
  260. /// Provides a lazy, caching interface for making common memory aliasing
  261. /// information queries, backed by LLVM's alias analysis passes.
  262. ///
  263. /// The dependency information returned is somewhat unusual, but is pragmatic.
  264. /// If queried about a store or call that might modify memory, the analysis
  265. /// will return the instruction[s] that may either load from that memory or
  266. /// store to it.  If queried with a load or call that can never modify memory,
  267. /// the analysis will return calls and stores that might modify the pointer,
  268. /// but generally does not return loads unless a) they are volatile, or
  269. /// b) they load from *must-aliased* pointers.  Returning a dependence on
  270. /// must-alias'd pointers instead of all pointers interacts well with the
  271. /// internal caching mechanism.
  272. class MemoryDependenceResults {
  273.   // A map from instructions to their dependency.
  274.   using LocalDepMapType = DenseMap<Instruction *, MemDepResult>;
  275.   LocalDepMapType LocalDeps;
  276.  
  277. public:
  278.   using NonLocalDepInfo = std::vector<NonLocalDepEntry>;
  279.  
  280. private:
  281.   /// A pair<Value*, bool> where the bool is true if the dependence is a read
  282.   /// only dependence, false if read/write.
  283.   using ValueIsLoadPair = PointerIntPair<const Value *, 1, bool>;
  284.  
  285.   /// This pair is used when caching information for a block.
  286.   ///
  287.   /// If the pointer is null, the cache value is not a full query that starts
  288.   /// at the specified block.  If non-null, the bool indicates whether or not
  289.   /// the contents of the block was skipped.
  290.   using BBSkipFirstBlockPair = PointerIntPair<BasicBlock *, 1, bool>;
  291.  
  292.   /// This record is the information kept for each (value, is load) pair.
  293.   struct NonLocalPointerInfo {
  294.     /// The pair of the block and the skip-first-block flag.
  295.     BBSkipFirstBlockPair Pair;
  296.     /// The results of the query for each relevant block.
  297.     NonLocalDepInfo NonLocalDeps;
  298.     /// The maximum size of the dereferences of the pointer.
  299.     ///
  300.     /// May be UnknownSize if the sizes are unknown.
  301.     LocationSize Size = LocationSize::afterPointer();
  302.     /// The AA tags associated with dereferences of the pointer.
  303.     ///
  304.     /// The members may be null if there are no tags or conflicting tags.
  305.     AAMDNodes AATags;
  306.  
  307.     NonLocalPointerInfo() = default;
  308.   };
  309.  
  310.   /// Cache storing single nonlocal def for the instruction.
  311.   /// It is set when nonlocal def would be found in function returning only
  312.   /// local dependencies.
  313.   DenseMap<AssertingVH<const Value>, NonLocalDepResult> NonLocalDefsCache;
  314.   using ReverseNonLocalDefsCacheTy =
  315.     DenseMap<Instruction *, SmallPtrSet<const Value*, 4>>;
  316.   ReverseNonLocalDefsCacheTy ReverseNonLocalDefsCache;
  317.  
  318.   /// This map stores the cached results of doing a pointer lookup at the
  319.   /// bottom of a block.
  320.   ///
  321.   /// The key of this map is the pointer+isload bit, the value is a list of
  322.   /// <bb->result> mappings.
  323.   using CachedNonLocalPointerInfo =
  324.       DenseMap<ValueIsLoadPair, NonLocalPointerInfo>;
  325.   CachedNonLocalPointerInfo NonLocalPointerDeps;
  326.  
  327.   // A map from instructions to their non-local pointer dependencies.
  328.   using ReverseNonLocalPtrDepTy =
  329.       DenseMap<Instruction *, SmallPtrSet<ValueIsLoadPair, 4>>;
  330.   ReverseNonLocalPtrDepTy ReverseNonLocalPtrDeps;
  331.  
  332.   /// This is the instruction we keep for each cached access that we have for
  333.   /// an instruction.
  334.   ///
  335.   /// The pointer is an owning pointer and the bool indicates whether we have
  336.   /// any dirty bits in the set.
  337.   using PerInstNLInfo = std::pair<NonLocalDepInfo, bool>;
  338.  
  339.   // A map from instructions to their non-local dependencies.
  340.   using NonLocalDepMapType = DenseMap<Instruction *, PerInstNLInfo>;
  341.  
  342.   NonLocalDepMapType NonLocalDepsMap;
  343.  
  344.   // A reverse mapping from dependencies to the dependees.  This is
  345.   // used when removing instructions to keep the cache coherent.
  346.   using ReverseDepMapType =
  347.       DenseMap<Instruction *, SmallPtrSet<Instruction *, 4>>;
  348.   ReverseDepMapType ReverseLocalDeps;
  349.  
  350.   // A reverse mapping from dependencies to the non-local dependees.
  351.   ReverseDepMapType ReverseNonLocalDeps;
  352.  
  353.   /// Current AA implementation, just a cache.
  354.   AAResults &AA;
  355.   AssumptionCache &AC;
  356.   const TargetLibraryInfo &TLI;
  357.   DominatorTree &DT;
  358.   PredIteratorCache PredCache;
  359.  
  360.   unsigned DefaultBlockScanLimit;
  361.  
  362.   /// Offsets to dependant clobber loads.
  363.   using ClobberOffsetsMapType = DenseMap<LoadInst *, int32_t>;
  364.   ClobberOffsetsMapType ClobberOffsets;
  365.  
  366. public:
  367.   MemoryDependenceResults(AAResults &AA, AssumptionCache &AC,
  368.                           const TargetLibraryInfo &TLI, DominatorTree &DT,
  369.                           unsigned DefaultBlockScanLimit)
  370.       : AA(AA), AC(AC), TLI(TLI), DT(DT),
  371.         DefaultBlockScanLimit(DefaultBlockScanLimit) {}
  372.  
  373.   /// Handle invalidation in the new PM.
  374.   bool invalidate(Function &F, const PreservedAnalyses &PA,
  375.                   FunctionAnalysisManager::Invalidator &Inv);
  376.  
  377.   /// Some methods limit the number of instructions they will examine.
  378.   /// The return value of this method is the default limit that will be
  379.   /// used if no limit is explicitly passed in.
  380.   unsigned getDefaultBlockScanLimit() const;
  381.  
  382.   /// Returns the instruction on which a memory operation depends.
  383.   ///
  384.   /// See the class comment for more details. It is illegal to call this on
  385.   /// non-memory instructions.
  386.   MemDepResult getDependency(Instruction *QueryInst);
  387.  
  388.   /// Perform a full dependency query for the specified call, returning the set
  389.   /// of blocks that the value is potentially live across.
  390.   ///
  391.   /// The returned set of results will include a "NonLocal" result for all
  392.   /// blocks where the value is live across.
  393.   ///
  394.   /// This method assumes the instruction returns a "NonLocal" dependency
  395.   /// within its own block.
  396.   ///
  397.   /// This returns a reference to an internal data structure that may be
  398.   /// invalidated on the next non-local query or when an instruction is
  399.   /// removed.  Clients must copy this data if they want it around longer than
  400.   /// that.
  401.   const NonLocalDepInfo &getNonLocalCallDependency(CallBase *QueryCall);
  402.  
  403.   /// Perform a full dependency query for an access to the QueryInst's
  404.   /// specified memory location, returning the set of instructions that either
  405.   /// define or clobber the value.
  406.   ///
  407.   /// Warning: For a volatile query instruction, the dependencies will be
  408.   /// accurate, and thus usable for reordering, but it is never legal to
  409.   /// remove the query instruction.
  410.   ///
  411.   /// This method assumes the pointer has a "NonLocal" dependency within
  412.   /// QueryInst's parent basic block.
  413.   void getNonLocalPointerDependency(Instruction *QueryInst,
  414.                                     SmallVectorImpl<NonLocalDepResult> &Result);
  415.  
  416.   /// Removes an instruction from the dependence analysis, updating the
  417.   /// dependence of instructions that previously depended on it.
  418.   void removeInstruction(Instruction *InstToRemove);
  419.  
  420.   /// Invalidates cached information about the specified pointer, because it
  421.   /// may be too conservative in memdep.
  422.   ///
  423.   /// This is an optional call that can be used when the client detects an
  424.   /// equivalence between the pointer and some other value and replaces the
  425.   /// other value with ptr. This can make Ptr available in more places that
  426.   /// cached info does not necessarily keep.
  427.   void invalidateCachedPointerInfo(Value *Ptr);
  428.  
  429.   /// Clears the PredIteratorCache info.
  430.   ///
  431.   /// This needs to be done when the CFG changes, e.g., due to splitting
  432.   /// critical edges.
  433.   void invalidateCachedPredecessors();
  434.  
  435.   /// Returns the instruction on which a memory location depends.
  436.   ///
  437.   /// If isLoad is true, this routine ignores may-aliases with read-only
  438.   /// operations.  If isLoad is false, this routine ignores may-aliases
  439.   /// with reads from read-only locations. If possible, pass the query
  440.   /// instruction as well; this function may take advantage of the metadata
  441.   /// annotated to the query instruction to refine the result. \p Limit
  442.   /// can be used to set the maximum number of instructions that will be
  443.   /// examined to find the pointer dependency. On return, it will be set to
  444.   /// the number of instructions left to examine. If a null pointer is passed
  445.   /// in, the limit will default to the value of -memdep-block-scan-limit.
  446.   ///
  447.   /// Note that this is an uncached query, and thus may be inefficient.
  448.   MemDepResult getPointerDependencyFrom(const MemoryLocation &Loc, bool isLoad,
  449.                                         BasicBlock::iterator ScanIt,
  450.                                         BasicBlock *BB,
  451.                                         Instruction *QueryInst = nullptr,
  452.                                         unsigned *Limit = nullptr);
  453.  
  454.   MemDepResult getPointerDependencyFrom(const MemoryLocation &Loc, bool isLoad,
  455.                                         BasicBlock::iterator ScanIt,
  456.                                         BasicBlock *BB,
  457.                                         Instruction *QueryInst,
  458.                                         unsigned *Limit,
  459.                                         BatchAAResults &BatchAA);
  460.  
  461.   MemDepResult
  462.   getSimplePointerDependencyFrom(const MemoryLocation &MemLoc, bool isLoad,
  463.                                  BasicBlock::iterator ScanIt, BasicBlock *BB,
  464.                                  Instruction *QueryInst, unsigned *Limit,
  465.                                  BatchAAResults &BatchAA);
  466.  
  467.   /// This analysis looks for other loads and stores with invariant.group
  468.   /// metadata and the same pointer operand. Returns Unknown if it does not
  469.   /// find anything, and Def if it can be assumed that 2 instructions load or
  470.   /// store the same value and NonLocal which indicate that non-local Def was
  471.   /// found, which can be retrieved by calling getNonLocalPointerDependency
  472.   /// with the same queried instruction.
  473.   MemDepResult getInvariantGroupPointerDependency(LoadInst *LI, BasicBlock *BB);
  474.  
  475.   /// Release memory in caches.
  476.   void releaseMemory();
  477.  
  478.   /// Return the clobber offset to dependent instruction.
  479.   std::optional<int32_t> getClobberOffset(LoadInst *DepInst) const {
  480.     const auto Off = ClobberOffsets.find(DepInst);
  481.     if (Off != ClobberOffsets.end())
  482.       return Off->getSecond();
  483.     return std::nullopt;
  484.   }
  485.  
  486. private:
  487.   MemDepResult getCallDependencyFrom(CallBase *Call, bool isReadOnlyCall,
  488.                                      BasicBlock::iterator ScanIt,
  489.                                      BasicBlock *BB);
  490.   bool getNonLocalPointerDepFromBB(Instruction *QueryInst,
  491.                                    const PHITransAddr &Pointer,
  492.                                    const MemoryLocation &Loc, bool isLoad,
  493.                                    BasicBlock *BB,
  494.                                    SmallVectorImpl<NonLocalDepResult> &Result,
  495.                                    DenseMap<BasicBlock *, Value *> &Visited,
  496.                                    bool SkipFirstBlock = false,
  497.                                    bool IsIncomplete = false);
  498.   MemDepResult getNonLocalInfoForBlock(Instruction *QueryInst,
  499.                                        const MemoryLocation &Loc, bool isLoad,
  500.                                        BasicBlock *BB, NonLocalDepInfo *Cache,
  501.                                        unsigned NumSortedEntries,
  502.                                        BatchAAResults &BatchAA);
  503.  
  504.   void removeCachedNonLocalPointerDependencies(ValueIsLoadPair P);
  505.  
  506.   void verifyRemoved(Instruction *Inst) const;
  507. };
  508.  
  509. /// An analysis that produces \c MemoryDependenceResults for a function.
  510. ///
  511. /// This is essentially a no-op because the results are computed entirely
  512. /// lazily.
  513. class MemoryDependenceAnalysis
  514.     : public AnalysisInfoMixin<MemoryDependenceAnalysis> {
  515.   friend AnalysisInfoMixin<MemoryDependenceAnalysis>;
  516.  
  517.   static AnalysisKey Key;
  518.  
  519.   unsigned DefaultBlockScanLimit;
  520.  
  521. public:
  522.   using Result = MemoryDependenceResults;
  523.  
  524.   MemoryDependenceAnalysis();
  525.   MemoryDependenceAnalysis(unsigned DefaultBlockScanLimit) : DefaultBlockScanLimit(DefaultBlockScanLimit) { }
  526.  
  527.   MemoryDependenceResults run(Function &F, FunctionAnalysisManager &AM);
  528. };
  529.  
  530. /// A wrapper analysis pass for the legacy pass manager that exposes a \c
  531. /// MemoryDepnedenceResults instance.
  532. class MemoryDependenceWrapperPass : public FunctionPass {
  533.   std::optional<MemoryDependenceResults> MemDep;
  534.  
  535. public:
  536.   static char ID;
  537.  
  538.   MemoryDependenceWrapperPass();
  539.   ~MemoryDependenceWrapperPass() override;
  540.  
  541.   /// Pass Implementation stuff.  This doesn't do any analysis eagerly.
  542.   bool runOnFunction(Function &) override;
  543.  
  544.   /// Clean up memory in between runs
  545.   void releaseMemory() override;
  546.  
  547.   /// Does not modify anything.  It uses Value Numbering and Alias Analysis.
  548.   void getAnalysisUsage(AnalysisUsage &AU) const override;
  549.  
  550.   MemoryDependenceResults &getMemDep() { return *MemDep; }
  551. };
  552.  
  553. } // end namespace llvm
  554.  
  555. #endif // LLVM_ANALYSIS_MEMORYDEPENDENCEANALYSIS_H
  556.