LLVM 22.0.0git
ValueLattice.h
Go to the documentation of this file.
1//===- ValueLattice.h - Value constraint analysis ---------------*- 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#ifndef LLVM_ANALYSIS_VALUELATTICE_H
10#define LLVM_ANALYSIS_VALUELATTICE_H
11
13#include "llvm/IR/Constants.h"
15
16//===----------------------------------------------------------------------===//
17// ValueLatticeElement
18//===----------------------------------------------------------------------===//
19
20namespace llvm {
21
22/// This class represents lattice values for constants.
23///
24/// FIXME: This is basically just for bringup, this can be made a lot more rich
25/// in the future.
26///
28 enum ValueLatticeElementTy {
29 /// This Value has no known value yet. As a result, this implies the
30 /// producing instruction is dead. Caution: We use this as the starting
31 /// state in our local meet rules. In this usage, it's taken to mean
32 /// "nothing known yet".
33 /// Transition to any other state allowed.
34 unknown,
35
36 /// This Value is an UndefValue constant or produces undef. Undefined values
37 /// can be merged with constants (or single element constant ranges),
38 /// assuming all uses of the result will be replaced.
39 /// Transition allowed to the following states:
40 /// constant
41 /// constantrange_including_undef
42 /// overdefined
43 undef,
44
45 /// This Value has a specific constant value. The constant cannot be undef.
46 /// (For constant integers, constantrange is used instead. Integer typed
47 /// constantexprs can appear as constant.) Note that the constant state
48 /// can be reached by merging undef & constant states.
49 /// Transition allowed to the following states:
50 /// overdefined
51 constant,
52
53 /// This Value is known to not have the specified value. (For constant
54 /// integers, constantrange is used instead. As above, integer typed
55 /// constantexprs can appear here.)
56 /// Transition allowed to the following states:
57 /// overdefined
58 notconstant,
59
60 /// The Value falls within this range. (Used only for integer typed values.)
61 /// Transition allowed to the following states:
62 /// constantrange (new range must be a superset of the existing range)
63 /// constantrange_including_undef
64 /// overdefined
65 constantrange,
66
67 /// This Value falls within this range, but also may be undef.
68 /// Merging it with other constant ranges results in
69 /// constantrange_including_undef.
70 /// Transition allowed to the following states:
71 /// overdefined
72 constantrange_including_undef,
73
74 /// We can not precisely model the dynamic values this value might take.
75 /// No transitions are allowed after reaching overdefined.
76 overdefined,
77 };
78
79 ValueLatticeElementTy Tag : 8;
80 /// Number of times a constant range has been extended with widening enabled.
81 unsigned NumRangeExtensions : 8;
82
83 /// The union either stores a pointer to a constant or a constant range,
84 /// associated to the lattice element. We have to ensure that Range is
85 /// initialized or destroyed when changing state to or from constantrange.
86 union {
89 };
90
91 /// Destroy contents of lattice value, without destructing the object.
92 void destroy() {
93 switch (Tag) {
94 case overdefined:
95 case unknown:
96 case undef:
97 case constant:
98 case notconstant:
99 break;
100 case constantrange_including_undef:
101 case constantrange:
102 Range.~ConstantRange();
103 break;
104 };
105 }
106
107public:
108 /// Struct to control some aspects related to merging constant ranges.
110 /// The merge value may include undef.
112
113 /// Handle repeatedly extending a range by going to overdefined after a
114 /// number of steps.
116
117 /// The number of allowed widening steps (including setting the range
118 /// initially).
120
122
124 unsigned MaxWidenSteps = 1)
127
129 MayIncludeUndef = V;
130 return *this;
131 }
132
133 MergeOptions &setCheckWiden(bool V = true) {
134 CheckWiden = V;
135 return *this;
136 }
137
138 MergeOptions &setMaxWidenSteps(unsigned Steps = 1) {
139 CheckWiden = true;
140 MaxWidenSteps = Steps;
141 return *this;
142 }
143 };
144
145 // ConstVal and Range are initialized on-demand.
146 ValueLatticeElement() : Tag(unknown), NumRangeExtensions(0) {}
147
148 ~ValueLatticeElement() { destroy(); }
149
151 : Tag(Other.Tag), NumRangeExtensions(0) {
152 switch (Other.Tag) {
153 case constantrange:
154 case constantrange_including_undef:
155 new (&Range) ConstantRange(Other.Range);
156 NumRangeExtensions = Other.NumRangeExtensions;
157 break;
158 case constant:
159 case notconstant:
160 ConstVal = Other.ConstVal;
161 break;
162 case overdefined:
163 case unknown:
164 case undef:
165 break;
166 }
167 }
168
170 : Tag(Other.Tag), NumRangeExtensions(0) {
171 switch (Other.Tag) {
172 case constantrange:
173 case constantrange_including_undef:
174 new (&Range) ConstantRange(std::move(Other.Range));
175 NumRangeExtensions = Other.NumRangeExtensions;
176 break;
177 case constant:
178 case notconstant:
179 ConstVal = Other.ConstVal;
180 break;
181 case overdefined:
182 case unknown:
183 case undef:
184 break;
185 }
186 Other.Tag = unknown;
187 }
188
190 destroy();
191 new (this) ValueLatticeElement(Other);
192 return *this;
193 }
194
196 destroy();
197 new (this) ValueLatticeElement(std::move(Other));
198 return *this;
199 }
200
203 Res.markConstant(C);
204 return Res;
205 }
208 assert(!isa<UndefValue>(C) && "!= undef is not supported");
209 Res.markNotConstant(C);
210 return Res;
211 }
213 bool MayIncludeUndef = false) {
214 if (CR.isFullSet())
215 return getOverdefined();
216
217 if (CR.isEmptySet()) {
219 if (MayIncludeUndef)
220 Res.markUndef();
221 return Res;
222 }
223
225 Res.markConstantRange(std::move(CR),
226 MergeOptions().setMayIncludeUndef(MayIncludeUndef));
227 return Res;
228 }
231 Res.markOverdefined();
232 return Res;
233 }
234
235 bool isUndef() const { return Tag == undef; }
236 bool isUnknown() const { return Tag == unknown; }
237 bool isUnknownOrUndef() const { return Tag == unknown || Tag == undef; }
238 bool isConstant() const { return Tag == constant; }
239 bool isNotConstant() const { return Tag == notconstant; }
241 return Tag == constantrange_including_undef;
242 }
243 /// Returns true if this value is a constant range. Use \p UndefAllowed to
244 /// exclude non-singleton constant ranges that may also be undef. Note that
245 /// this function also returns true if the range may include undef, but only
246 /// contains a single element. In that case, it can be replaced by a constant.
247 bool isConstantRange(bool UndefAllowed = true) const {
248 return Tag == constantrange || (Tag == constantrange_including_undef &&
249 (UndefAllowed || Range.isSingleElement()));
250 }
251 bool isOverdefined() const { return Tag == overdefined; }
252
254 assert(isConstant() && "Cannot get the constant of a non-constant!");
255 return ConstVal;
256 }
257
259 assert(isNotConstant() && "Cannot get the constant of a non-notconstant!");
260 return ConstVal;
261 }
262
263 /// Returns the constant range for this value. Use \p UndefAllowed to exclude
264 /// non-singleton constant ranges that may also be undef. Note that this
265 /// function also returns a range if the range may include undef, but only
266 /// contains a single element. In that case, it can be replaced by a constant.
267 const ConstantRange &getConstantRange(bool UndefAllowed = true) const {
268 assert(isConstantRange(UndefAllowed) &&
269 "Cannot get the constant-range of a non-constant-range!");
270 return Range;
271 }
272
273 std::optional<APInt> asConstantInteger() const {
274 if (isConstant() && isa<ConstantInt>(getConstant())) {
275 return cast<ConstantInt>(getConstant())->getValue();
276 } else if (isConstantRange() && getConstantRange().isSingleElement()) {
278 }
279 return std::nullopt;
280 }
281
282 ConstantRange asConstantRange(unsigned BW, bool UndefAllowed = false) const {
283 if (isConstantRange(UndefAllowed))
284 return getConstantRange();
285 if (isConstant())
286 return getConstant()->toConstantRange();
287 if (isUnknown())
288 return ConstantRange::getEmpty(BW);
289 return ConstantRange::getFull(BW);
290 }
291
292 ConstantRange asConstantRange(Type *Ty, bool UndefAllowed = false) const {
293 assert(Ty->isIntOrIntVectorTy() && "Must be integer type");
294 return asConstantRange(Ty->getScalarSizeInBits(), UndefAllowed);
295 }
296
298 if (isOverdefined())
299 return false;
300 destroy();
301 Tag = overdefined;
302 return true;
303 }
304
305 bool markUndef() {
306 if (isUndef())
307 return false;
308
309 assert(isUnknown());
310 Tag = undef;
311 return true;
312 }
313
314 bool markConstant(Constant *V, bool MayIncludeUndef = false) {
315 if (isa<UndefValue>(V))
316 return markUndef();
317
318 if (isConstant()) {
319 assert(getConstant() == V && "Marking constant with different value");
320 return false;
321 }
322
323 if (ConstantInt *CI = dyn_cast<ConstantInt>(V))
324 return markConstantRange(
325 ConstantRange(CI->getValue()),
326 MergeOptions().setMayIncludeUndef(MayIncludeUndef));
327
328 assert(isUnknown() || isUndef());
329 Tag = constant;
330 ConstVal = V;
331 return true;
332 }
333
335 assert(V && "Marking constant with NULL");
336 if (ConstantInt *CI = dyn_cast<ConstantInt>(V))
337 return markConstantRange(
338 ConstantRange(CI->getValue() + 1, CI->getValue()));
339
340 if (isa<UndefValue>(V))
341 return false;
342
343 if (isNotConstant()) {
344 assert(getNotConstant() == V && "Marking !constant with different value");
345 return false;
346 }
347
348 assert(isUnknown());
349 Tag = notconstant;
350 ConstVal = V;
351 return true;
352 }
353
354 /// Mark the object as constant range with \p NewR. If the object is already a
355 /// constant range, nothing changes if the existing range is equal to \p
356 /// NewR and the tag. Otherwise \p NewR must be a superset of the existing
357 /// range or the object must be undef. The tag is set to
358 /// constant_range_including_undef if either the existing value or the new
359 /// range may include undef.
361 MergeOptions Opts = MergeOptions()) {
362 assert(!NewR.isEmptySet() && "should only be called for non-empty sets");
363
364 if (NewR.isFullSet())
365 return markOverdefined();
366
367 ValueLatticeElementTy OldTag = Tag;
368 ValueLatticeElementTy NewTag =
369 (isUndef() || isConstantRangeIncludingUndef() || Opts.MayIncludeUndef)
370 ? constantrange_including_undef
371 : constantrange;
372 if (isConstantRange()) {
373 Tag = NewTag;
374 if (getConstantRange() == NewR)
375 return Tag != OldTag;
376
377 // Simple form of widening. If a range is extended multiple times, go to
378 // overdefined.
379 if (Opts.CheckWiden && ++NumRangeExtensions > Opts.MaxWidenSteps)
380 return markOverdefined();
381
383 "Existing range must be a subset of NewR");
384 Range = std::move(NewR);
385 return true;
386 }
387
388 assert(isUnknown() || isUndef() || isConstant());
389 assert((!isConstant() || NewR.contains(getConstant()->toConstantRange())) &&
390 "Constant must be subset of new range");
391
392 NumRangeExtensions = 0;
393 Tag = NewTag;
394 new (&Range) ConstantRange(std::move(NewR));
395 return true;
396 }
397
398 /// Updates this object to approximate both this object and RHS. Returns
399 /// true if this object has been changed.
401 MergeOptions Opts = MergeOptions()) {
402 if (RHS.isUnknown() || isOverdefined())
403 return false;
404 if (RHS.isOverdefined()) {
406 return true;
407 }
408
409 if (isUndef()) {
410 assert(!RHS.isUnknown());
411 if (RHS.isUndef())
412 return false;
413 if (RHS.isConstant())
414 return markConstant(RHS.getConstant(), true);
415 if (RHS.isConstantRange())
416 return markConstantRange(RHS.getConstantRange(true),
417 Opts.setMayIncludeUndef());
418 return markOverdefined();
419 }
420
421 if (isUnknown()) {
422 assert(!RHS.isUnknown() && "Unknow RHS should be handled earlier");
423 *this = RHS;
424 return true;
425 }
426
427 if (isConstant()) {
428 if (RHS.isConstant() && getConstant() == RHS.getConstant())
429 return false;
430 if (RHS.isUndef())
431 return false;
432 // If the constant is a vector of integers, try to treat it as a range.
433 if (getConstant()->getType()->isVectorTy() &&
434 getConstant()->getType()->getScalarType()->isIntegerTy()) {
436 ConstantRange NewR = L.unionWith(
437 RHS.asConstantRange(L.getBitWidth(), /*UndefAllowed=*/true));
438 return markConstantRange(
439 std::move(NewR),
440 Opts.setMayIncludeUndef(RHS.isConstantRangeIncludingUndef()));
441 }
443 return true;
444 }
445
446 if (isNotConstant()) {
447 if (RHS.isNotConstant() && getNotConstant() == RHS.getNotConstant())
448 return false;
450 return true;
451 }
452
453 auto OldTag = Tag;
454 assert(isConstantRange() && "New ValueLattice type?");
455 if (RHS.isUndef()) {
456 Tag = constantrange_including_undef;
457 return OldTag != Tag;
458 }
459
460 const ConstantRange &L = getConstantRange();
461 ConstantRange NewR = L.unionWith(
462 RHS.asConstantRange(L.getBitWidth(), /*UndefAllowed=*/true));
463 return markConstantRange(
464 std::move(NewR),
465 Opts.setMayIncludeUndef(RHS.isConstantRangeIncludingUndef()));
466 }
467
468 // Compares this symbolic value with Other using Pred and returns either
469 /// true, false or undef constants, or nullptr if the comparison cannot be
470 /// evaluated.
473 const DataLayout &DL) const;
474
475 /// Combine two sets of facts about the same value into a single set of
476 /// facts. Note that this method is not suitable for merging facts along
477 /// different paths in a CFG; that's what the mergeIn function is for. This
478 /// is for merging facts gathered about the same value at the same location
479 /// through two independent means.
480 /// Notes:
481 /// * This method does not promise to return the most precise possible lattice
482 /// value implied by A and B. It is allowed to return any lattice element
483 /// which is at least as strong as *either* A or B (unless our facts
484 /// conflict, see below).
485 /// * Due to unreachable code, the intersection of two lattice values could be
486 /// contradictory. If this happens, we return some valid lattice value so
487 /// as not confuse the rest of LVI. Ideally, we'd always return Undefined,
488 /// but we do not make this guarantee. TODO: This would be a useful
489 /// enhancement.
491 intersect(const ValueLatticeElement &Other) const;
492
493 unsigned getNumRangeExtensions() const { return NumRangeExtensions; }
494 void setNumRangeExtensions(unsigned N) { NumRangeExtensions = N; }
495};
496
497static_assert(sizeof(ValueLatticeElement) <= 40,
498 "size of ValueLatticeElement changed unexpectedly");
499
500LLVM_ABI raw_ostream &operator<<(raw_ostream &OS,
501 const ValueLatticeElement &Val);
502} // end namespace llvm
503#endif
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
#define LLVM_ABI
Definition: Compiler.h:213
This file contains the declarations for the subclasses of Constant, which represent the different fla...
raw_pwrite_stream & OS
static SymbolRef::Type getType(const Symbol *Sym)
Definition: TapiFile.cpp:39
Value * RHS
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
Definition: InstrTypes.h:678
This is the shared class of boolean and integer constants.
Definition: Constants.h:87
This class represents a range of values.
Definition: ConstantRange.h:47
const APInt * getSingleElement() const
If this set contains a single element, return it, otherwise return null.
LLVM_ABI bool isFullSet() const
Return true if this set contains all of the elements possible for this data-type.
LLVM_ABI bool isEmptySet() const
Return true if this set contains no members.
bool isSingleElement() const
Return true if this set contains exactly one member.
LLVM_ABI bool contains(const APInt &Val) const
Return true if the specified value is in the set.
This is an important base class in LLVM.
Definition: Constant.h:43
LLVM_ABI ConstantRange toConstantRange() const
Convert constant to an approximate constant range.
Definition: Constants.cpp:1792
A parsed version of the target data layout string in and methods for querying it.
Definition: DataLayout.h:63
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
bool isIntOrIntVectorTy() const
Return true if this is an integer type or a vector of integer types.
Definition: Type.h:246
LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
This class represents lattice values for constants.
Definition: ValueLattice.h:27
bool markNotConstant(Constant *V)
Definition: ValueLattice.h:334
static ValueLatticeElement getRange(ConstantRange CR, bool MayIncludeUndef=false)
Definition: ValueLattice.h:212
LLVM_ABI Constant * getCompare(CmpInst::Predicate Pred, Type *Ty, const ValueLatticeElement &Other, const DataLayout &DL) const
true, false or undef constants, or nullptr if the comparison cannot be evaluated.
bool isConstantRangeIncludingUndef() const
Definition: ValueLattice.h:240
ValueLatticeElement(const ValueLatticeElement &Other)
Definition: ValueLattice.h:150
static ValueLatticeElement getNot(Constant *C)
Definition: ValueLattice.h:206
ConstantRange asConstantRange(unsigned BW, bool UndefAllowed=false) const
Definition: ValueLattice.h:282
std::optional< APInt > asConstantInteger() const
Definition: ValueLattice.h:273
ValueLatticeElement & operator=(const ValueLatticeElement &Other)
Definition: ValueLattice.h:189
ValueLatticeElement(ValueLatticeElement &&Other)
Definition: ValueLattice.h:169
void setNumRangeExtensions(unsigned N)
Definition: ValueLattice.h:494
const ConstantRange & getConstantRange(bool UndefAllowed=true) const
Returns the constant range for this value.
Definition: ValueLattice.h:267
bool isConstantRange(bool UndefAllowed=true) const
Returns true if this value is a constant range.
Definition: ValueLattice.h:247
static ValueLatticeElement get(Constant *C)
Definition: ValueLattice.h:201
unsigned getNumRangeExtensions() const
Definition: ValueLattice.h:493
Constant * getNotConstant() const
Definition: ValueLattice.h:258
LLVM_ABI ValueLatticeElement intersect(const ValueLatticeElement &Other) const
Combine two sets of facts about the same value into a single set of facts.
bool isUnknownOrUndef() const
Definition: ValueLattice.h:237
ConstantRange asConstantRange(Type *Ty, bool UndefAllowed=false) const
Definition: ValueLattice.h:292
Constant * getConstant() const
Definition: ValueLattice.h:253
bool mergeIn(const ValueLatticeElement &RHS, MergeOptions Opts=MergeOptions())
Updates this object to approximate both this object and RHS.
Definition: ValueLattice.h:400
ValueLatticeElement & operator=(ValueLatticeElement &&Other)
Definition: ValueLattice.h:195
bool markConstant(Constant *V, bool MayIncludeUndef=false)
Definition: ValueLattice.h:314
static ValueLatticeElement getOverdefined()
Definition: ValueLattice.h:229
bool markConstantRange(ConstantRange NewR, MergeOptions Opts=MergeOptions())
Mark the object as constant range with NewR.
Definition: ValueLattice.h:360
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Other
Any other memory.
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
Definition: APFixedPoint.h:312
#define N
Struct to control some aspects related to merging constant ranges.
Definition: ValueLattice.h:109
bool MayIncludeUndef
The merge value may include undef.
Definition: ValueLattice.h:111
MergeOptions & setMayIncludeUndef(bool V=true)
Definition: ValueLattice.h:128
bool CheckWiden
Handle repeatedly extending a range by going to overdefined after a number of steps.
Definition: ValueLattice.h:115
MergeOptions & setMaxWidenSteps(unsigned Steps=1)
Definition: ValueLattice.h:138
MergeOptions & setCheckWiden(bool V=true)
Definition: ValueLattice.h:133
MergeOptions(bool MayIncludeUndef, bool CheckWiden, unsigned MaxWidenSteps=1)
Definition: ValueLattice.h:123
unsigned MaxWidenSteps
The number of allowed widening steps (including setting the range initially).
Definition: ValueLattice.h:119