1 //===- llvm/Analysis/WithCache.h - KnownBits cache for pointers -*- 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 // Store a pointer to any type along with the KnownBits information for it
10 // that is computed lazily (if required).
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_ANALYSIS_WITHCACHE_H
15 #define LLVM_ANALYSIS_WITHCACHE_H
16 
17 #include "llvm/ADT/PointerIntPair.h"
18 #include "llvm/IR/Value.h"
19 #include "llvm/Support/KnownBits.h"
20 #include <type_traits>
21 
22 namespace llvm {
23 struct SimplifyQuery;
24 KnownBits computeKnownBits(const Value *V, unsigned Depth,
25                            const SimplifyQuery &Q);
26 
27 template <typename Arg> class WithCache {
28   static_assert(std::is_pointer_v<Arg>, "WithCache requires a pointer type!");
29 
30   using UnderlyingType = std::remove_pointer_t<Arg>;
31   constexpr static bool IsConst = std::is_const_v<Arg>;
32 
33   template <typename T, bool Const>
34   using conditionally_const_t = std::conditional_t<Const, const T, T>;
35 
36   using PointerType = conditionally_const_t<UnderlyingType *, IsConst>;
37   using ReferenceType = conditionally_const_t<UnderlyingType &, IsConst>;
38 
39   // Store the presence of the KnownBits information in one of the bits of
40   // Pointer.
41   // true  -> present
42   // false -> absent
43   mutable PointerIntPair<PointerType, 1, bool> Pointer;
44   mutable KnownBits Known;
45 
calculateKnownBits(const SimplifyQuery & Q)46   void calculateKnownBits(const SimplifyQuery &Q) const {
47     Known = computeKnownBits(Pointer.getPointer(), 0, Q);
48     Pointer.setInt(true);
49   }
50 
51 public:
WithCache(PointerType Pointer)52   WithCache(PointerType Pointer) : Pointer(Pointer, false) {}
WithCache(PointerType Pointer,const KnownBits & Known)53   WithCache(PointerType Pointer, const KnownBits &Known)
54       : Pointer(Pointer, true), Known(Known) {}
55 
getValue()56   [[nodiscard]] PointerType getValue() const { return Pointer.getPointer(); }
57 
getKnownBits(const SimplifyQuery & Q)58   [[nodiscard]] const KnownBits &getKnownBits(const SimplifyQuery &Q) const {
59     if (!hasKnownBits())
60       calculateKnownBits(Q);
61     return Known;
62   }
63 
hasKnownBits()64   [[nodiscard]] bool hasKnownBits() const { return Pointer.getInt(); }
65 
PointerType()66   operator PointerType() const { return Pointer.getPointer(); }
67   PointerType operator->() const { return Pointer.getPointer(); }
68   ReferenceType operator*() const { return *Pointer.getPointer(); }
69 };
70 } // namespace llvm
71 
72 #endif
73