|
|
|||
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
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|