LLVM 24.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 // Pointer constants derived from equality predicates may have different
84 // provenance than the original value. Limit constant propagation if this
85 // happens to be the case.
86 bool MayHaveDifferentProvenance = false;
87
88 /// The union either stores a pointer to a constant or a constant range,
89 /// associated to the lattice element. We have to ensure that Range is
90 /// initialized or destroyed when changing state to or from constantrange.
91 union {
94 };
95
96 /// Destroy contents of lattice value, without destructing the object.
97 void destroy() {
98 switch (Tag) {
99 case overdefined:
100 case unknown:
101 case undef:
102 case constant:
103 case notconstant:
104 break;
105 case constantrange_including_undef:
106 case constantrange:
107 Range.~ConstantRange();
108 break;
109 };
110 }
111
112public:
113 /// Struct to control some aspects related to merging constant ranges.
115 /// The merge value may include undef.
117
118 /// Handle repeatedly extending a range by going to overdefined after a
119 /// number of steps.
121
122 /// The number of allowed widening steps (including setting the range
123 /// initially).
125
127
132
134 MayIncludeUndef = V;
135 return *this;
136 }
137
138 MergeOptions &setCheckWiden(bool V = true) {
139 CheckWiden = V;
140 return *this;
141 }
142
143 MergeOptions &setMaxWidenSteps(unsigned Steps = 1) {
144 CheckWiden = true;
145 MaxWidenSteps = Steps;
146 return *this;
147 }
148 };
149
150 // ConstVal and Range are initialized on-demand.
151 ValueLatticeElement() : Tag(unknown), NumRangeExtensions(0) {}
152
153 ~ValueLatticeElement() { destroy(); }
154
156 : Tag(Other.Tag), NumRangeExtensions(0),
157 MayHaveDifferentProvenance(Other.MayHaveDifferentProvenance) {
158 switch (Other.Tag) {
159 case constantrange:
160 case constantrange_including_undef:
161 new (&Range) ConstantRange(Other.Range);
162 NumRangeExtensions = Other.NumRangeExtensions;
163 break;
164 case constant:
165 case notconstant:
166 ConstVal = Other.ConstVal;
167 break;
168 case overdefined:
169 case unknown:
170 case undef:
171 break;
172 }
173 }
174
176 : Tag(Other.Tag), NumRangeExtensions(0),
177 MayHaveDifferentProvenance(Other.MayHaveDifferentProvenance) {
178 switch (Other.Tag) {
179 case constantrange:
180 case constantrange_including_undef:
181 new (&Range) ConstantRange(std::move(Other.Range));
182 NumRangeExtensions = Other.NumRangeExtensions;
183 break;
184 case constant:
185 case notconstant:
186 ConstVal = Other.ConstVal;
187 break;
188 case overdefined:
189 case unknown:
190 case undef:
191 break;
192 }
193 Other.Tag = unknown;
194 }
195
197 destroy();
198 new (this) ValueLatticeElement(Other);
199 return *this;
200 }
201
203 destroy();
204 new (this) ValueLatticeElement(std::move(Other));
205 return *this;
206 }
207
210 Res.markConstant(C);
211 return Res;
212 }
215 assert(!isa<UndefValue>(C) && "!= undef is not supported");
216 Res.markNotConstant(C);
217 return Res;
218 }
220 bool MayIncludeUndef = false) {
221 if (CR.isFullSet())
222 return getOverdefined();
223
224 if (CR.isEmptySet()) {
226 if (MayIncludeUndef)
227 Res.markUndef();
228 return Res;
229 }
230
232 Res.markConstantRange(std::move(CR),
233 MergeOptions().setMayIncludeUndef(MayIncludeUndef));
234 return Res;
235 }
238 Res.markOverdefined();
239 return Res;
240 }
241
242 bool isUndef() const { return Tag == undef; }
243 bool isUnknown() const { return Tag == unknown; }
244 bool isUnknownOrUndef() const { return Tag == unknown || Tag == undef; }
245 bool isConstant() const { return Tag == constant; }
246 bool isNotConstant() const { return Tag == notconstant; }
248 return Tag == constantrange_including_undef;
249 }
250 /// Returns true if this value is a constant range. Use \p UndefAllowed to
251 /// exclude non-singleton constant ranges that may also be undef. Note that
252 /// this function also returns true if the range may include undef, but only
253 /// contains a single element. In that case, it can be replaced by a constant.
254 bool isConstantRange(bool UndefAllowed = true) const {
255 return Tag == constantrange || (Tag == constantrange_including_undef &&
256 (UndefAllowed || Range.isSingleElement()));
257 }
258 bool isOverdefined() const { return Tag == overdefined; }
259
261 assert(isConstant() && "Cannot get the constant of a non-constant!");
262 return ConstVal;
263 }
264
266 assert(isNotConstant() && "Cannot get the constant of a non-notconstant!");
267 return ConstVal;
268 }
269
270 /// Returns the constant range for this value. Use \p UndefAllowed to exclude
271 /// non-singleton constant ranges that may also be undef. Note that this
272 /// function also returns a range if the range may include undef, but only
273 /// contains a single element. In that case, it can be replaced by a constant.
274 const ConstantRange &getConstantRange(bool UndefAllowed = true) const {
275 assert(isConstantRange(UndefAllowed) &&
276 "Cannot get the constant-range of a non-constant-range!");
277 return Range;
278 }
279
280 std::optional<APInt> asConstantInteger() const {
282 return cast<ConstantInt>(getConstant())->getValue();
283 } else if (isConstantRange() && getConstantRange().isSingleElement()) {
285 }
286 return std::nullopt;
287 }
288
289 ConstantRange asConstantRange(unsigned BW, bool UndefAllowed = false) const {
290 if (isConstantRange(UndefAllowed))
291 return getConstantRange();
292 if (isConstant())
293 return getConstant()->toConstantRange();
294 if (isUnknown())
295 return ConstantRange::getEmpty(BW);
296 return ConstantRange::getFull(BW);
297 }
298
299 ConstantRange asConstantRange(Type *Ty, bool UndefAllowed = false) const {
300 assert(Ty->isIntOrIntVectorTy() && "Must be integer type");
301 return asConstantRange(Ty->getScalarSizeInBits(), UndefAllowed);
302 }
303
305 if (isOverdefined())
306 return false;
307 destroy();
308 Tag = overdefined;
309 return true;
310 }
311
312 bool markUndef() {
313 if (isUndef())
314 return false;
315
316 assert(isUnknown());
317 Tag = undef;
318 return true;
319 }
320
321 bool markConstant(Constant *V, bool MayIncludeUndef = false) {
322 if (isa<UndefValue>(V))
323 return markUndef();
324
325 if (isConstant()) {
326 assert(getConstant() == V && "Marking constant with different value");
327 return false;
328 }
329
331 return markConstantRange(
332 ConstantRange(CI->getValue()),
333 MergeOptions().setMayIncludeUndef(MayIncludeUndef));
334
335 assert(isUnknown() || isUndef());
336 Tag = constant;
337 ConstVal = V;
338 return true;
339 }
340
342 assert(V && "Marking constant with NULL");
344 return markConstantRange(
345 ConstantRange(CI->getValue() + 1, CI->getValue()));
346
347 if (isa<UndefValue>(V))
348 return false;
349
350 if (isNotConstant()) {
351 assert(getNotConstant() == V && "Marking !constant with different value");
352 return false;
353 }
354
355 assert(isUnknown());
356 Tag = notconstant;
357 ConstVal = V;
358 return true;
359 }
360
361 /// Mark the object as constant range with \p NewR. If the object is already a
362 /// constant range, nothing changes if the existing range is equal to \p
363 /// NewR and the tag. Otherwise \p NewR must be a superset of the existing
364 /// range or the object must be undef. The tag is set to
365 /// constant_range_including_undef if either the existing value or the new
366 /// range may include undef.
368 MergeOptions Opts = MergeOptions()) {
369 assert(!NewR.isEmptySet() && "should only be called for non-empty sets");
370
371 if (NewR.isFullSet())
372 return markOverdefined();
373
374 ValueLatticeElementTy OldTag = Tag;
375 ValueLatticeElementTy NewTag =
376 (isUndef() || isConstantRangeIncludingUndef() || Opts.MayIncludeUndef)
377 ? constantrange_including_undef
378 : constantrange;
379 if (isConstantRange()) {
380 Tag = NewTag;
381 if (getConstantRange() == NewR)
382 return Tag != OldTag;
383
384 // Simple form of widening. If a range is extended multiple times, go to
385 // overdefined.
386 if (Opts.CheckWiden && ++NumRangeExtensions > Opts.MaxWidenSteps)
387 return markOverdefined();
388
390 "Existing range must be a subset of NewR");
391 Range = std::move(NewR);
392 return true;
393 }
394
395 assert(isUnknown() || isUndef() || isConstant());
396 assert((!isConstant() || NewR.contains(getConstant()->toConstantRange())) &&
397 "Constant must be subset of new range");
398
399 NumRangeExtensions = 0;
400 Tag = NewTag;
401 new (&Range) ConstantRange(std::move(NewR));
402 return true;
403 }
404
405 /// Updates this object to approximate both this object and RHS. Returns
406 /// true if this object has been changed.
408 MergeOptions Opts = MergeOptions()) {
409 if (RHS.isUnknown() || isOverdefined())
410 return false;
411 if (RHS.isOverdefined()) {
413 return true;
414 }
415
416 if (isUndef()) {
417 assert(!RHS.isUnknown());
418 if (RHS.isUndef())
419 return false;
420 if (RHS.isConstant())
421 return markConstant(RHS.getConstant(), true);
422 if (RHS.isConstantRange())
423 return markConstantRange(RHS.getConstantRange(true),
424 Opts.setMayIncludeUndef());
425 return markOverdefined();
426 }
427
428 if (isUnknown()) {
429 assert(!RHS.isUnknown() && "Unknow RHS should be handled earlier");
430 *this = RHS;
431 return true;
432 }
433
434 if (isConstant()) {
435 if (RHS.isConstant() && getConstant() == RHS.getConstant()) {
436 // Equal constants may still differ in provenance, propagate it when
437 // merging values.
438 bool Current = MayHaveDifferentProvenance;
439 MayHaveDifferentProvenance |= RHS.mayHaveDifferentProvenance();
440 return MayHaveDifferentProvenance != Current;
441 }
442 if (RHS.isUndef())
443 return false;
444 // If the constant is a vector of integers, try to treat it as a range.
445 if (getConstant()->getType()->isVectorTy() &&
446 getConstant()->getType()->getScalarType()->isIntegerTy()) {
448 ConstantRange NewR = L.unionWith(
449 RHS.asConstantRange(L.getBitWidth(), /*UndefAllowed=*/true));
450 return markConstantRange(
451 std::move(NewR),
452 Opts.setMayIncludeUndef(RHS.isConstantRangeIncludingUndef()));
453 }
455 return true;
456 }
457
458 if (isNotConstant()) {
459 if (RHS.isNotConstant() && getNotConstant() == RHS.getNotConstant())
460 return false;
462 return true;
463 }
464
465 auto OldTag = Tag;
466 assert(isConstantRange() && "New ValueLattice type?");
467 if (RHS.isUndef()) {
468 Tag = constantrange_including_undef;
469 return OldTag != Tag;
470 }
471
472 const ConstantRange &L = getConstantRange();
473 ConstantRange NewR = L.unionWith(
474 RHS.asConstantRange(L.getBitWidth(), /*UndefAllowed=*/true));
475 return markConstantRange(
476 std::move(NewR),
477 Opts.setMayIncludeUndef(RHS.isConstantRangeIncludingUndef()));
478 }
479
480 // Compares this symbolic value with Other using Pred and returns either
481 /// true, false or undef constants, or nullptr if the comparison cannot be
482 /// evaluated.
485 const DataLayout &DL) const;
486
487 /// Combine two sets of facts about the same value into a single set of
488 /// facts. Note that this method is not suitable for merging facts along
489 /// different paths in a CFG; that's what the mergeIn function is for. This
490 /// is for merging facts gathered about the same value at the same location
491 /// through two independent means.
492 /// Notes:
493 /// * This method does not promise to return the most precise possible lattice
494 /// value implied by A and B. It is allowed to return any lattice element
495 /// which is at least as strong as *either* A or B (unless our facts
496 /// conflict, see below).
497 /// * Due to unreachable code, the intersection of two lattice values could be
498 /// contradictory. If this happens, we return some valid lattice value so
499 /// as not confuse the rest of LVI. Ideally, we'd always return Undefined,
500 /// but we do not make this guarantee. TODO: This would be a useful
501 /// enhancement.
503 intersect(const ValueLatticeElement &Other) const;
504
505 unsigned getNumRangeExtensions() const { return NumRangeExtensions; }
506 void setNumRangeExtensions(unsigned N) { NumRangeExtensions = N; }
507
508 bool mayHaveDifferentProvenance() const { return MayHaveDifferentProvenance; }
509 void setMayHaveDifferentProvenance(bool V) { MayHaveDifferentProvenance = V; }
510};
511
512static_assert(sizeof(ValueLatticeElement) <= 40,
513 "size of ValueLatticeElement changed unexpectedly");
514
515LLVM_ABI raw_ostream &operator<<(raw_ostream &OS,
516 const ValueLatticeElement &Val);
517} // end namespace llvm
518#endif
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
#define LLVM_ABI
Definition Compiler.h:215
This file contains the declarations for the subclasses of Constant, which represent the different fla...
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
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:740
This is the shared class of boolean and integer constants.
Definition Constants.h:87
This class represents a range of values.
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.
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.
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:64
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
This class represents lattice values for constants.
bool markNotConstant(Constant *V)
static ValueLatticeElement getRange(ConstantRange CR, bool MayIncludeUndef=false)
void setMayHaveDifferentProvenance(bool V)
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
ValueLatticeElement(const ValueLatticeElement &Other)
static ValueLatticeElement getNot(Constant *C)
ConstantRange asConstantRange(unsigned BW, bool UndefAllowed=false) const
std::optional< APInt > asConstantInteger() const
ValueLatticeElement & operator=(const ValueLatticeElement &Other)
ValueLatticeElement(ValueLatticeElement &&Other)
void setNumRangeExtensions(unsigned N)
const ConstantRange & getConstantRange(bool UndefAllowed=true) const
Returns the constant range for this value.
bool isConstantRange(bool UndefAllowed=true) const
Returns true if this value is a constant range.
static ValueLatticeElement get(Constant *C)
unsigned getNumRangeExtensions() const
Constant * getNotConstant() const
LLVM_ABI ValueLatticeElement intersect(const ValueLatticeElement &Other) const
Combine two sets of facts about the same value into a single set of facts.
ConstantRange asConstantRange(Type *Ty, bool UndefAllowed=false) const
Constant * getConstant() const
bool mergeIn(const ValueLatticeElement &RHS, MergeOptions Opts=MergeOptions())
Updates this object to approximate both this object and RHS.
bool mayHaveDifferentProvenance() const
ValueLatticeElement & operator=(ValueLatticeElement &&Other)
bool markConstant(Constant *V, bool MayIncludeUndef=false)
static ValueLatticeElement getOverdefined()
bool markConstantRange(ConstantRange NewR, MergeOptions Opts=MergeOptions())
Mark the object as constant range with NewR.
This is an optimization pass for GlobalISel generic memory operations.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
@ Other
Any other memory.
Definition ModRef.h:68
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
#define N
Struct to control some aspects related to merging constant ranges.
bool MayIncludeUndef
The merge value may include undef.
MergeOptions & setMayIncludeUndef(bool V=true)
bool CheckWiden
Handle repeatedly extending a range by going to overdefined after a number of steps.
MergeOptions & setMaxWidenSteps(unsigned Steps=1)
MergeOptions & setCheckWiden(bool V=true)
MergeOptions(bool MayIncludeUndef, bool CheckWiden, unsigned MaxWidenSteps=1)
unsigned MaxWidenSteps
The number of allowed widening steps (including setting the range initially).