Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:44:44

0001 //===- SSAUpdater.h - Unstructured SSA Update Tool --------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 // This file declares the SSAUpdater class.
0010 //
0011 //===----------------------------------------------------------------------===//
0012 
0013 #ifndef LLVM_TRANSFORMS_UTILS_SSAUPDATER_H
0014 #define LLVM_TRANSFORMS_UTILS_SSAUPDATER_H
0015 
0016 #include "llvm/ADT/ArrayRef.h"
0017 #include "llvm/ADT/StringRef.h"
0018 #include <string>
0019 
0020 namespace llvm {
0021 
0022 class BasicBlock;
0023 class Instruction;
0024 class LoadInst;
0025 class PHINode;
0026 class DbgVariableRecord;
0027 template <typename T> class SmallVectorImpl;
0028 template <typename T> class SSAUpdaterTraits;
0029 class Type;
0030 class Use;
0031 class Value;
0032 class DbgValueInst;
0033 
0034 /// Helper class for SSA formation on a set of values defined in
0035 /// multiple blocks.
0036 ///
0037 /// This is used when code duplication or another unstructured
0038 /// transformation wants to rewrite a set of uses of one value with uses of a
0039 /// set of values.
0040 class SSAUpdater {
0041   friend class SSAUpdaterTraits<SSAUpdater>;
0042 
0043 private:
0044   /// This keeps track of which value to use on a per-block basis. When we
0045   /// insert PHI nodes, we keep track of them here.
0046   void *AV = nullptr;
0047 
0048   /// ProtoType holds the type of the values being rewritten.
0049   Type *ProtoType = nullptr;
0050 
0051   /// PHI nodes are given a name based on ProtoName.
0052   std::string ProtoName;
0053 
0054   /// If this is non-null, the SSAUpdater adds all PHI nodes that it creates to
0055   /// the vector.
0056   SmallVectorImpl<PHINode *> *InsertedPHIs;
0057 
0058 public:
0059   /// If InsertedPHIs is specified, it will be filled
0060   /// in with all PHI Nodes created by rewriting.
0061   explicit SSAUpdater(SmallVectorImpl<PHINode *> *InsertedPHIs = nullptr);
0062   SSAUpdater(const SSAUpdater &) = delete;
0063   SSAUpdater &operator=(const SSAUpdater &) = delete;
0064   ~SSAUpdater();
0065 
0066   /// Reset this object to get ready for a new set of SSA updates with
0067   /// type 'Ty'.
0068   ///
0069   /// PHI nodes get a name based on 'Name'.
0070   void Initialize(Type *Ty, StringRef Name);
0071 
0072   /// Indicate that a rewritten value is available in the specified block
0073   /// with the specified value.
0074   void AddAvailableValue(BasicBlock *BB, Value *V);
0075 
0076   /// Return true if the SSAUpdater already has a value for the specified
0077   /// block.
0078   bool HasValueForBlock(BasicBlock *BB) const;
0079 
0080   /// Return the value for the specified block if the SSAUpdater has one,
0081   /// otherwise return nullptr.
0082   Value *FindValueForBlock(BasicBlock *BB) const;
0083 
0084   /// Construct SSA form, materializing a value that is live at the end
0085   /// of the specified block.
0086   Value *GetValueAtEndOfBlock(BasicBlock *BB);
0087 
0088   /// Construct SSA form, materializing a value that is live in the
0089   /// middle of the specified block.
0090   ///
0091   /// \c GetValueInMiddleOfBlock is the same as \c GetValueAtEndOfBlock except
0092   /// in one important case: if there is a definition of the rewritten value
0093   /// after the 'use' in BB.  Consider code like this:
0094   ///
0095   /// \code
0096   ///      X1 = ...
0097   ///   SomeBB:
0098   ///      use(X)
0099   ///      X2 = ...
0100   ///      br Cond, SomeBB, OutBB
0101   /// \endcode
0102   ///
0103   /// In this case, there are two values (X1 and X2) added to the AvailableVals
0104   /// set by the client of the rewriter, and those values are both live out of
0105   /// their respective blocks.  However, the use of X happens in the *middle* of
0106   /// a block.  Because of this, we need to insert a new PHI node in SomeBB to
0107   /// merge the appropriate values, and this value isn't live out of the block.
0108   Value *GetValueInMiddleOfBlock(BasicBlock *BB);
0109 
0110   /// Rewrite a use of the symbolic value.
0111   ///
0112   /// This handles PHI nodes, which use their value in the corresponding
0113   /// predecessor. Note that this will not work if the use is supposed to be
0114   /// rewritten to a value defined in the same block as the use, but above it.
0115   /// Any 'AddAvailableValue's added for the use's block will be considered to
0116   /// be below it.
0117   void RewriteUse(Use &U);
0118 
0119   /// Rewrite debug value intrinsics to conform to a new SSA form.
0120   ///
0121   /// This will scout out all the debug value intrinsics associated with
0122   /// the instruction. Anything outside of its block will have its
0123   /// value set to the new SSA value if available, and undef if not.
0124   void UpdateDebugValues(Instruction *I);
0125   void UpdateDebugValues(Instruction *I,
0126                          SmallVectorImpl<DbgValueInst *> &DbgValues);
0127   void UpdateDebugValues(Instruction *I,
0128                          SmallVectorImpl<DbgVariableRecord *> &DbgValues);
0129 
0130   /// Rewrite a use like \c RewriteUse but handling in-block definitions.
0131   ///
0132   /// This version of the method can rewrite uses in the same block as
0133   /// a definition, because it assumes that all uses of a value are below any
0134   /// inserted values.
0135   void RewriteUseAfterInsertions(Use &U);
0136 
0137 private:
0138   Value *GetValueAtEndOfBlockInternal(BasicBlock *BB);
0139   void UpdateDebugValue(Instruction *I, DbgValueInst *DbgValue);
0140   void UpdateDebugValue(Instruction *I, DbgVariableRecord *DbgValue);
0141 };
0142 
0143 /// Helper class for promoting a collection of loads and stores into SSA
0144 /// Form using the SSAUpdater.
0145 ///
0146 /// This handles complexities that SSAUpdater doesn't, such as multiple loads
0147 /// and stores in one block.
0148 ///
0149 /// Clients of this class are expected to subclass this and implement the
0150 /// virtual methods.
0151 class LoadAndStorePromoter {
0152 protected:
0153   SSAUpdater &SSA;
0154 
0155 public:
0156   LoadAndStorePromoter(ArrayRef<const Instruction *> Insts,
0157                        SSAUpdater &S, StringRef Name = StringRef());
0158   virtual ~LoadAndStorePromoter() = default;
0159 
0160   /// This does the promotion.
0161   ///
0162   /// Insts is a list of loads and stores to promote, and Name is the basename
0163   /// for the PHIs to insert. After this is complete, the loads and stores are
0164   /// removed from the code.
0165   void run(const SmallVectorImpl<Instruction *> &Insts);
0166 
0167   /// This hook is invoked after all the stores are found and inserted as
0168   /// available values.
0169   virtual void doExtraRewritesBeforeFinalDeletion() {}
0170 
0171   /// Clients can choose to implement this to get notified right before
0172   /// a load is RAUW'd another value.
0173   virtual void replaceLoadWithValue(LoadInst *LI, Value *V) const {}
0174 
0175   /// Called before each instruction is deleted.
0176   virtual void instructionDeleted(Instruction *I) const {}
0177 
0178   /// Called to update debug info associated with the instruction.
0179   virtual void updateDebugInfo(Instruction *I) const {}
0180 
0181   /// Return false if a sub-class wants to keep one of the loads/stores
0182   /// after the SSA construction.
0183   virtual bool shouldDelete(Instruction *I) const { return true; }
0184 
0185   /// Return the value to use for the point in the code that the alloca is
0186   /// positioned. This will only be used if an Alloca is included in Insts,
0187   /// otherwise the value of a uninitialized load will be assumed to be poison.
0188   virtual Value *getValueToUseForAlloca(Instruction *AI) const {
0189     return nullptr;
0190   }
0191 };
0192 
0193 } // end namespace llvm
0194 
0195 #endif // LLVM_TRANSFORMS_UTILS_SSAUPDATER_H