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 
12 #include "llvm/IR/Constants.h"
13 #include "llvm/IR/ConstantRange.h"
14 #include "llvm/IR/Instructions.h"
15 
16 //===----------------------------------------------------------------------===//
17 //                               ValueLatticeElement
18 //===----------------------------------------------------------------------===//
19 
20 namespace llvm {
21 
22 class Constant;
23 
24 /// This class represents lattice values for constants.
25 ///
26 /// FIXME: This is basically just for bringup, this can be made a lot more rich
27 /// in the future.
28 ///
29 class ValueLatticeElement {
30   enum ValueLatticeElementTy {
31     /// This Value has no known value yet.  As a result, this implies the
32     /// producing instruction is dead.  Caution: We use this as the starting
33     /// state in our local meet rules.  In this usage, it's taken to mean
34     /// "nothing known yet".
35     /// Transition to any other state allowed.
36     unknown,
37 
38     /// This Value is an UndefValue constant or produces undef. Undefined values
39     /// can be merged with constants (or single element constant ranges),
40     /// assuming all uses of the result will be replaced.
41     /// Transition allowed to the following states:
42     ///  constant
43     ///  constantrange_including_undef
44     ///  overdefined
45     undef,
46 
47     /// This Value has a specific constant value.  The constant cannot be undef.
48     /// (For constant integers, constantrange is used instead. Integer typed
49     /// constantexprs can appear as constant.) Note that the constant state
50     /// can be reached by merging undef & constant states.
51     /// Transition allowed to the following states:
52     ///  overdefined
53     constant,
54 
55     /// This Value is known to not have the specified value. (For constant
56     /// integers, constantrange is used instead.  As above, integer typed
57     /// constantexprs can appear here.)
58     /// Transition allowed to the following states:
59     ///  overdefined
60     notconstant,
61 
62     /// The Value falls within this range. (Used only for integer typed values.)
63     /// Transition allowed to the following states:
64     ///  constantrange (new range must be a superset of the existing range)
65     ///  constantrange_including_undef
66     ///  overdefined
67     constantrange,
68 
69     /// This Value falls within this range, but also may be undef.
70     /// Merging it with other constant ranges results in
71     /// constantrange_including_undef.
72     /// Transition allowed to the following states:
73     ///  overdefined
74     constantrange_including_undef,
75 
76     /// We can not precisely model the dynamic values this value might take.
77     /// No transitions are allowed after reaching overdefined.
78     overdefined,
79   };
80 
81   ValueLatticeElementTy Tag : 8;
82   /// Number of times a constant range has been extended with widening enabled.
83   unsigned NumRangeExtensions : 8;
84 
85   /// The union either stores a pointer to a constant or a constant range,
86   /// associated to the lattice element. We have to ensure that Range is
87   /// initialized or destroyed when changing state to or from constantrange.
88   union {
89     Constant *ConstVal;
90     ConstantRange Range;
91   };
92 
93   /// Destroy contents of lattice value, without destructing the object.
94   void destroy() {
95     switch (Tag) {
96     case overdefined:
97     case unknown:
98     case undef:
99     case constant:
100     case notconstant:
101       break;
102     case constantrange_including_undef:
103     case constantrange:
104       Range.~ConstantRange();
105       break;
106     };
107   }
108 
109 public:
110   /// Struct to control some aspects related to merging constant ranges.
111   struct MergeOptions {
112     /// The merge value may include undef.
113     bool MayIncludeUndef;
114 
115     /// Handle repeatedly extending a range by going to overdefined after a
116     /// number of steps.
117     bool CheckWiden;
118 
119     /// The number of allowed widening steps (including setting the range
120     /// initially).
121     unsigned MaxWidenSteps;
122 
123     MergeOptions() : MergeOptions(false, false) {}
124 
125     MergeOptions(bool MayIncludeUndef, bool CheckWiden,
126                  unsigned MaxWidenSteps = 1)
127         : MayIncludeUndef(MayIncludeUndef), CheckWiden(CheckWiden),
128           MaxWidenSteps(MaxWidenSteps) {}
129 
130     MergeOptions &setMayIncludeUndef(bool V = true) {
131       MayIncludeUndef = V;
132       return *this;
133     }
134 
135     MergeOptions &setCheckWiden(bool V = true) {
136       CheckWiden = V;
137       return *this;
138     }
139 
140     MergeOptions &setMaxWidenSteps(unsigned Steps = 1) {
141       CheckWiden = true;
142       MaxWidenSteps = Steps;
143       return *this;
144     }
145   };
146 
147   // ConstVal and Range are initialized on-demand.
148   ValueLatticeElement() : Tag(unknown), NumRangeExtensions(0) {}
149 
150   ~ValueLatticeElement() { destroy(); }
151 
152   ValueLatticeElement(const ValueLatticeElement &Other)
153       : Tag(Other.Tag), NumRangeExtensions(0) {
154     switch (Other.Tag) {
155     case constantrange:
156     case constantrange_including_undef:
157       new (&Range) ConstantRange(Other.Range);
158       NumRangeExtensions = Other.NumRangeExtensions;
159       break;
160     case constant:
161     case notconstant:
162       ConstVal = Other.ConstVal;
163       break;
164     case overdefined:
165     case unknown:
166     case undef:
167       break;
168     }
169   }
170 
171   ValueLatticeElement(ValueLatticeElement &&Other)
172       : Tag(Other.Tag), NumRangeExtensions(0) {
173     switch (Other.Tag) {
174     case constantrange:
175     case constantrange_including_undef:
176       new (&Range) ConstantRange(std::move(Other.Range));
177       NumRangeExtensions = Other.NumRangeExtensions;
178       break;
179     case constant:
180     case notconstant:
181       ConstVal = Other.ConstVal;
182       break;
183     case overdefined:
184     case unknown:
185     case undef:
186       break;
187     }
188     Other.Tag = unknown;
189   }
190 
191   ValueLatticeElement &operator=(const ValueLatticeElement &Other) {
192     destroy();
193     new (this) ValueLatticeElement(Other);
194     return *this;
195   }
196 
197   ValueLatticeElement &operator=(ValueLatticeElement &&Other) {
198     destroy();
199     new (this) ValueLatticeElement(std::move(Other));
200     return *this;
201   }
202 
203   static ValueLatticeElement get(Constant *C) {
204     ValueLatticeElement Res;
205     if (isa<UndefValue>(C))
206       Res.markUndef();
207     else
208       Res.markConstant(C);
209     return Res;
210   }
211   static ValueLatticeElement getNot(Constant *C) {
212     ValueLatticeElement Res;
213     assert(!isa<UndefValue>(C) && "!= undef is not supported");
214     Res.markNotConstant(C);
215     return Res;
216   }
217   static ValueLatticeElement getRange(ConstantRange CR,
218                                       bool MayIncludeUndef = false) {
219     if (CR.isFullSet())
220       return getOverdefined();
221 
222     if (CR.isEmptySet()) {
223       ValueLatticeElement Res;
224       if (MayIncludeUndef)
225         Res.markUndef();
226       return Res;
227     }
228 
229     ValueLatticeElement Res;
230     Res.markConstantRange(std::move(CR),
231                           MergeOptions().setMayIncludeUndef(MayIncludeUndef));
232     return Res;
233   }
234   static ValueLatticeElement getOverdefined() {
235     ValueLatticeElement Res;
236     Res.markOverdefined();
237     return Res;
238   }
239 
240   bool isUndef() const { return Tag == undef; }
241   bool isUnknown() const { return Tag == unknown; }
242   bool isUnknownOrUndef() const { return Tag == unknown || Tag == undef; }
243   bool isConstant() const { return Tag == constant; }
244   bool isNotConstant() const { return Tag == notconstant; }
245   bool isConstantRangeIncludingUndef() const {
246     return Tag == constantrange_including_undef;
247   }
248   /// Returns true if this value is a constant range. Use \p UndefAllowed to
249   /// exclude non-singleton constant ranges that may also be undef. Note that
250   /// this function also returns true if the range may include undef, but only
251   /// contains a single element. In that case, it can be replaced by a constant.
252   bool isConstantRange(bool UndefAllowed = true) const {
253     return Tag == constantrange || (Tag == constantrange_including_undef &&
254                                     (UndefAllowed || Range.isSingleElement()));
255   }
256   bool isOverdefined() const { return Tag == overdefined; }
257 
258   Constant *getConstant() const {
259     assert(isConstant() && "Cannot get the constant of a non-constant!");
260     return ConstVal;
261   }
262 
263   Constant *getNotConstant() const {
264     assert(isNotConstant() && "Cannot get the constant of a non-notconstant!");
265     return ConstVal;
266   }
267 
268   /// Returns the constant range for this value. Use \p UndefAllowed to exclude
269   /// non-singleton constant ranges that may also be undef. Note that this
270   /// function also returns a range if the range may include undef, but only
271   /// contains a single element. In that case, it can be replaced by a constant.
272   const ConstantRange &getConstantRange(bool UndefAllowed = true) const {
273     assert(isConstantRange(UndefAllowed) &&
274            "Cannot get the constant-range of a non-constant-range!");
275     return Range;
276   }
277 
278   Optional<APInt> asConstantInteger() const {
279     if (isConstant() && isa<ConstantInt>(getConstant())) {
280       return cast<ConstantInt>(getConstant())->getValue();
281     } else if (isConstantRange() && getConstantRange().isSingleElement()) {
282       return *getConstantRange().getSingleElement();
283     }
284     return None;
285   }
286 
287   bool markOverdefined() {
288     if (isOverdefined())
289       return false;
290     destroy();
291     Tag = overdefined;
292     return true;
293   }
294 
295   bool markUndef() {
296     if (isUndef())
297       return false;
298 
299     assert(isUnknown());
300     Tag = undef;
301     return true;
302   }
303 
304   bool markConstant(Constant *V, bool MayIncludeUndef = false) {
305     if (isa<UndefValue>(V))
306       return markUndef();
307 
308     if (isConstant()) {
309       assert(getConstant() == V && "Marking constant with different value");
310       return false;
311     }
312 
313     if (ConstantInt *CI = dyn_cast<ConstantInt>(V))
314       return markConstantRange(
315           ConstantRange(CI->getValue()),
316           MergeOptions().setMayIncludeUndef(MayIncludeUndef));
317 
318     assert(isUnknown() || isUndef());
319     Tag = constant;
320     ConstVal = V;
321     return true;
322   }
323 
324   bool markNotConstant(Constant *V) {
325     assert(V && "Marking constant with NULL");
326     if (ConstantInt *CI = dyn_cast<ConstantInt>(V))
327       return markConstantRange(
328           ConstantRange(CI->getValue() + 1, CI->getValue()));
329 
330     if (isa<UndefValue>(V))
331       return false;
332 
333     if (isNotConstant()) {
334       assert(getNotConstant() == V && "Marking !constant with different value");
335       return false;
336     }
337 
338     assert(isUnknown());
339     Tag = notconstant;
340     ConstVal = V;
341     return true;
342   }
343 
344   /// Mark the object as constant range with \p NewR. If the object is already a
345   /// constant range, nothing changes if the existing range is equal to \p
346   /// NewR and the tag. Otherwise \p NewR must be a superset of the existing
347   /// range or the object must be undef. The tag is set to
348   /// constant_range_including_undef if either the existing value or the new
349   /// range may include undef.
350   bool markConstantRange(ConstantRange NewR,
351                          MergeOptions Opts = MergeOptions()) {
352     assert(!NewR.isEmptySet() && "should only be called for non-empty sets");
353 
354     if (NewR.isFullSet())
355       return markOverdefined();
356 
357     ValueLatticeElementTy OldTag = Tag;
358     ValueLatticeElementTy NewTag =
359         (isUndef() || isConstantRangeIncludingUndef() || Opts.MayIncludeUndef)
360             ? constantrange_including_undef
361             : constantrange;
362     if (isConstantRange()) {
363       Tag = NewTag;
364       if (getConstantRange() == NewR)
365         return Tag != OldTag;
366 
367       // Simple form of widening. If a range is extended multiple times, go to
368       // overdefined.
369       if (Opts.CheckWiden && ++NumRangeExtensions > Opts.MaxWidenSteps)
370         return markOverdefined();
371 
372       assert(NewR.contains(getConstantRange()) &&
373              "Existing range must be a subset of NewR");
374       Range = std::move(NewR);
375       return true;
376     }
377 
378     assert(isUnknown() || isUndef());
379 
380     NumRangeExtensions = 0;
381     Tag = NewTag;
382     new (&Range) ConstantRange(std::move(NewR));
383     return true;
384   }
385 
386   /// Updates this object to approximate both this object and RHS. Returns
387   /// true if this object has been changed.
388   bool mergeIn(const ValueLatticeElement &RHS,
389                MergeOptions Opts = MergeOptions()) {
390     if (RHS.isUnknown() || isOverdefined())
391       return false;
392     if (RHS.isOverdefined()) {
393       markOverdefined();
394       return true;
395     }
396 
397     if (isUndef()) {
398       assert(!RHS.isUnknown());
399       if (RHS.isUndef())
400         return false;
401       if (RHS.isConstant())
402         return markConstant(RHS.getConstant(), true);
403       if (RHS.isConstantRange())
404         return markConstantRange(RHS.getConstantRange(true),
405                                  Opts.setMayIncludeUndef());
406       return markOverdefined();
407     }
408 
409     if (isUnknown()) {
410       assert(!RHS.isUnknown() && "Unknow RHS should be handled earlier");
411       *this = RHS;
412       return true;
413     }
414 
415     if (isConstant()) {
416       if (RHS.isConstant() && getConstant() == RHS.getConstant())
417         return false;
418       if (RHS.isUndef())
419         return false;
420       markOverdefined();
421       return true;
422     }
423 
424     if (isNotConstant()) {
425       if (RHS.isNotConstant() && getNotConstant() == RHS.getNotConstant())
426         return false;
427       markOverdefined();
428       return true;
429     }
430 
431     auto OldTag = Tag;
432     assert(isConstantRange() && "New ValueLattice type?");
433     if (RHS.isUndef()) {
434       Tag = constantrange_including_undef;
435       return OldTag != Tag;
436     }
437 
438     if (!RHS.isConstantRange()) {
439       // We can get here if we've encountered a constantexpr of integer type
440       // and merge it with a constantrange.
441       markOverdefined();
442       return true;
443     }
444 
445     ConstantRange NewR = getConstantRange().unionWith(RHS.getConstantRange());
446     return markConstantRange(
447         std::move(NewR),
448         Opts.setMayIncludeUndef(RHS.isConstantRangeIncludingUndef()));
449   }
450 
451   // Compares this symbolic value with Other using Pred and returns either
452   /// true, false or undef constants, or nullptr if the comparison cannot be
453   /// evaluated.
454   Constant *getCompare(CmpInst::Predicate Pred, Type *Ty,
455                        const ValueLatticeElement &Other) const {
456     if (isUnknownOrUndef() || Other.isUnknownOrUndef())
457       return UndefValue::get(Ty);
458 
459     if (isConstant() && Other.isConstant())
460       return ConstantExpr::getCompare(Pred, getConstant(), Other.getConstant());
461 
462     if (ICmpInst::isEquality(Pred)) {
463       // not(C) != C => true, not(C) == C => false.
464       if ((isNotConstant() && Other.isConstant() &&
465            getNotConstant() == Other.getConstant()) ||
466           (isConstant() && Other.isNotConstant() &&
467            getConstant() == Other.getNotConstant()))
468         return Pred == ICmpInst::ICMP_NE
469             ? ConstantInt::getTrue(Ty) : ConstantInt::getFalse(Ty);
470     }
471 
472     // Integer constants are represented as ConstantRanges with single
473     // elements.
474     if (!isConstantRange() || !Other.isConstantRange())
475       return nullptr;
476 
477     const auto &CR = getConstantRange();
478     const auto &OtherCR = Other.getConstantRange();
479     if (CR.icmp(Pred, OtherCR))
480       return ConstantInt::getTrue(Ty);
481     if (CR.icmp(CmpInst::getInversePredicate(Pred), OtherCR))
482       return ConstantInt::getFalse(Ty);
483 
484     return nullptr;
485   }
486 
487   unsigned getNumRangeExtensions() const { return NumRangeExtensions; }
488   void setNumRangeExtensions(unsigned N) { NumRangeExtensions = N; }
489 };
490 
491 static_assert(sizeof(ValueLatticeElement) <= 40,
492               "size of ValueLatticeElement changed unexpectedly");
493 
494 raw_ostream &operator<<(raw_ostream &OS, const ValueLatticeElement &Val);
495 } // end namespace llvm
496 #endif
497