- //===- GVN.h - Eliminate redundant values and loads -------------*- C++ -*-===// 
- // 
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 
- // See https://llvm.org/LICENSE.txt for license information. 
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 
- // 
- //===----------------------------------------------------------------------===// 
- /// \file 
- /// This file provides the interface for LLVM's Global Value Numbering pass 
- /// which eliminates fully redundant instructions. It also does somewhat Ad-Hoc 
- /// PRE and dead load elimination. 
- /// 
- //===----------------------------------------------------------------------===// 
-   
- #ifndef LLVM_TRANSFORMS_SCALAR_GVN_H 
- #define LLVM_TRANSFORMS_SCALAR_GVN_H 
-   
- #include "llvm/ADT/DenseMap.h" 
- #include "llvm/ADT/MapVector.h" 
- #include "llvm/ADT/SetVector.h" 
- #include "llvm/ADT/SmallVector.h" 
- #include "llvm/IR/Dominators.h" 
- #include "llvm/IR/InstrTypes.h" 
- #include "llvm/IR/PassManager.h" 
- #include "llvm/IR/ValueHandle.h" 
- #include "llvm/Support/Allocator.h" 
- #include "llvm/Support/Compiler.h" 
- #include <cstdint> 
- #include <optional> 
- #include <utility> 
- #include <vector> 
-   
- namespace llvm { 
-   
- class AAResults; 
- class AssumeInst; 
- class AssumptionCache; 
- class BasicBlock; 
- class BranchInst; 
- class CallInst; 
- class ExtractValueInst; 
- class Function; 
- class FunctionPass; 
- class GetElementPtrInst; 
- class ImplicitControlFlowTracking; 
- class LoadInst; 
- class LoopInfo; 
- class MemDepResult; 
- class MemoryDependenceResults; 
- class MemorySSA; 
- class MemorySSAUpdater; 
- class NonLocalDepResult; 
- class OptimizationRemarkEmitter; 
- class PHINode; 
- class TargetLibraryInfo; 
- class Value; 
- /// A private "module" namespace for types and utilities used by GVN. These 
- /// are implementation details and should not be used by clients. 
- namespace gvn LLVM_LIBRARY_VISIBILITY { 
-   
- struct AvailableValue; 
- struct AvailableValueInBlock; 
- class GVNLegacyPass; 
-   
- } // end namespace gvn 
-   
- /// A set of parameters to control various transforms performed by GVN pass. 
- //  Each of the optional boolean parameters can be set to: 
- ///      true - enabling the transformation. 
- ///      false - disabling the transformation. 
- ///      None - relying on a global default. 
- /// Intended use is to create a default object, modify parameters with 
- /// additional setters and then pass it to GVN. 
- struct GVNOptions { 
-   std::optional<bool> AllowPRE; 
-   std::optional<bool> AllowLoadPRE; 
-   std::optional<bool> AllowLoadInLoopPRE; 
-   std::optional<bool> AllowLoadPRESplitBackedge; 
-   std::optional<bool> AllowMemDep; 
-   
-   GVNOptions() = default; 
-   
-   /// Enables or disables PRE in GVN. 
-   GVNOptions &setPRE(bool PRE) { 
-     AllowPRE = PRE; 
-     return *this; 
-   } 
-   
-   /// Enables or disables PRE of loads in GVN. 
-   GVNOptions &setLoadPRE(bool LoadPRE) { 
-     AllowLoadPRE = LoadPRE; 
-     return *this; 
-   } 
-   
-   GVNOptions &setLoadInLoopPRE(bool LoadInLoopPRE) { 
-     AllowLoadInLoopPRE = LoadInLoopPRE; 
-     return *this; 
-   } 
-   
-   /// Enables or disables PRE of loads in GVN. 
-   GVNOptions &setLoadPRESplitBackedge(bool LoadPRESplitBackedge) { 
-     AllowLoadPRESplitBackedge = LoadPRESplitBackedge; 
-     return *this; 
-   } 
-   
-   /// Enables or disables use of MemDepAnalysis. 
-   GVNOptions &setMemDep(bool MemDep) { 
-     AllowMemDep = MemDep; 
-     return *this; 
-   } 
- }; 
-   
- /// The core GVN pass object. 
- /// 
- /// FIXME: We should have a good summary of the GVN algorithm implemented by 
- /// this particular pass here. 
- class GVNPass : public PassInfoMixin<GVNPass> { 
-   GVNOptions Options; 
-   
- public: 
-   struct Expression; 
-   
-   GVNPass(GVNOptions Options = {}) : Options(Options) {} 
-   
-   /// Run the pass over the function. 
-   PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); 
-   
-   void printPipeline(raw_ostream &OS, 
-                      function_ref<StringRef(StringRef)> MapClassName2PassName); 
-   
-   /// This removes the specified instruction from 
-   /// our various maps and marks it for deletion. 
-   void markInstructionForDeletion(Instruction *I) { 
-     VN.erase(I); 
-     InstrsToErase.push_back(I); 
-   } 
-   
-   DominatorTree &getDominatorTree() const { return *DT; } 
-   AAResults *getAliasAnalysis() const { return VN.getAliasAnalysis(); } 
-   MemoryDependenceResults &getMemDep() const { return *MD; } 
-   
-   bool isPREEnabled() const; 
-   bool isLoadPREEnabled() const; 
-   bool isLoadInLoopPREEnabled() const; 
-   bool isLoadPRESplitBackedgeEnabled() const; 
-   bool isMemDepEnabled() const; 
-   
-   /// This class holds the mapping between values and value numbers.  It is used 
-   /// as an efficient mechanism to determine the expression-wise equivalence of 
-   /// two values. 
-   class ValueTable { 
-     DenseMap<Value *, uint32_t> valueNumbering; 
-     DenseMap<Expression, uint32_t> expressionNumbering; 
-   
-     // Expressions is the vector of Expression. ExprIdx is the mapping from 
-     // value number to the index of Expression in Expressions. We use it 
-     // instead of a DenseMap because filling such mapping is faster than 
-     // filling a DenseMap and the compile time is a little better. 
-     uint32_t nextExprNumber = 0; 
-   
-     std::vector<Expression> Expressions; 
-     std::vector<uint32_t> ExprIdx; 
-   
-     // Value number to PHINode mapping. Used for phi-translate in scalarpre. 
-     DenseMap<uint32_t, PHINode *> NumberingPhi; 
-   
-     // Cache for phi-translate in scalarpre. 
-     using PhiTranslateMap = 
-         DenseMap<std::pair<uint32_t, const BasicBlock *>, uint32_t>; 
-     PhiTranslateMap PhiTranslateTable; 
-   
-     AAResults *AA = nullptr; 
-     MemoryDependenceResults *MD = nullptr; 
-     DominatorTree *DT = nullptr; 
-   
-     uint32_t nextValueNumber = 1; 
-   
-     Expression createExpr(Instruction *I); 
-     Expression createCmpExpr(unsigned Opcode, CmpInst::Predicate Predicate, 
-                              Value *LHS, Value *RHS); 
-     Expression createExtractvalueExpr(ExtractValueInst *EI); 
-     Expression createGEPExpr(GetElementPtrInst *GEP); 
-     uint32_t lookupOrAddCall(CallInst *C); 
-     uint32_t phiTranslateImpl(const BasicBlock *BB, const BasicBlock *PhiBlock, 
-                               uint32_t Num, GVNPass &Gvn); 
-     bool areCallValsEqual(uint32_t Num, uint32_t NewNum, const BasicBlock *Pred, 
-                           const BasicBlock *PhiBlock, GVNPass &Gvn); 
-     std::pair<uint32_t, bool> assignExpNewValueNum(Expression &exp); 
-     bool areAllValsInBB(uint32_t num, const BasicBlock *BB, GVNPass &Gvn); 
-   
-   public: 
-     ValueTable(); 
-     ValueTable(const ValueTable &Arg); 
-     ValueTable(ValueTable &&Arg); 
-     ~ValueTable(); 
-     ValueTable &operator=(const ValueTable &Arg); 
-   
-     uint32_t lookupOrAdd(Value *V); 
-     uint32_t lookup(Value *V, bool Verify = true) const; 
-     uint32_t lookupOrAddCmp(unsigned Opcode, CmpInst::Predicate Pred, 
-                             Value *LHS, Value *RHS); 
-     uint32_t phiTranslate(const BasicBlock *BB, const BasicBlock *PhiBlock, 
-                           uint32_t Num, GVNPass &Gvn); 
-     void eraseTranslateCacheEntry(uint32_t Num, const BasicBlock &CurrBlock); 
-     bool exists(Value *V) const; 
-     void add(Value *V, uint32_t num); 
-     void clear(); 
-     void erase(Value *v); 
-     void setAliasAnalysis(AAResults *A) { AA = A; } 
-     AAResults *getAliasAnalysis() const { return AA; } 
-     void setMemDep(MemoryDependenceResults *M) { MD = M; } 
-     void setDomTree(DominatorTree *D) { DT = D; } 
-     uint32_t getNextUnusedValueNumber() { return nextValueNumber; } 
-     void verifyRemoved(const Value *) const; 
-   }; 
-   
- private: 
-   friend class gvn::GVNLegacyPass; 
-   friend struct DenseMapInfo<Expression>; 
-   
-   MemoryDependenceResults *MD = nullptr; 
-   DominatorTree *DT = nullptr; 
-   const TargetLibraryInfo *TLI = nullptr; 
-   AssumptionCache *AC = nullptr; 
-   SetVector<BasicBlock *> DeadBlocks; 
-   OptimizationRemarkEmitter *ORE = nullptr; 
-   ImplicitControlFlowTracking *ICF = nullptr; 
-   LoopInfo *LI = nullptr; 
-   MemorySSAUpdater *MSSAU = nullptr; 
-   
-   ValueTable VN; 
-   
-   /// A mapping from value numbers to lists of Value*'s that 
-   /// have that value number.  Use findLeader to query it. 
-   struct LeaderTableEntry { 
-     Value *Val; 
-     const BasicBlock *BB; 
-     LeaderTableEntry *Next; 
-   }; 
-   DenseMap<uint32_t, LeaderTableEntry> LeaderTable; 
-   BumpPtrAllocator TableAllocator; 
-   
-   // Block-local map of equivalent values to their leader, does not 
-   // propagate to any successors. Entries added mid-block are applied 
-   // to the remaining instructions in the block. 
-   SmallMapVector<Value *, Value *, 4> ReplaceOperandsWithMap; 
-   SmallVector<Instruction *, 8> InstrsToErase; 
-   
-   // Map the block to reversed postorder traversal number. It is used to 
-   // find back edge easily. 
-   DenseMap<AssertingVH<BasicBlock>, uint32_t> BlockRPONumber; 
-   
-   // This is set 'true' initially and also when new blocks have been added to 
-   // the function being analyzed. This boolean is used to control the updating 
-   // of BlockRPONumber prior to accessing the contents of BlockRPONumber. 
-   bool InvalidBlockRPONumbers = true; 
-   
-   using LoadDepVect = SmallVector<NonLocalDepResult, 64>; 
-   using AvailValInBlkVect = SmallVector<gvn::AvailableValueInBlock, 64>; 
-   using UnavailBlkVect = SmallVector<BasicBlock *, 64>; 
-   
-   bool runImpl(Function &F, AssumptionCache &RunAC, DominatorTree &RunDT, 
-                const TargetLibraryInfo &RunTLI, AAResults &RunAA, 
-                MemoryDependenceResults *RunMD, LoopInfo *LI, 
-                OptimizationRemarkEmitter *ORE, MemorySSA *MSSA = nullptr); 
-   
-   /// Push a new Value to the LeaderTable onto the list for its value number. 
-   void addToLeaderTable(uint32_t N, Value *V, const BasicBlock *BB) { 
-     LeaderTableEntry &Curr = LeaderTable[N]; 
-     if (!Curr.Val) { 
-       Curr.Val = V; 
-       Curr.BB = BB; 
-       return; 
-     } 
-   
-     LeaderTableEntry *Node = TableAllocator.Allocate<LeaderTableEntry>(); 
-     Node->Val = V; 
-     Node->BB = BB; 
-     Node->Next = Curr.Next; 
-     Curr.Next = Node; 
-   } 
-   
-   /// Scan the list of values corresponding to a given 
-   /// value number, and remove the given instruction if encountered. 
-   void removeFromLeaderTable(uint32_t N, Instruction *I, BasicBlock *BB) { 
-     LeaderTableEntry *Prev = nullptr; 
-     LeaderTableEntry *Curr = &LeaderTable[N]; 
-   
-     while (Curr && (Curr->Val != I || Curr->BB != BB)) { 
-       Prev = Curr; 
-       Curr = Curr->Next; 
-     } 
-   
-     if (!Curr) 
-       return; 
-   
-     if (Prev) { 
-       Prev->Next = Curr->Next; 
-     } else { 
-       if (!Curr->Next) { 
-         Curr->Val = nullptr; 
-         Curr->BB = nullptr; 
-       } else { 
-         LeaderTableEntry *Next = Curr->Next; 
-         Curr->Val = Next->Val; 
-         Curr->BB = Next->BB; 
-         Curr->Next = Next->Next; 
-       } 
-     } 
-   } 
-   
-   // List of critical edges to be split between iterations. 
-   SmallVector<std::pair<Instruction *, unsigned>, 4> toSplit; 
-   
-   // Helper functions of redundant load elimination 
-   bool processLoad(LoadInst *L); 
-   bool processNonLocalLoad(LoadInst *L); 
-   bool processAssumeIntrinsic(AssumeInst *II); 
-   
-   /// Given a local dependency (Def or Clobber) determine if a value is 
-   /// available for the load. 
-   std::optional<gvn::AvailableValue> 
-   AnalyzeLoadAvailability(LoadInst *Load, MemDepResult DepInfo, Value *Address); 
-   
-   /// Given a list of non-local dependencies, determine if a value is 
-   /// available for the load in each specified block.  If it is, add it to 
-   /// ValuesPerBlock.  If not, add it to UnavailableBlocks. 
-   void AnalyzeLoadAvailability(LoadInst *Load, LoadDepVect &Deps, 
-                                AvailValInBlkVect &ValuesPerBlock, 
-                                UnavailBlkVect &UnavailableBlocks); 
-   
-   bool PerformLoadPRE(LoadInst *Load, AvailValInBlkVect &ValuesPerBlock, 
-                       UnavailBlkVect &UnavailableBlocks); 
-   
-   /// Try to replace a load which executes on each loop iteraiton with Phi 
-   /// translation of load in preheader and load(s) in conditionally executed 
-   /// paths. 
-   bool performLoopLoadPRE(LoadInst *Load, AvailValInBlkVect &ValuesPerBlock, 
-                           UnavailBlkVect &UnavailableBlocks); 
-   
-   /// Eliminates partially redundant \p Load, replacing it with \p 
-   /// AvailableLoads (connected by Phis if needed). 
-   void eliminatePartiallyRedundantLoad( 
-       LoadInst *Load, AvailValInBlkVect &ValuesPerBlock, 
-       MapVector<BasicBlock *, Value *> &AvailableLoads); 
-   
-   // Other helper routines 
-   bool processInstruction(Instruction *I); 
-   bool processBlock(BasicBlock *BB); 
-   void dump(DenseMap<uint32_t, Value *> &d) const; 
-   bool iterateOnFunction(Function &F); 
-   bool performPRE(Function &F); 
-   bool performScalarPRE(Instruction *I); 
-   bool performScalarPREInsertion(Instruction *Instr, BasicBlock *Pred, 
-                                  BasicBlock *Curr, unsigned int ValNo); 
-   Value *findLeader(const BasicBlock *BB, uint32_t num); 
-   void cleanupGlobalSets(); 
-   void verifyRemoved(const Instruction *I) const; 
-   bool splitCriticalEdges(); 
-   BasicBlock *splitCriticalEdges(BasicBlock *Pred, BasicBlock *Succ); 
-   bool replaceOperandsForInBlockEquality(Instruction *I) const; 
-   bool propagateEquality(Value *LHS, Value *RHS, const BasicBlockEdge &Root, 
-                          bool DominatesByEdge); 
-   bool processFoldableCondBr(BranchInst *BI); 
-   void addDeadBlock(BasicBlock *BB); 
-   void assignValNumForDeadCode(); 
-   void assignBlockRPONumber(Function &F); 
- }; 
-   
- /// Create a legacy GVN pass. This also allows parameterizing whether or not 
- /// MemDep is enabled. 
- FunctionPass *createGVNPass(bool NoMemDepAnalysis = false); 
-   
- /// A simple and fast domtree-based GVN pass to hoist common expressions 
- /// from sibling branches. 
- struct GVNHoistPass : PassInfoMixin<GVNHoistPass> { 
-   /// Run the pass over the function. 
-   PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); 
- }; 
-   
- /// Uses an "inverted" value numbering to decide the similarity of 
- /// expressions and sinks similar expressions into successors. 
- struct GVNSinkPass : PassInfoMixin<GVNSinkPass> { 
-   /// Run the pass over the function. 
-   PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); 
- }; 
-   
- } // end namespace llvm 
-   
- #endif // LLVM_TRANSFORMS_SCALAR_GVN_H 
-