Home | History | Annotate | Line # | Download | only in Analysis
      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/ConstantRange.h"
     13 #include "llvm/IR/Constants.h"
     14 #include "llvm/IR/Instructions.h"
     15 //
     16 //===----------------------------------------------------------------------===//
     17 //                               ValueLatticeElement
     18 //===----------------------------------------------------------------------===//
     19 
     20 namespace 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 ///
     27 class 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".
     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 {
     87     Constant *ConstVal;
     88     ConstantRange Range;
     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 
    107 public:
    108   /// Struct to control some aspects related to merging constant ranges.
    109   struct MergeOptions {
    110     /// The merge value may include undef.
    111     bool MayIncludeUndef;
    112 
    113     /// Handle repeatedly extending a range by going to overdefined after a
    114     /// number of steps.
    115     bool CheckWiden;
    116 
    117     /// The number of allowed widening steps (including setting the range
    118     /// initially).
    119     unsigned MaxWidenSteps;
    120 
    121     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) {
    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 
    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));
    198     return *this;
    199   }
    200 
    201   static ValueLatticeElement get(Constant *C) {
    202     ValueLatticeElement Res;
    203     if (isa<UndefValue>(C))
    204       Res.markUndef();
    205     else
    206       Res.markConstant(C);
    207     return Res;
    208   }
    209   static ValueLatticeElement getNot(Constant *C) {
    210     ValueLatticeElement Res;
    211     assert(!isa<UndefValue>(C) && "!= undef is not supported");
    212     Res.markNotConstant(C);
    213     return Res;
    214   }
    215   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 
    227     ValueLatticeElement Res;
    228     Res.markConstantRange(std::move(CR),
    229                           MergeOptions().setMayIncludeUndef(MayIncludeUndef));
    230     return Res;
    231   }
    232   static ValueLatticeElement getOverdefined() {
    233     ValueLatticeElement Res;
    234     Res.markOverdefined();
    235     return Res;
    236   }
    237 
    238   bool isUndef() const { return Tag == undef; }
    239   bool isUnknown() const { return Tag == unknown; }
    240   bool isUnknownOrUndef() const { return Tag == unknown || Tag == undef; }
    241   bool isConstant() const { return Tag == constant; }
    242   bool isNotConstant() const { return Tag == notconstant; }
    243   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   }
    254   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 
    266   /// 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) &&
    272            "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 
    285   bool markOverdefined() {
    286     if (isOverdefined())
    287       return false;
    288     destroy();
    289     Tag = overdefined;
    290     return true;
    291   }
    292 
    293   bool markUndef() {
    294     if (isUndef())
    295       return false;
    296 
    297     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());
    317     Tag = constant;
    318     ConstVal = V;
    319     return true;
    320   }
    321 
    322   bool markNotConstant(Constant *V) {
    323     assert(V && "Marking constant with NULL");
    324     if (ConstantInt *CI = dyn_cast<ConstantInt>(V))
    325       return markConstantRange(
    326           ConstantRange(CI->getValue() + 1, CI->getValue()));
    327 
    328     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());
    337     Tag = notconstant;
    338     ConstVal = V;
    339     return true;
    340   }
    341 
    342   /// 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;
    360     if (isConstantRange()) {
    361       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;
    374     }
    375 
    376     assert(isUnknown() || isUndef());
    377 
    378     NumRangeExtensions = 0;
    379     Tag = NewTag;
    380     new (&Range) ConstantRange(std::move(NewR));
    381     return true;
    382   }
    383 
    384   /// Updates this object to approximate both this object and RHS. Returns
    385   /// true if this object has been changed.
    386   bool mergeIn(const ValueLatticeElement &RHS,
    387                MergeOptions Opts = MergeOptions()) {
    388     if (RHS.isUnknown() || isOverdefined())
    389       return false;
    390     if (RHS.isOverdefined()) {
    391       markOverdefined();
    392       return true;
    393     }
    394 
    395     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");
    409       *this = RHS;
    410       return true;
    411     }
    412 
    413     if (isConstant()) {
    414       if (RHS.isConstant() && getConstant() == RHS.getConstant())
    415         return false;
    416       if (RHS.isUndef())
    417         return false;
    418       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 
    429     auto OldTag = Tag;
    430     assert(isConstantRange() && "New ValueLattice type?");
    431     if (RHS.isUndef()) {
    432       Tag = constantrange_including_undef;
    433       return OldTag != Tag;
    434     }
    435 
    436     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     }
    442 
    443     ConstantRange NewR = getConstantRange().unionWith(RHS.getConstantRange());
    444     return markConstantRange(
    445         std::move(NewR),
    446         Opts.setMayIncludeUndef(RHS.isConstantRangeIncludingUndef()));
    447   }
    448 
    449   // Compares this symbolic value with Other using Pred and returns either
    450   /// 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 {
    454     if (isUnknownOrUndef() || Other.isUnknownOrUndef())
    455       return UndefValue::get(Ty);
    456 
    457     if (isConstant() && Other.isConstant())
    458       return ConstantExpr::getCompare(Pred, getConstant(), Other.getConstant());
    459 
    460     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 
    470     // 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 (CR.icmp(Pred, OtherCR))
    478       return ConstantInt::getTrue(Ty);
    479     if (CR.icmp(CmpInst::getInversePredicate(Pred), OtherCR))
    480       return ConstantInt::getFalse(Ty);
    481 
    482     return nullptr;
    483   }
    484 
    485   unsigned getNumRangeExtensions() const { return NumRangeExtensions; }
    486   void setNumRangeExtensions(unsigned N) { NumRangeExtensions = N; }
    487 };
    488 
    489 static_assert(sizeof(ValueLatticeElement) <= 40,
    490               "size of ValueLatticeElement changed unexpectedly");
    491 
    492 raw_ostream &operator<<(raw_ostream &OS, const ValueLatticeElement &Val);
    493 } // end namespace llvm
    494 #endif
    495