PtrUseVisitor.h 10 KB

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