1 //===- PtrUseVisitor.h - InstVisitors over a pointers uses ------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 /// \file
10 /// This file provides a collection of visitors which walk the (instruction)
11 /// uses of a pointer. These visitors all provide the same essential behavior
12 /// as an InstVisitor with similar template-based flexibility and
13 /// implementation strategies.
14 ///
15 /// These can be used, for example, to quickly analyze the uses of an alloca,
16 /// global variable, or function argument.
17 ///
18 /// FIXME: Provide a variant which doesn't track offsets and is cheaper.
19 //
20 //===----------------------------------------------------------------------===//
21 
22 #ifndef LLVM_ANALYSIS_PTRUSEVISITOR_H
23 #define LLVM_ANALYSIS_PTRUSEVISITOR_H
24 
25 #include "llvm/ADT/APInt.h"
26 #include "llvm/ADT/PointerIntPair.h"
27 #include "llvm/ADT/SmallPtrSet.h"
28 #include "llvm/ADT/SmallVector.h"
29 #include "llvm/IR/DataLayout.h"
30 #include "llvm/IR/DerivedTypes.h"
31 #include "llvm/IR/InstVisitor.h"
32 #include "llvm/IR/Instruction.h"
33 #include "llvm/IR/Instructions.h"
34 #include "llvm/IR/IntrinsicInst.h"
35 #include "llvm/IR/Intrinsics.h"
36 #include "llvm/IR/Type.h"
37 #include "llvm/IR/Use.h"
38 #include "llvm/IR/User.h"
39 #include "llvm/Support/Casting.h"
40 #include <algorithm>
41 #include <cassert>
42 #include <type_traits>
43 
44 namespace llvm {
45 
46 namespace detail {
47 
48 /// Implementation of non-dependent functionality for \c PtrUseVisitor.
49 ///
50 /// See \c PtrUseVisitor for the public interface and detailed comments about
51 /// usage. This class is just a helper base class which is not templated and
52 /// contains all common code to be shared between different instantiations of
53 /// PtrUseVisitor.
54 class PtrUseVisitorBase {
55 public:
56   /// This class provides information about the result of a visit.
57   ///
58   /// After walking all the users (recursively) of a pointer, the basic
59   /// infrastructure records some commonly useful information such as escape
60   /// analysis and whether the visit completed or aborted early.
61   class PtrInfo {
62   public:
PtrInfo()63     PtrInfo() : AbortedInfo(nullptr, false), EscapedInfo(nullptr, false) {}
64 
65     /// Reset the pointer info, clearing all state.
reset()66     void reset() {
67       AbortedInfo.setPointer(nullptr);
68       AbortedInfo.setInt(false);
69       EscapedInfo.setPointer(nullptr);
70       EscapedInfo.setInt(false);
71     }
72 
73     /// Did we abort the visit early?
isAborted()74     bool isAborted() const { return AbortedInfo.getInt(); }
75 
76     /// Is the pointer escaped at some point?
isEscaped()77     bool isEscaped() const { return EscapedInfo.getInt(); }
78 
79     /// Get the instruction causing the visit to abort.
80     /// \returns a pointer to the instruction causing the abort if one is
81     /// available; otherwise returns null.
getAbortingInst()82     Instruction *getAbortingInst() const { return AbortedInfo.getPointer(); }
83 
84     /// Get the instruction causing the pointer to escape.
85     /// \returns a pointer to the instruction which escapes the pointer if one
86     /// is available; otherwise returns null.
getEscapingInst()87     Instruction *getEscapingInst() const { return EscapedInfo.getPointer(); }
88 
89     /// Mark the visit as aborted. Intended for use in a void return.
90     /// \param I The instruction which caused the visit to abort, if available.
91     void setAborted(Instruction *I = nullptr) {
92       AbortedInfo.setInt(true);
93       AbortedInfo.setPointer(I);
94     }
95 
96     /// Mark the pointer as escaped. Intended for use in a void return.
97     /// \param I The instruction which escapes the pointer, if available.
98     void setEscaped(Instruction *I = nullptr) {
99       EscapedInfo.setInt(true);
100       EscapedInfo.setPointer(I);
101     }
102 
103     /// Mark the pointer as escaped, and the visit as aborted. Intended
104     /// for use in a void return.
105     /// \param I The instruction which both escapes the pointer and aborts the
106     /// visit, if available.
107     void setEscapedAndAborted(Instruction *I = nullptr) {
108       setEscaped(I);
109       setAborted(I);
110     }
111 
112   private:
113     PointerIntPair<Instruction *, 1, bool> AbortedInfo, EscapedInfo;
114   };
115 
116 protected:
117   const DataLayout &DL;
118 
119   /// \name Visitation infrastructure
120   /// @{
121 
122   /// The info collected about the pointer being visited thus far.
123   PtrInfo PI;
124 
125   /// A struct of the data needed to visit a particular use.
126   ///
127   /// This is used to maintain a worklist fo to-visit uses. This is used to
128   /// make the visit be iterative rather than recursive.
129   struct UseToVisit {
130     using UseAndIsOffsetKnownPair = PointerIntPair<Use *, 1, bool>;
131 
132     UseAndIsOffsetKnownPair UseAndIsOffsetKnown;
133     APInt Offset;
134   };
135 
136   /// The worklist of to-visit uses.
137   SmallVector<UseToVisit, 8> Worklist;
138 
139   /// A set of visited uses to break cycles in unreachable code.
140   SmallPtrSet<Use *, 8> VisitedUses;
141 
142   /// @}
143 
144   /// \name Per-visit state
145   /// This state is reset for each instruction visited.
146   /// @{
147 
148   /// The use currently being visited.
149   Use *U;
150 
151   /// True if we have a known constant offset for the use currently
152   /// being visited.
153   bool IsOffsetKnown;
154 
155   /// The constant offset of the use if that is known.
156   APInt Offset;
157 
158   /// @}
159 
160   /// Note that the constructor is protected because this class must be a base
161   /// class, we can't create instances directly of this class.
PtrUseVisitorBase(const DataLayout & DL)162   PtrUseVisitorBase(const DataLayout &DL) : DL(DL) {}
163 
164   /// Enqueue the users of this instruction in the visit worklist.
165   ///
166   /// This will visit the users with the same offset of the current visit
167   /// (including an unknown offset if that is the current state).
168   void enqueueUsers(Instruction &I);
169 
170   /// Walk the operands of a GEP and adjust the offset as appropriate.
171   ///
172   /// This routine does the heavy lifting of the pointer walk by computing
173   /// offsets and looking through GEPs.
174   bool adjustOffsetForGEP(GetElementPtrInst &GEPI);
175 };
176 
177 } // end namespace detail
178 
179 /// A base class for visitors over the uses of a pointer value.
180 ///
181 /// Once constructed, a user can call \c visit on a pointer value, and this
182 /// will walk its uses and visit each instruction using an InstVisitor. It also
183 /// provides visit methods which will recurse through any pointer-to-pointer
184 /// transformations such as GEPs and bitcasts.
185 ///
186 /// During the visit, the current Use* being visited is available to the
187 /// subclass, as well as the current offset from the original base pointer if
188 /// known.
189 ///
190 /// The recursive visit of uses is accomplished with a worklist, so the only
191 /// ordering guarantee is that an instruction is visited before any uses of it
192 /// are visited. Note that this does *not* mean before any of its users are
193 /// visited! This is because users can be visited multiple times due to
194 /// multiple, different uses of pointers derived from the same base.
195 ///
196 /// A particular Use will only be visited once, but a User may be visited
197 /// multiple times, once per Use. This visits may notably have different
198 /// offsets.
199 ///
200 /// All visit methods on the underlying InstVisitor return a boolean. This
201 /// return short-circuits the visit, stopping it immediately.
202 ///
203 /// FIXME: Generalize this for all values rather than just instructions.
204 template <typename DerivedT>
205 class PtrUseVisitor : protected InstVisitor<DerivedT>,
206                       public detail::PtrUseVisitorBase {
207   friend class InstVisitor<DerivedT>;
208 
209   using Base = InstVisitor<DerivedT>;
210 
211 public:
PtrUseVisitor(const DataLayout & DL)212   PtrUseVisitor(const DataLayout &DL) : PtrUseVisitorBase(DL) {
213     static_assert(std::is_base_of<PtrUseVisitor, DerivedT>::value,
214                   "Must pass the derived type to this template!");
215   }
216 
217   /// Recursively visit the uses of the given pointer.
218   /// \returns An info struct about the pointer. See \c PtrInfo for details.
visitPtr(Instruction & I)219   PtrInfo visitPtr(Instruction &I) {
220     // This must be a pointer type. Get an integer type suitable to hold
221     // offsets on this pointer.
222     // FIXME: Support a vector of pointers.
223     assert(I.getType()->isPointerTy());
224     IntegerType *IntIdxTy = cast<IntegerType>(DL.getIndexType(I.getType()));
225     IsOffsetKnown = true;
226     Offset = APInt(IntIdxTy->getBitWidth(), 0);
227     PI.reset();
228 
229     // Enqueue the uses of this pointer.
230     enqueueUsers(I);
231 
232     // Visit all the uses off the worklist until it is empty.
233     while (!Worklist.empty()) {
234       UseToVisit ToVisit = Worklist.pop_back_val();
235       U = ToVisit.UseAndIsOffsetKnown.getPointer();
236       IsOffsetKnown = ToVisit.UseAndIsOffsetKnown.getInt();
237       if (IsOffsetKnown)
238         Offset = std::move(ToVisit.Offset);
239 
240       Instruction *I = cast<Instruction>(U->getUser());
241       static_cast<DerivedT*>(this)->visit(I);
242       if (PI.isAborted())
243         break;
244     }
245     return PI;
246   }
247 
248 protected:
visitStoreInst(StoreInst & SI)249   void visitStoreInst(StoreInst &SI) {
250     if (SI.getValueOperand() == U->get())
251       PI.setEscaped(&SI);
252   }
253 
visitBitCastInst(BitCastInst & BC)254   void visitBitCastInst(BitCastInst &BC) {
255     enqueueUsers(BC);
256   }
257 
visitAddrSpaceCastInst(AddrSpaceCastInst & ASC)258   void visitAddrSpaceCastInst(AddrSpaceCastInst &ASC) {
259     enqueueUsers(ASC);
260   }
261 
visitPtrToIntInst(PtrToIntInst & I)262   void visitPtrToIntInst(PtrToIntInst &I) {
263     PI.setEscaped(&I);
264   }
265 
visitGetElementPtrInst(GetElementPtrInst & GEPI)266   void visitGetElementPtrInst(GetElementPtrInst &GEPI) {
267     if (GEPI.use_empty())
268       return;
269 
270     // If we can't walk the GEP, clear the offset.
271     if (!adjustOffsetForGEP(GEPI)) {
272       IsOffsetKnown = false;
273       Offset = APInt();
274     }
275 
276     // Enqueue the users now that the offset has been adjusted.
277     enqueueUsers(GEPI);
278   }
279 
280   // No-op intrinsics which we know don't escape the pointer to logic in
281   // some other function.
visitDbgInfoIntrinsic(DbgInfoIntrinsic & I)282   void visitDbgInfoIntrinsic(DbgInfoIntrinsic &I) {}
visitMemIntrinsic(MemIntrinsic & I)283   void visitMemIntrinsic(MemIntrinsic &I) {}
visitIntrinsicInst(IntrinsicInst & II)284   void visitIntrinsicInst(IntrinsicInst &II) {
285     switch (II.getIntrinsicID()) {
286     default:
287       return Base::visitIntrinsicInst(II);
288 
289     case Intrinsic::lifetime_start:
290     case Intrinsic::lifetime_end:
291       return; // No-op intrinsics.
292     }
293   }
294 
295   // Generically, arguments to calls and invokes escape the pointer to some
296   // other function. Mark that.
visitCallBase(CallBase & CB)297   void visitCallBase(CallBase &CB) {
298     PI.setEscaped(&CB);
299     Base::visitCallBase(CB);
300   }
301 };
302 
303 } // end namespace llvm
304 
305 #endif // LLVM_ANALYSIS_PTRUSEVISITOR_H
306