LLVM 24.0.0git
GISelValueTracking.h
Go to the documentation of this file.
1//===- llvm/CodeGen/GlobalISel/GISelValueTracking.h -------------*- 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/// \file
9/// Provides analysis for querying information about KnownBits during GISel
10/// passes.
11///
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_CODEGEN_GLOBALISEL_GISELVALUETRACKING_H
15#define LLVM_CODEGEN_GLOBALISEL_GISELVALUETRACKING_H
16
17#include "llvm/ADT/APFloat.h"
18#include "llvm/ADT/DenseMap.h"
22#include "llvm/IR/InstrTypes.h"
23#include "llvm/IR/PassManager.h"
28
29namespace llvm {
30
31class TargetLowering;
32class DataLayout;
33
37 const TargetLowering &TL;
38 const DataLayout &DL;
39 unsigned MaxDepth;
40
41 // The triple (Register, DemandedElts, Depth) used as worklist and cache key.
42 using WorkItem = std::tuple<Register, APInt, unsigned>;
43 // Items pending evaluation during the active top-level query.
45 // Memoised results for the current top-level query.
47
48 void computeKnownBitsMin(Register Src0, Register Src1, KnownBits &Known,
49 const APInt &DemandedElts, unsigned Depth = 0);
50
51 unsigned computeNumSignBitsMin(Register Src0, Register Src1,
52 const APInt &DemandedElts, unsigned Depth = 0);
53
55 FPClassTest InterestedClasses, unsigned Depth);
56
58 const APInt &DemandedElts,
59 FPClassTest InterestedClasses,
60 KnownFPClass &Known, unsigned Depth);
61
62 void computeKnownFPClass(Register R, const APInt &DemandedElts,
63 FPClassTest InterestedClasses, KnownFPClass &Known,
64 unsigned Depth);
65
66 void computeKnownBits(Register R, KnownBits &Known, const APInt &DemandedElts,
67 unsigned Depth = 0);
68
69 bool getKnownBitsResult(Register Reg, const APInt &DemandedElts,
70 unsigned Depth, KnownBits &Known) {
71 auto It = Results.find({Reg, DemandedElts, Depth});
72 if (It == Results.end())
73 return false;
74 Known = It->second;
75 return true;
76 }
77
78 void setKnownBitsResult(Register Reg, const APInt &DemandedElts,
79 unsigned Depth, const KnownBits &Known) {
80 Results[{Reg, DemandedElts, Depth}] = Known;
81 }
82
83public:
84 GISelValueTracking(MachineFunction &MF, unsigned MaxDepth = 6);
85 ~GISelValueTracking() override = default;
86
87 const MachineFunction &getMachineFunction() const { return MF; }
88
89 const DataLayout &getDataLayout() const { return DL; }
90
91 void computeKnownBitsImpl(Register R, KnownBits &Known,
92 const APInt &DemandedElts, unsigned Depth = 0);
93
94 unsigned computeNumSignBits(Register R, const APInt &DemandedElts,
95 unsigned Depth = 0);
96 unsigned computeNumSignBits(Register R, unsigned Depth = 0);
97
98 // KnownBitsAPI
99 KnownBits getKnownBits(Register R);
100 KnownBits getKnownBits(Register R, const APInt &DemandedElts,
101 unsigned Depth = 0);
102
103 APInt getKnownZeroes(Register R);
104 APInt getKnownOnes(Register R);
105
106 /// \return true if 'V & Mask' is known to be zero in DemandedElts. We use
107 /// this predicate to simplify operations downstream.
108 /// Mask is known to be zero for bits that V cannot have.
109 bool maskedValueIsZero(Register Val, const APInt &Mask) {
110 return Mask.isSubsetOf(getKnownBits(Val).Zero);
111 }
112
113 /// \return true if the sign bit of Op is known to be zero. We use this
114 /// predicate to simplify operations downstream.
115 bool signBitIsZero(Register Op);
116
117 /// Return true if the value defined by \p R is provably never zero.
118 ///
119 /// \p DemandedElts selects the vector elements that must be proven nonzero.
120 /// For scalar values this is a one-bit mask. The overload without
121 /// \p DemandedElts demands every fixed-vector element, or the scalar value to
122 /// be non-zero.
123 bool isKnownNeverZero(Register R, unsigned Depth = 0);
124 bool isKnownNeverZero(Register R, const APInt &DemandedElts,
125 unsigned Depth = 0);
126
127 /// \return The known alignment for the pointer-like value \p R.
128 Align computeKnownAlignment(Register R, unsigned Depth = 0);
129
130 /// If a G_SHL/G_ASHR/G_LSHR node with shift operand \p R has shift amounts
131 /// that are all less than the element bit-width of the shift node, return the
132 /// valid constant range.
133 std::optional<ConstantRange>
134 getValidShiftAmountRange(Register R, const APInt &DemandedElts,
135 unsigned Depth);
136
137 /// If a G_SHL/G_ASHR/G_LSHR node with shift operand \p R has shift amounts
138 /// that are all less than the element bit-width of the shift node, return the
139 /// minimum possible value.
140 std::optional<uint64_t> getValidMinimumShiftAmount(Register R,
141 const APInt &DemandedElts,
142 unsigned Depth = 0);
143
144 /// Determine which floating-point classes are valid for \p V, and return them
145 /// in KnownFPClass bit sets.
146 ///
147 /// This function is defined on values with floating-point type, values
148 /// vectors of floating-point type, and arrays of floating-point type.
149
150 /// \p InterestedClasses is a compile time optimization hint for which
151 /// floating point classes should be queried. Queries not specified in \p
152 /// InterestedClasses should be reliable if they are determined during the
153 /// query.
154 KnownFPClass computeKnownFPClass(Register R, const APInt &DemandedElts,
155 FPClassTest InterestedClasses,
156 unsigned Depth);
157
159 FPClassTest InterestedClasses = fcAllFlags,
160 unsigned Depth = 0);
161
162 /// Wrapper to account for known fast math flags at the use instruction.
163 KnownFPClass computeKnownFPClass(Register R, const APInt &DemandedElts,
164 uint32_t Flags,
165 FPClassTest InterestedClasses,
166 unsigned Depth);
167
169 FPClassTest InterestedClasses,
170 unsigned Depth);
171
172 /// Returns true if \p Val can be assumed to never be a NaN. If \p SNaN is
173 /// true, this returns whether \p Val can be assumed to never be a signaling
174 /// NaN.
175 bool isKnownNeverNaN(Register Val, bool SNaN = false);
176
177 /// Returns true if \p Val can be assumed to never be a signaling NaN.
178 bool isKnownNeverSNaN(Register Val) { return isKnownNeverNaN(Val, true); }
179
180 /// Returns true if \p Val can be assumed to never be a zero, accounting for
181 /// denormal flushing of the containing function.
182 bool isKnownNeverLogicalZero(Register Val, unsigned Depth = 0);
183
184 // Observer API. No-op for non-caching implementation.
185 void erasingInstr(MachineInstr &MI) override {}
186 void createdInstr(MachineInstr &MI) override {}
187 void changingInstr(MachineInstr &MI) override {}
188 void changedInstr(MachineInstr &MI) override {}
189
190protected:
191 unsigned getMaxDepth() const { return MaxDepth; }
192};
193
194/// To use KnownBitsInfo analysis in a pass,
195/// KnownBitsInfo &Info = getAnalysis<GISelValueTrackingInfoAnalysis>().get(MF);
196/// Add to observer if the Info is caching.
197/// WrapperObserver.addObserver(Info);
198
199/// Eventually add other features such as caching/ser/deserializing
200/// to MIR etc. Those implementations can derive from GISelValueTracking
201/// and override computeKnownBitsImpl.
203 std::unique_ptr<GISelValueTracking> Info;
204
205public:
206 static char ID;
209 void getAnalysisUsage(AnalysisUsage &AU) const override;
210 bool runOnMachineFunction(MachineFunction &MF) override;
211 void releaseMemory() override { Info.reset(); }
212};
213
215 : public AnalysisInfoMixin<GISelValueTrackingAnalysis> {
217 LLVM_ABI static AnalysisKey Key;
218
219public:
221
224};
225
227 : public RequiredPassInfoMixin<GISelValueTrackingPrinterPass> {
228 raw_ostream &OS;
229
230public:
232
235};
236
238 : public RequiredPassInfoMixin<GISelValueTrackingFPClassPrinterPass> {
239 raw_ostream &OS;
240
241public:
243
246};
247} // namespace llvm
248
249#endif // LLVM_CODEGEN_GLOBALISEL_GISELVALUETRACKING_H
This file declares a class to represent arbitrary precision floating point values and provide a varie...
#define LLVM_ABI
Definition Compiler.h:215
This file defines the DenseMap class.
This contains common code to allow clients to notify changes to machine instr.
IRTranslator LLVM IR MI
This header defines various interfaces for pass management in LLVM.
Register Reg
static void computeKnownBits(const Value *V, const APInt &DemandedElts, KnownBits &Known, const SimplifyQuery &Q, unsigned Depth)
Determine which bits of V are known to be either zero or one and return them in the Known bit set.
void computeKnownFPClass(const Value *V, const APInt &DemandedElts, FPClassTest InterestedClasses, KnownFPClass &Known, const SimplifyQuery &Q, unsigned Depth)
static void computeKnownFPClassForFPTrunc(const Operator *Op, const APInt &DemandedElts, FPClassTest InterestedClasses, KnownFPClass &Known, const SimplifyQuery &Q, unsigned Depth)
Class for arbitrary precision integers.
Definition APInt.h:78
Represent the analysis usage information of a pass.
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:64
Abstract class that contains various methods for clients to notify about changes.
void releaseMemory() override
releaseMemory() - This member can be implemented by a pass if it wants to be able to release its memo...
LLVM_ABI Result run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
LLVM_ABI PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
LLVM_ABI PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
KnownBits getKnownBits(Register R)
void createdInstr(MachineInstr &MI) override
An instruction has been created and inserted into the function.
bool maskedValueIsZero(Register Val, const APInt &Mask)
bool isKnownNeverSNaN(Register Val)
Returns true if Val can be assumed to never be a signaling NaN.
const DataLayout & getDataLayout() const
const MachineFunction & getMachineFunction() const
void changedInstr(MachineInstr &MI) override
This instruction was mutated in some way.
void erasingInstr(MachineInstr &MI) override
An instruction is about to be erased.
bool isKnownNeverNaN(Register Val, bool SNaN=false)
Returns true if Val can be assumed to never be a NaN.
~GISelValueTracking() override=default
void changingInstr(MachineInstr &MI) override
This instruction is about to be mutated in some way.
GISelValueTracking(MachineFunction &MF, unsigned MaxDepth=6)
Representation of each machine instruction.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
Wrapper class representing virtual and physical registers.
Definition Register.h:20
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
This is an optimization pass for GlobalISel generic memory operations.
@ Known
Known to have no common set bits.
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
FPClassTest
Floating-point class tests, supported by 'is_fpclass' intrinsic.
DWARFExpression::Operation Op
LLVM_ABI bool isKnownNeverNaN(const Value *V, const SimplifyQuery &SQ, unsigned Depth=0)
Return true if the floating-point scalar value is not a NaN or if the floating-point vector value has...
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
A CRTP mix-in that provides informational APIs needed for analysis passes.
A special type used by analysis passes to provide an address that identifies that particular analysis...
Definition Analysis.h:29
A CRTP mix-in for passes that should not be skipped.