blob: 108d08033ac3463eda8c143d4274576a76810bca [file] [log] [blame]
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001//===- ValueLattice.h - Value constraint analysis ---------------*- C++ -*-===//
2//
Andrew Walbran16937d02019-10-22 13:54:20 +01003// 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
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01006//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLVM_ANALYSIS_VALUELATTICE_H
10#define LLVM_ANALYSIS_VALUELATTICE_H
11
12#include "llvm/IR/ConstantRange.h"
13#include "llvm/IR/Constants.h"
Olivier Deprezf4ef2d02021-04-20 13:36:24 +020014#include "llvm/IR/Instructions.h"
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010015//
16//===----------------------------------------------------------------------===//
17// ValueLatticeElement
18//===----------------------------------------------------------------------===//
19
20/// This class represents lattice values for constants.
21///
22/// FIXME: This is basically just for bringup, this can be made a lot more rich
23/// in the future.
24///
25
26namespace llvm {
27class ValueLatticeElement {
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".
Olivier Deprezf4ef2d02021-04-20 13:36:24 +020033 /// Transition to any other state allowed.
34 unknown,
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010035
Olivier Deprezf4ef2d02021-04-20 13:36:24 +020036 /// 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
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010051 constant,
52
Olivier Deprezf4ef2d02021-04-20 13:36:24 +020053 /// This Value is known to not have the specified value. (For constant
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010054 /// integers, constantrange is used instead. As above, integer typed
55 /// constantexprs can appear here.)
Olivier Deprezf4ef2d02021-04-20 13:36:24 +020056 /// Transition allowed to the following states:
57 /// overdefined
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010058 notconstant,
59
60 /// The Value falls within this range. (Used only for integer typed values.)
Olivier Deprezf4ef2d02021-04-20 13:36:24 +020061 /// Transition allowed to the following states:
62 /// constantrange (new range must be a superset of the existing range)
63 /// constantrange_including_undef
64 /// overdefined
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010065 constantrange,
66
Olivier Deprezf4ef2d02021-04-20 13:36:24 +020067 /// 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
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010074 /// We can not precisely model the dynamic values this value might take.
Olivier Deprezf4ef2d02021-04-20 13:36:24 +020075 /// No transitions are allowed after reaching overdefined.
76 overdefined,
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010077 };
78
Olivier Deprezf4ef2d02021-04-20 13:36:24 +020079 ValueLatticeElementTy Tag : 8;
80 /// Number of times a constant range has been extended with widening enabled.
81 unsigned NumRangeExtensions : 8;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010082
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 {
87 Constant *ConstVal;
88 ConstantRange Range;
89 };
90
Olivier Deprezf4ef2d02021-04-20 13:36:24 +020091 /// Destroy contents of lattice value, without destructing the object.
92 void destroy() {
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010093 switch (Tag) {
94 case overdefined:
Olivier Deprezf4ef2d02021-04-20 13:36:24 +020095 case unknown:
96 case undef:
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010097 case constant:
98 case notconstant:
99 break;
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200100 case constantrange_including_undef:
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100101 case constantrange:
102 Range.~ConstantRange();
103 break;
104 };
105 }
106
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200107public:
108 /// Struct to control some aspects related to merging constant ranges.
109 struct MergeOptions {
110 /// The merge value may include undef.
111 bool MayIncludeUndef;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100112
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200113 /// Handle repeatedly extending a range by going to overdefined after a
114 /// number of steps.
115 bool CheckWiden;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100116
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200117 /// The number of allowed widening steps (including setting the range
118 /// initially).
119 unsigned MaxWidenSteps;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100120
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200121 MergeOptions() : MergeOptions(false, false) {}
122
123 MergeOptions(bool MayIncludeUndef, bool CheckWiden,
124 unsigned MaxWidenSteps = 1)
125 : MayIncludeUndef(MayIncludeUndef), CheckWiden(CheckWiden),
126 MaxWidenSteps(MaxWidenSteps) {}
127
128 MergeOptions &setMayIncludeUndef(bool V = true) {
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
150 ValueLatticeElement(const ValueLatticeElement &Other)
151 : Tag(Other.Tag), NumRangeExtensions(0) {
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100152 switch (Other.Tag) {
153 case constantrange:
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200154 case constantrange_including_undef:
155 new (&Range) ConstantRange(Other.Range);
156 NumRangeExtensions = Other.NumRangeExtensions;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100157 break;
158 case constant:
159 case notconstant:
160 ConstVal = Other.ConstVal;
161 break;
162 case overdefined:
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200163 case unknown:
164 case undef:
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100165 break;
166 }
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200167 }
168
169 ValueLatticeElement(ValueLatticeElement &&Other)
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
189 ValueLatticeElement &operator=(const ValueLatticeElement &Other) {
190 destroy();
191 new (this) ValueLatticeElement(Other);
192 return *this;
193 }
194
195 ValueLatticeElement &operator=(ValueLatticeElement &&Other) {
196 destroy();
197 new (this) ValueLatticeElement(std::move(Other));
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100198 return *this;
199 }
200
201 static ValueLatticeElement get(Constant *C) {
202 ValueLatticeElement Res;
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200203 if (isa<UndefValue>(C))
204 Res.markUndef();
205 else
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100206 Res.markConstant(C);
207 return Res;
208 }
209 static ValueLatticeElement getNot(Constant *C) {
210 ValueLatticeElement Res;
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200211 assert(!isa<UndefValue>(C) && "!= undef is not supported");
212 Res.markNotConstant(C);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100213 return Res;
214 }
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200215 static ValueLatticeElement getRange(ConstantRange CR,
216 bool MayIncludeUndef = false) {
217 if (CR.isFullSet())
218 return getOverdefined();
219
220 if (CR.isEmptySet()) {
221 ValueLatticeElement Res;
222 if (MayIncludeUndef)
223 Res.markUndef();
224 return Res;
225 }
226
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100227 ValueLatticeElement Res;
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200228 Res.markConstantRange(std::move(CR),
229 MergeOptions().setMayIncludeUndef(MayIncludeUndef));
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100230 return Res;
231 }
232 static ValueLatticeElement getOverdefined() {
233 ValueLatticeElement Res;
234 Res.markOverdefined();
235 return Res;
236 }
237
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200238 bool isUndef() const { return Tag == undef; }
239 bool isUnknown() const { return Tag == unknown; }
240 bool isUnknownOrUndef() const { return Tag == unknown || Tag == undef; }
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100241 bool isConstant() const { return Tag == constant; }
242 bool isNotConstant() const { return Tag == notconstant; }
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200243 bool isConstantRangeIncludingUndef() const {
244 return Tag == constantrange_including_undef;
245 }
246 /// Returns true if this value is a constant range. Use \p UndefAllowed to
247 /// exclude non-singleton constant ranges that may also be undef. Note that
248 /// this function also returns true if the range may include undef, but only
249 /// contains a single element. In that case, it can be replaced by a constant.
250 bool isConstantRange(bool UndefAllowed = true) const {
251 return Tag == constantrange || (Tag == constantrange_including_undef &&
252 (UndefAllowed || Range.isSingleElement()));
253 }
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100254 bool isOverdefined() const { return Tag == overdefined; }
255
256 Constant *getConstant() const {
257 assert(isConstant() && "Cannot get the constant of a non-constant!");
258 return ConstVal;
259 }
260
261 Constant *getNotConstant() const {
262 assert(isNotConstant() && "Cannot get the constant of a non-notconstant!");
263 return ConstVal;
264 }
265
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200266 /// Returns the constant range for this value. Use \p UndefAllowed to exclude
267 /// non-singleton constant ranges that may also be undef. Note that this
268 /// function also returns a range if the range may include undef, but only
269 /// contains a single element. In that case, it can be replaced by a constant.
270 const ConstantRange &getConstantRange(bool UndefAllowed = true) const {
271 assert(isConstantRange(UndefAllowed) &&
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100272 "Cannot get the constant-range of a non-constant-range!");
273 return Range;
274 }
275
276 Optional<APInt> asConstantInteger() const {
277 if (isConstant() && isa<ConstantInt>(getConstant())) {
278 return cast<ConstantInt>(getConstant())->getValue();
279 } else if (isConstantRange() && getConstantRange().isSingleElement()) {
280 return *getConstantRange().getSingleElement();
281 }
282 return None;
283 }
284
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200285 bool markOverdefined() {
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100286 if (isOverdefined())
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200287 return false;
288 destroy();
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100289 Tag = overdefined;
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200290 return true;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100291 }
292
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200293 bool markUndef() {
294 if (isUndef())
295 return false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100296
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200297 assert(isUnknown());
298 Tag = undef;
299 return true;
300 }
301
302 bool markConstant(Constant *V, bool MayIncludeUndef = false) {
303 if (isa<UndefValue>(V))
304 return markUndef();
305
306 if (isConstant()) {
307 assert(getConstant() == V && "Marking constant with different value");
308 return false;
309 }
310
311 if (ConstantInt *CI = dyn_cast<ConstantInt>(V))
312 return markConstantRange(
313 ConstantRange(CI->getValue()),
314 MergeOptions().setMayIncludeUndef(MayIncludeUndef));
315
316 assert(isUnknown() || isUndef());
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100317 Tag = constant;
318 ConstVal = V;
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200319 return true;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100320 }
321
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200322 bool markNotConstant(Constant *V) {
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100323 assert(V && "Marking constant with NULL");
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200324 if (ConstantInt *CI = dyn_cast<ConstantInt>(V))
325 return markConstantRange(
326 ConstantRange(CI->getValue() + 1, CI->getValue()));
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100327
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200328 if (isa<UndefValue>(V))
329 return false;
330
331 if (isNotConstant()) {
332 assert(getNotConstant() == V && "Marking !constant with different value");
333 return false;
334 }
335
336 assert(isUnknown());
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100337 Tag = notconstant;
338 ConstVal = V;
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200339 return true;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100340 }
341
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200342 /// Mark the object as constant range with \p NewR. If the object is already a
343 /// constant range, nothing changes if the existing range is equal to \p
344 /// NewR and the tag. Otherwise \p NewR must be a superset of the existing
345 /// range or the object must be undef. The tag is set to
346 /// constant_range_including_undef if either the existing value or the new
347 /// range may include undef.
348 bool markConstantRange(ConstantRange NewR,
349 MergeOptions Opts = MergeOptions()) {
350 assert(!NewR.isEmptySet() && "should only be called for non-empty sets");
351
352 if (NewR.isFullSet())
353 return markOverdefined();
354
355 ValueLatticeElementTy OldTag = Tag;
356 ValueLatticeElementTy NewTag =
357 (isUndef() || isConstantRangeIncludingUndef() || Opts.MayIncludeUndef)
358 ? constantrange_including_undef
359 : constantrange;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100360 if (isConstantRange()) {
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200361 Tag = NewTag;
362 if (getConstantRange() == NewR)
363 return Tag != OldTag;
364
365 // Simple form of widening. If a range is extended multiple times, go to
366 // overdefined.
367 if (Opts.CheckWiden && ++NumRangeExtensions > Opts.MaxWidenSteps)
368 return markOverdefined();
369
370 assert(NewR.contains(getConstantRange()) &&
371 "Existing range must be a subset of NewR");
372 Range = std::move(NewR);
373 return true;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100374 }
375
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200376 assert(isUnknown() || isUndef());
377
378 NumRangeExtensions = 0;
379 Tag = NewTag;
380 new (&Range) ConstantRange(std::move(NewR));
381 return true;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100382 }
383
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100384 /// Updates this object to approximate both this object and RHS. Returns
385 /// true if this object has been changed.
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200386 bool mergeIn(const ValueLatticeElement &RHS,
387 MergeOptions Opts = MergeOptions()) {
388 if (RHS.isUnknown() || isOverdefined())
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100389 return false;
390 if (RHS.isOverdefined()) {
391 markOverdefined();
392 return true;
393 }
394
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200395 if (isUndef()) {
396 assert(!RHS.isUnknown());
397 if (RHS.isUndef())
398 return false;
399 if (RHS.isConstant())
400 return markConstant(RHS.getConstant(), true);
401 if (RHS.isConstantRange())
402 return markConstantRange(RHS.getConstantRange(true),
403 Opts.setMayIncludeUndef());
404 return markOverdefined();
405 }
406
407 if (isUnknown()) {
408 assert(!RHS.isUnknown() && "Unknow RHS should be handled earlier");
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100409 *this = RHS;
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200410 return true;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100411 }
412
413 if (isConstant()) {
414 if (RHS.isConstant() && getConstant() == RHS.getConstant())
415 return false;
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200416 if (RHS.isUndef())
417 return false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100418 markOverdefined();
419 return true;
420 }
421
422 if (isNotConstant()) {
423 if (RHS.isNotConstant() && getNotConstant() == RHS.getNotConstant())
424 return false;
425 markOverdefined();
426 return true;
427 }
428
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200429 auto OldTag = Tag;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100430 assert(isConstantRange() && "New ValueLattice type?");
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200431 if (RHS.isUndef()) {
432 Tag = constantrange_including_undef;
433 return OldTag != Tag;
434 }
435
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100436 if (!RHS.isConstantRange()) {
437 // We can get here if we've encountered a constantexpr of integer type
438 // and merge it with a constantrange.
439 markOverdefined();
440 return true;
441 }
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200442
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100443 ConstantRange NewR = getConstantRange().unionWith(RHS.getConstantRange());
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200444 return markConstantRange(
445 std::move(NewR),
446 Opts.setMayIncludeUndef(RHS.isConstantRangeIncludingUndef()));
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100447 }
448
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200449 // Compares this symbolic value with Other using Pred and returns either
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100450 /// true, false or undef constants, or nullptr if the comparison cannot be
451 /// evaluated.
452 Constant *getCompare(CmpInst::Predicate Pred, Type *Ty,
453 const ValueLatticeElement &Other) const {
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200454 if (isUnknownOrUndef() || Other.isUnknownOrUndef())
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100455 return UndefValue::get(Ty);
456
457 if (isConstant() && Other.isConstant())
458 return ConstantExpr::getCompare(Pred, getConstant(), Other.getConstant());
459
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200460 if (ICmpInst::isEquality(Pred)) {
461 // not(C) != C => true, not(C) == C => false.
462 if ((isNotConstant() && Other.isConstant() &&
463 getNotConstant() == Other.getConstant()) ||
464 (isConstant() && Other.isNotConstant() &&
465 getConstant() == Other.getNotConstant()))
466 return Pred == ICmpInst::ICMP_NE
467 ? ConstantInt::getTrue(Ty) : ConstantInt::getFalse(Ty);
468 }
469
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100470 // Integer constants are represented as ConstantRanges with single
471 // elements.
472 if (!isConstantRange() || !Other.isConstantRange())
473 return nullptr;
474
475 const auto &CR = getConstantRange();
476 const auto &OtherCR = Other.getConstantRange();
477 if (ConstantRange::makeSatisfyingICmpRegion(Pred, OtherCR).contains(CR))
478 return ConstantInt::getTrue(Ty);
479 if (ConstantRange::makeSatisfyingICmpRegion(
480 CmpInst::getInversePredicate(Pred), OtherCR)
481 .contains(CR))
482 return ConstantInt::getFalse(Ty);
483
484 return nullptr;
485 }
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200486
487 unsigned getNumRangeExtensions() const { return NumRangeExtensions; }
488 void setNumRangeExtensions(unsigned N) { NumRangeExtensions = N; }
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100489};
490
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200491static_assert(sizeof(ValueLatticeElement) <= 40,
492 "size of ValueLatticeElement changed unexpectedly");
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100493
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200494raw_ostream &operator<<(raw_ostream &OS, const ValueLatticeElement &Val);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100495} // end namespace llvm
496#endif