- //===------ VirtualInstruction.cpp ------------------------------*- 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 
- // 
- //===----------------------------------------------------------------------===// 
- // 
- // Tools for determining which instructions are within a statement and the 
- // nature of their operands. 
- // 
- //===----------------------------------------------------------------------===// 
-   
- #ifndef POLLY_SUPPORT_VIRTUALINSTRUCTION_H 
- #define POLLY_SUPPORT_VIRTUALINSTRUCTION_H 
-   
- #include "polly/ScopInfo.h" 
-   
- namespace polly { 
- using llvm::User; 
-   
- /// Determine the nature of a value's use within a statement. 
- /// 
- /// These are not always representable by llvm::Use. For instance, scalar write 
- /// MemoryAccesses do use a value, but are not associated with an instruction's 
- /// argument. 
- /// 
- /// Despite its name it is not tied to virtual instructions (although it works 
- /// fine with them), but to promote consistent handling of values used in 
- /// statements. 
- class VirtualUse final { 
- public: 
-   /// The different types of uses. Handling usually differentiates a lot between 
-   /// these; one can use a switch to handle each case (and get warned by the 
-   /// compiler if one is not handled). 
-   enum UseKind { 
-     // An llvm::Constant. 
-     Constant, 
-   
-     // An llvm::BasicBlock. 
-     Block, 
-   
-     // A value that can be generated using ScopExpander. 
-     Synthesizable, 
-   
-     // A load that always reads the same value throughout the SCoP (address and 
-     // the value located there a SCoP-invariant) and has been hoisted in front 
-     // of the SCoP. 
-     Hoisted, 
-   
-     // Definition before the SCoP and not synthesizable. Can be an instruction 
-     // outside the SCoP, a function argument or a global value. Whether there is 
-     // a scalar MemoryAccess in this statement for reading it depends on the 
-     // -polly-analyze-read-only-scalars switch. 
-     ReadOnly, 
-   
-     // A definition within the same statement. No MemoryAccess between 
-     // definition and use are necessary. 
-     Intra, 
-   
-     // Definition in another statement. There is a scalar MemoryAccess that 
-     // makes it available in this statement. 
-     Inter 
-   }; 
-   
- private: 
-   /// The statement where a value is used. 
-   ScopStmt *User; 
-   
-   /// The value that is used. 
-   Value *Val; 
-   
-   /// The type of value use. 
-   UseKind Kind; 
-   
-   /// The value represented as llvm::SCEV expression. 
-   const SCEV *ScevExpr; 
-   
-   /// If this is an inter-statement (or read-only) use, contains the 
-   /// MemoryAccess that makes the value available in this statement. In case of 
-   /// intra-statement uses, can contain a MemoryKind::Array access. In all other 
-   /// cases, it is a nullptr. 
-   MemoryAccess *InputMA; 
-   
-   VirtualUse(ScopStmt *User, Value *Val, UseKind Kind, const SCEV *ScevExpr, 
-              MemoryAccess *InputMA) 
-       : User(User), Val(Val), Kind(Kind), ScevExpr(ScevExpr), InputMA(InputMA) { 
-   } 
-   
- public: 
-   /// Get a VirtualUse for an llvm::Use. 
-   /// 
-   /// @param S       The Scop object. 
-   /// @param U       The llvm::Use the get information for. 
-   /// @param LI      The LoopInfo analysis. Needed to determine whether the 
-   ///                value is synthesizable. 
-   /// @param Virtual Whether to ignore existing MemoryAccess. 
-   /// 
-   /// @return The VirtualUse representing the same use as @p U. 
-   static VirtualUse create(Scop *S, const Use &U, LoopInfo *LI, bool Virtual); 
-   
-   /// Get a VirtualUse for uses within statements. 
-   /// 
-   /// It is assumed that the user is not a PHINode. Such uses are always 
-   /// VirtualUse::Inter unless in a regions statement. 
-   /// 
-   /// @param S         The Scop object. 
-   /// @param UserStmt  The statement in which @p Val is used. Can be nullptr, in 
-   ///                  which case it assumed that the statement has been 
-   ///                  removed, which is only possible if no instruction in it 
-   ///                  had side-effects or computes a value used by another 
-   ///                  statement. 
-   /// @param UserScope Loop scope in which the value is used. Needed to 
-   ///                  determine whether the value is synthesizable. 
-   /// @param Val       The value being used. 
-   /// @param Virtual   Whether to use (and prioritize over instruction location) 
-   ///                  information about MemoryAccesses. 
-   /// 
-   /// @return A VirtualUse object that gives information about @p Val's use in 
-   ///         @p UserStmt. 
-   static VirtualUse create(Scop *S, ScopStmt *UserStmt, Loop *UserScope, 
-                            Value *Val, bool Virtual); 
-   
-   static VirtualUse create(ScopStmt *UserStmt, Loop *UserScope, Value *Val, 
-                            bool Virtual) { 
-     return create(UserStmt->getParent(), UserStmt, UserScope, Val, Virtual); 
-   } 
-   
-   bool isConstant() const { return Kind == Constant; } 
-   bool isBlock() const { return Kind == Block; } 
-   bool isSynthesizable() const { return Kind == Synthesizable; } 
-   bool isHoisted() const { return Kind == Hoisted; } 
-   bool isReadOnly() const { return Kind == ReadOnly; } 
-   bool isIntra() const { return Kind == Intra; } 
-   bool isInter() const { return Kind == Inter; } 
-   
-   /// Return user statement. 
-   ScopStmt *getUser() const { return User; } 
-   
-   /// Return the used value. 
-   llvm::Value *getValue() const { return Val; } 
-   
-   /// Return the type of use. 
-   UseKind getKind() const { return Kind; } 
-   
-   /// Return the ScalarEvolution representation of @p Val. 
-   const SCEV *getScevExpr() const { return ScevExpr; } 
-   
-   /// Return the MemoryAccess that makes the value available in this statement, 
-   /// if any. 
-   MemoryAccess *getMemoryAccess() const { return InputMA; } 
-   
-   /// Print a description of this object. 
-   /// 
-   /// @param OS           Stream to print to. 
-   /// @param Reproducible If true, ensures that the output is stable between 
-   ///                     runs and is suitable to check in regression tests. 
-   ///                     This excludes printing e.g. pointer values. If false, 
-   ///                     the output should not be used for regression tests, 
-   ///                     but may contain more information useful in debugger 
-   ///                     sessions. 
-   void print(raw_ostream &OS, bool Reproducible = true) const; 
-   
- #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 
-   void dump() const; 
- #endif 
- }; 
-   
- /// An iterator for virtual operands. 
- class VirtualOperandIterator final { 
-   friend class VirtualInstruction; 
-   friend class VirtualUse; 
-   
-   using Self = VirtualOperandIterator; 
-   
-   ScopStmt *User; 
-   User::op_iterator U; 
-   
-   VirtualOperandIterator(ScopStmt *User, User::op_iterator U) 
-       : User(User), U(U) {} 
-   
- public: 
-   using iterator_category = std::forward_iterator_tag; 
-   using value_type = VirtualUse; 
-   using difference_type = std::ptrdiff_t; 
-   using pointer = value_type *; 
-   using reference = value_type &; 
-   
-   inline bool operator==(const Self &that) const { 
-     assert(this->User == that.User); 
-     return this->U == that.U; 
-   } 
-   
-   inline bool operator!=(const Self &that) const { 
-     assert(this->User == that.User); 
-     return this->U != that.U; 
-   } 
-   
-   VirtualUse operator*() const { 
-     return VirtualUse::create(User, User->getSurroundingLoop(), U->get(), true); 
-   } 
-   
-   Use *operator->() const { return U; } 
-   
-   Self &operator++() { 
-     U++; 
-     return *this; 
-   } 
-   
-   Self operator++(int) { 
-     Self tmp = *this; 
-     ++*this; 
-     return tmp; 
-   } 
- }; 
-   
- /// This class represents a "virtual instruction", an instruction in a ScopStmt, 
- /// effectively a ScopStmt/Instruction-pair. 
- /// 
- /// An instructions can be moved between statements (e.g. to avoid a scalar 
- /// dependency) and even can be contained in multiple statements (for instance, 
- /// to recompute a value instead of transferring it), hence 'virtual'. This 
- /// class is required to represent such instructions that are not in their 
- /// 'physical' location anymore. 
- /// 
- /// A statement can currently not contain the same instructions multiple times 
- /// (that is, from different loop iterations). Therefore, a 
- /// ScopStmt/Instruction-pair uniquely identifies a virtual instructions. 
- /// ScopStmt::getInstruction() can contain the same instruction multiple times, 
- /// but they necessarily compute the same value. 
- class VirtualInstruction final { 
-   friend class VirtualOperandIterator; 
-   friend struct llvm::DenseMapInfo<VirtualInstruction>; 
-   
- private: 
-   /// The statement this virtual instruction is in. 
-   ScopStmt *Stmt = nullptr; 
-   
-   /// The instruction of a statement. 
-   Instruction *Inst = nullptr; 
-   
- public: 
-   VirtualInstruction() {} 
-   
-   /// Create a new virtual instruction of an instruction @p Inst in @p Stmt. 
-   VirtualInstruction(ScopStmt *Stmt, Instruction *Inst) 
-       : Stmt(Stmt), Inst(Inst) { 
-     assert(Stmt && Inst); 
-   } 
-   
-   VirtualOperandIterator operand_begin() const { 
-     return VirtualOperandIterator(Stmt, Inst->op_begin()); 
-   } 
-   
-   VirtualOperandIterator operand_end() const { 
-     return VirtualOperandIterator(Stmt, Inst->op_end()); 
-   } 
-   
-   /// Returns a list of virtual operands. 
-   /// 
-   /// Virtual operands, like virtual instructions, need to encode the ScopStmt 
-   /// they are in. 
-   llvm::iterator_range<VirtualOperandIterator> operands() const { 
-     return {operand_begin(), operand_end()}; 
-   } 
-   
-   /// Return the SCoP everything is contained in. 
-   Scop *getScop() const { return Stmt->getParent(); } 
-   
-   /// Return the ScopStmt this virtual instruction is in. 
-   ScopStmt *getStmt() const { return Stmt; } 
-   
-   /// Return the instruction in the statement. 
-   Instruction *getInstruction() const { return Inst; } 
-   
-   /// Print a description of this object. 
-   /// 
-   /// @param OS           Stream to print to. 
-   /// @param Reproducible If true, ensures that the output is stable between 
-   ///                     runs and is suitable for checks in regression tests. 
-   ///                     This excludes printing e.g., pointer values. If false, 
-   ///                     the output should not be used for regression tests, 
-   ///                     but may contain more information useful in debugger 
-   ///                     sessions. 
-   void print(raw_ostream &OS, bool Reproducible = true) const; 
-   
- #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 
-   void dump() const; 
- #endif 
- }; 
-   
- static inline bool operator==(VirtualInstruction LHS, VirtualInstruction RHS) { 
-   return LHS.getStmt() == RHS.getStmt() && 
-          LHS.getInstruction() == RHS.getInstruction(); 
- } 
-   
- /// Find all reachable instructions and accesses. 
- /// 
- /// @param S              The SCoP to find everything reachable in. 
- /// @param LI             LoopInfo required for analysis. 
- /// @param UsedInsts[out] Receives all reachable instructions. 
- /// @param UsedAccs[out]  Receives all reachable accesses. 
- /// @param OnlyLocal      If non-nullptr, activates local mode: The SCoP is 
- ///                       assumed to consist only of this statement and is 
- ///                       conservatively correct. Does not require walking the 
- ///                       whole SCoP. 
- void markReachable(Scop *S, LoopInfo *LI, 
-                    DenseSet<VirtualInstruction> &UsedInsts, 
-                    DenseSet<MemoryAccess *> &UsedAccs, 
-                    ScopStmt *OnlyLocal = nullptr); 
- } // namespace polly 
-   
- namespace llvm { 
- /// Support VirtualInstructions in llvm::DenseMaps. 
- template <> struct DenseMapInfo<polly::VirtualInstruction> { 
- public: 
-   static bool isEqual(polly::VirtualInstruction LHS, 
-                       polly::VirtualInstruction RHS) { 
-     return DenseMapInfo<polly::ScopStmt *>::isEqual(LHS.getStmt(), 
-                                                     RHS.getStmt()) && 
-            DenseMapInfo<Instruction *>::isEqual(LHS.getInstruction(), 
-                                                 RHS.getInstruction()); 
-   } 
-   
-   static polly::VirtualInstruction getTombstoneKey() { 
-     polly::VirtualInstruction TombstoneKey; 
-     TombstoneKey.Stmt = DenseMapInfo<polly::ScopStmt *>::getTombstoneKey(); 
-     TombstoneKey.Inst = DenseMapInfo<Instruction *>::getTombstoneKey(); 
-     return TombstoneKey; 
-   } 
-   
-   static polly::VirtualInstruction getEmptyKey() { 
-     polly::VirtualInstruction EmptyKey; 
-     EmptyKey.Stmt = DenseMapInfo<polly::ScopStmt *>::getEmptyKey(); 
-     EmptyKey.Inst = DenseMapInfo<Instruction *>::getEmptyKey(); 
-     return EmptyKey; 
-   } 
-   
-   static unsigned getHashValue(polly::VirtualInstruction Val) { 
-     return DenseMapInfo<std::pair<polly::ScopStmt *, Instruction *>>:: 
-         getHashValue(std::make_pair(Val.getStmt(), Val.getInstruction())); 
-   } 
- }; 
- } // namespace llvm 
-   
- #endif /* POLLY_SUPPORT_VIRTUALINSTRUCTION_H */ 
-