Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:43:16

0001 //===- PtrUseVisitor.h - InstVisitors over a pointers uses ------*- 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 /// \file
0010 /// This file provides a collection of visitors which walk the (instruction)
0011 /// uses of a pointer. These visitors all provide the same essential behavior
0012 /// as an InstVisitor with similar template-based flexibility and
0013 /// implementation strategies.
0014 ///
0015 /// These can be used, for example, to quickly analyze the uses of an alloca,
0016 /// global variable, or function argument.
0017 ///
0018 /// FIXME: Provide a variant which doesn't track offsets and is cheaper.
0019 //
0020 //===----------------------------------------------------------------------===//
0021 
0022 #ifndef LLVM_ANALYSIS_PTRUSEVISITOR_H
0023 #define LLVM_ANALYSIS_PTRUSEVISITOR_H
0024 
0025 #include "llvm/ADT/APInt.h"
0026 #include "llvm/ADT/PointerIntPair.h"
0027 #include "llvm/ADT/SmallPtrSet.h"
0028 #include "llvm/ADT/SmallVector.h"
0029 #include "llvm/IR/DerivedTypes.h"
0030 #include "llvm/IR/InstVisitor.h"
0031 #include "llvm/IR/IntrinsicInst.h"
0032 #include <cassert>
0033 #include <type_traits>
0034 
0035 namespace llvm {
0036 class DataLayout;
0037 
0038 namespace detail {
0039 
0040 /// Implementation of non-dependent functionality for \c PtrUseVisitor.
0041 ///
0042 /// See \c PtrUseVisitor for the public interface and detailed comments about
0043 /// usage. This class is just a helper base class which is not templated and
0044 /// contains all common code to be shared between different instantiations of
0045 /// PtrUseVisitor.
0046 class PtrUseVisitorBase {
0047 public:
0048   /// This class provides information about the result of a visit.
0049   ///
0050   /// After walking all the users (recursively) of a pointer, the basic
0051   /// infrastructure records some commonly useful information such as escape
0052   /// analysis and whether the visit completed or aborted early.
0053   class PtrInfo {
0054   public:
0055     /// Reset the pointer info, clearing all state.
0056     void reset() {
0057       AbortedInfo = nullptr;
0058       EscapedInfo = nullptr;
0059     }
0060 
0061     /// Did we abort the visit early?
0062     bool isAborted() const { return AbortedInfo != nullptr; }
0063 
0064     /// Is the pointer escaped at some point?
0065     bool isEscaped() const { return EscapedInfo != nullptr; }
0066 
0067     /// Is the pointer escaped into a read-only nocapture call at some point?
0068     bool isEscapedReadOnly() const { return EscapedReadOnly != nullptr; }
0069 
0070     /// Get the instruction causing the visit to abort.
0071     /// \returns a pointer to the instruction causing the abort if one is
0072     /// available; otherwise returns null.
0073     Instruction *getAbortingInst() const { return AbortedInfo; }
0074 
0075     /// Get the instruction causing the pointer to escape.
0076     /// \returns a pointer to the instruction which escapes the pointer if one
0077     /// is available; otherwise returns null.
0078     Instruction *getEscapingInst() const { return EscapedInfo; }
0079 
0080     /// Get the instruction causing the pointer to escape which is a read-only
0081     /// nocapture call.
0082     Instruction *getEscapedReadOnlyInst() const { return EscapedReadOnly; }
0083 
0084     /// Mark the visit as aborted. Intended for use in a void return.
0085     /// \param I The instruction which caused the visit to abort, if available.
0086     void setAborted(Instruction *I) {
0087       assert(I && "Expected a valid pointer in setAborted");
0088       AbortedInfo = I;
0089     }
0090 
0091     /// Mark the pointer as escaped. Intended for use in a void return.
0092     /// \param I The instruction which escapes the pointer, if available.
0093     void setEscaped(Instruction *I) {
0094       assert(I && "Expected a valid pointer in setEscaped");
0095       EscapedInfo = I;
0096     }
0097 
0098     /// Mark the pointer as escaped into a readonly-nocapture call.
0099     void setEscapedReadOnly(Instruction *I) {
0100       assert(I && "Expected a valid pointer in setEscapedReadOnly");
0101       EscapedReadOnly = I;
0102     }
0103 
0104     /// Mark the pointer as escaped, and the visit as aborted. Intended
0105     /// for use in a void return.
0106     /// \param I The instruction which both escapes the pointer and aborts the
0107     /// visit, if available.
0108     void setEscapedAndAborted(Instruction *I) {
0109       setEscaped(I);
0110       setAborted(I);
0111     }
0112 
0113   private:
0114     Instruction *AbortedInfo = nullptr;
0115     Instruction *EscapedInfo = nullptr;
0116     Instruction *EscapedReadOnly = nullptr;
0117   };
0118 
0119 protected:
0120   const DataLayout &DL;
0121 
0122   /// \name Visitation infrastructure
0123   /// @{
0124 
0125   /// The info collected about the pointer being visited thus far.
0126   PtrInfo PI;
0127 
0128   /// A struct of the data needed to visit a particular use.
0129   ///
0130   /// This is used to maintain a worklist fo to-visit uses. This is used to
0131   /// make the visit be iterative rather than recursive.
0132   struct UseToVisit {
0133     using UseAndIsOffsetKnownPair = PointerIntPair<Use *, 1, bool>;
0134 
0135     UseAndIsOffsetKnownPair UseAndIsOffsetKnown;
0136     APInt Offset;
0137   };
0138 
0139   /// The worklist of to-visit uses.
0140   SmallVector<UseToVisit, 8> Worklist;
0141 
0142   /// A set of visited uses to break cycles in unreachable code.
0143   SmallPtrSet<Use *, 8> VisitedUses;
0144 
0145   /// @}
0146 
0147   /// \name Per-visit state
0148   /// This state is reset for each instruction visited.
0149   /// @{
0150 
0151   /// The use currently being visited.
0152   Use *U;
0153 
0154   /// True if we have a known constant offset for the use currently
0155   /// being visited.
0156   bool IsOffsetKnown;
0157 
0158   /// The constant offset of the use if that is known.
0159   APInt Offset;
0160 
0161   /// @}
0162 
0163   /// Note that the constructor is protected because this class must be a base
0164   /// class, we can't create instances directly of this class.
0165   PtrUseVisitorBase(const DataLayout &DL) : DL(DL) {}
0166 
0167   /// Enqueue the users of this instruction in the visit worklist.
0168   ///
0169   /// This will visit the users with the same offset of the current visit
0170   /// (including an unknown offset if that is the current state).
0171   void enqueueUsers(Value &I);
0172 
0173   /// Walk the operands of a GEP and adjust the offset as appropriate.
0174   ///
0175   /// This routine does the heavy lifting of the pointer walk by computing
0176   /// offsets and looking through GEPs.
0177   bool adjustOffsetForGEP(GetElementPtrInst &GEPI);
0178 };
0179 
0180 } // end namespace detail
0181 
0182 /// A base class for visitors over the uses of a pointer value.
0183 ///
0184 /// Once constructed, a user can call \c visit on a pointer value, and this
0185 /// will walk its uses and visit each instruction using an InstVisitor. It also
0186 /// provides visit methods which will recurse through any pointer-to-pointer
0187 /// transformations such as GEPs and bitcasts.
0188 ///
0189 /// During the visit, the current Use* being visited is available to the
0190 /// subclass, as well as the current offset from the original base pointer if
0191 /// known.
0192 ///
0193 /// The recursive visit of uses is accomplished with a worklist, so the only
0194 /// ordering guarantee is that an instruction is visited before any uses of it
0195 /// are visited. Note that this does *not* mean before any of its users are
0196 /// visited! This is because users can be visited multiple times due to
0197 /// multiple, different uses of pointers derived from the same base.
0198 ///
0199 /// A particular Use will only be visited once, but a User may be visited
0200 /// multiple times, once per Use. This visits may notably have different
0201 /// offsets.
0202 ///
0203 /// All visit methods on the underlying InstVisitor return a boolean. This
0204 /// return short-circuits the visit, stopping it immediately.
0205 ///
0206 /// FIXME: Generalize this for all values rather than just instructions.
0207 template <typename DerivedT>
0208 class PtrUseVisitor : protected InstVisitor<DerivedT>,
0209                       public detail::PtrUseVisitorBase {
0210   friend class InstVisitor<DerivedT>;
0211 
0212   using Base = InstVisitor<DerivedT>;
0213 
0214 public:
0215   PtrUseVisitor(const DataLayout &DL) : PtrUseVisitorBase(DL) {
0216     static_assert(std::is_base_of<PtrUseVisitor, DerivedT>::value,
0217                   "Must pass the derived type to this template!");
0218   }
0219 
0220   /// Recursively visit the uses of the given pointer.
0221   /// \returns An info struct about the pointer. See \c PtrInfo for details.
0222   /// We may also need to process Argument pointers, so the input uses is
0223   /// a common Value type.
0224   PtrInfo visitPtr(Value &I) {
0225     // This must be a pointer type. Get an integer type suitable to hold
0226     // offsets on this pointer.
0227     // FIXME: Support a vector of pointers.
0228     assert(I.getType()->isPointerTy());
0229     assert(isa<Instruction>(I) || isa<Argument>(I));
0230     IntegerType *IntIdxTy = cast<IntegerType>(DL.getIndexType(I.getType()));
0231     IsOffsetKnown = true;
0232     Offset = APInt(IntIdxTy->getBitWidth(), 0);
0233     PI.reset();
0234 
0235     // Enqueue the uses of this pointer.
0236     enqueueUsers(I);
0237 
0238     // Visit all the uses off the worklist until it is empty.
0239     while (!Worklist.empty()) {
0240       UseToVisit ToVisit = Worklist.pop_back_val();
0241       U = ToVisit.UseAndIsOffsetKnown.getPointer();
0242       IsOffsetKnown = ToVisit.UseAndIsOffsetKnown.getInt();
0243       if (IsOffsetKnown)
0244         Offset = std::move(ToVisit.Offset);
0245 
0246       Instruction *I = cast<Instruction>(U->getUser());
0247       static_cast<DerivedT*>(this)->visit(I);
0248       if (PI.isAborted())
0249         break;
0250     }
0251     return PI;
0252   }
0253 
0254 protected:
0255   void visitStoreInst(StoreInst &SI) {
0256     if (SI.getValueOperand() == U->get())
0257       PI.setEscaped(&SI);
0258   }
0259 
0260   void visitBitCastInst(BitCastInst &BC) {
0261     enqueueUsers(BC);
0262   }
0263 
0264   void visitAddrSpaceCastInst(AddrSpaceCastInst &ASC) {
0265     enqueueUsers(ASC);
0266   }
0267 
0268   void visitPtrToIntInst(PtrToIntInst &I) {
0269     PI.setEscaped(&I);
0270   }
0271 
0272   void visitGetElementPtrInst(GetElementPtrInst &GEPI) {
0273     if (GEPI.use_empty())
0274       return;
0275 
0276     // If we can't walk the GEP, clear the offset.
0277     if (!adjustOffsetForGEP(GEPI)) {
0278       IsOffsetKnown = false;
0279       Offset = APInt();
0280     }
0281 
0282     // Enqueue the users now that the offset has been adjusted.
0283     enqueueUsers(GEPI);
0284   }
0285 
0286   // No-op intrinsics which we know don't escape the pointer to logic in
0287   // some other function.
0288   void visitDbgInfoIntrinsic(DbgInfoIntrinsic &I) {}
0289   void visitMemIntrinsic(MemIntrinsic &I) {}
0290   void visitIntrinsicInst(IntrinsicInst &II) {
0291     switch (II.getIntrinsicID()) {
0292     default:
0293       return Base::visitIntrinsicInst(II);
0294 
0295     // We escape pointers used by a fake_use to prevent SROA from transforming
0296     // them.
0297     case Intrinsic::fake_use:
0298       PI.setEscaped(&II);
0299       return;
0300 
0301     case Intrinsic::lifetime_start:
0302     case Intrinsic::lifetime_end:
0303       return; // No-op intrinsics.
0304     }
0305   }
0306 
0307   // Generically, arguments to calls and invokes escape the pointer to some
0308   // other function. Mark that.
0309   void visitCallBase(CallBase &CB) {
0310     PI.setEscaped(&CB);
0311     Base::visitCallBase(CB);
0312   }
0313 };
0314 
0315 } // end namespace llvm
0316 
0317 #endif // LLVM_ANALYSIS_PTRUSEVISITOR_H