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
22namespace llvm {
23struct SimplifyQuery;
24KnownBits computeKnownBits(const Value *V, unsigned Depth,
25 const SimplifyQuery &Q);
26
27template <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
46 void calculateKnownBits(const SimplifyQuery &Q) const {
47 Known = computeKnownBits(Pointer.getPointer(), 0, Q);
48 Pointer.setInt(true);
49 }
50
51public:
52 WithCache(PointerType Pointer) : Pointer(Pointer, false) {}
53 WithCache(PointerType Pointer, const KnownBits &Known)
54 : Pointer(Pointer, true), Known(Known) {}
55
56 [[nodiscard]] PointerType getValue() const { return Pointer.getPointer(); }
57
58 [[nodiscard]] const KnownBits &getKnownBits(const SimplifyQuery &Q) const {
59 if (!hasKnownBits())
60 calculateKnownBits(Q);
61 return Known;
62 }
63
64 [[nodiscard]] bool hasKnownBits() const { return Pointer.getInt(); }
65
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