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