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 /// 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 26 namespace llvm { 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. destroy()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 MergeOptionsMergeOptions121 MergeOptions() : MergeOptions(false, false) {} 122 123 MergeOptions(bool MayIncludeUndef, bool CheckWiden, 124 unsigned MaxWidenSteps = 1) MayIncludeUndefMergeOptions125 : 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. ValueLatticeElement()146 ValueLatticeElement() : Tag(unknown), NumRangeExtensions(0) {} 147 ~ValueLatticeElement()148 ~ValueLatticeElement() { destroy(); } 149 ValueLatticeElement(const ValueLatticeElement & Other)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 ValueLatticeElement(ValueLatticeElement && Other)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 get(Constant * C)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 } getNot(Constant * C)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 } getOverdefined()232 static ValueLatticeElement getOverdefined() { 233 ValueLatticeElement Res; 234 Res.markOverdefined(); 235 return Res; 236 } 237 isUndef()238 bool isUndef() const { return Tag == undef; } isUnknown()239 bool isUnknown() const { return Tag == unknown; } isUnknownOrUndef()240 bool isUnknownOrUndef() const { return Tag == unknown || Tag == undef; } isConstant()241 bool isConstant() const { return Tag == constant; } isNotConstant()242 bool isNotConstant() const { return Tag == notconstant; } isConstantRangeIncludingUndef()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 } isOverdefined()254 bool isOverdefined() const { return Tag == overdefined; } 255 getConstant()256 Constant *getConstant() const { 257 assert(isConstant() && "Cannot get the constant of a non-constant!"); 258 return ConstVal; 259 } 260 getNotConstant()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 asConstantInteger()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 markOverdefined()285 bool markOverdefined() { 286 if (isOverdefined()) 287 return false; 288 destroy(); 289 Tag = overdefined; 290 return true; 291 } 292 markUndef()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 markNotConstant(Constant * V)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. getCompare(CmpInst::Predicate Pred,Type * Ty,const ValueLatticeElement & Other)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 (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 } 486 getNumRangeExtensions()487 unsigned getNumRangeExtensions() const { return NumRangeExtensions; } setNumRangeExtensions(unsigned N)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