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/Support/Compiler.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. 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 Res.markConstant(C); 204 return Res; 205 } getNot(Constant * C)206 static ValueLatticeElement getNot(Constant *C) { 207 ValueLatticeElement Res; 208 assert(!isa<UndefValue>(C) && "!= undef is not supported"); 209 Res.markNotConstant(C); 210 return Res; 211 } 212 static ValueLatticeElement getRange(ConstantRange CR, 213 bool MayIncludeUndef = false) { 214 if (CR.isFullSet()) 215 return getOverdefined(); 216 217 if (CR.isEmptySet()) { 218 ValueLatticeElement Res; 219 if (MayIncludeUndef) 220 Res.markUndef(); 221 return Res; 222 } 223 224 ValueLatticeElement Res; 225 Res.markConstantRange(std::move(CR), 226 MergeOptions().setMayIncludeUndef(MayIncludeUndef)); 227 return Res; 228 } getOverdefined()229 static ValueLatticeElement getOverdefined() { 230 ValueLatticeElement Res; 231 Res.markOverdefined(); 232 return Res; 233 } 234 isUndef()235 bool isUndef() const { return Tag == undef; } isUnknown()236 bool isUnknown() const { return Tag == unknown; } isUnknownOrUndef()237 bool isUnknownOrUndef() const { return Tag == unknown || Tag == undef; } isConstant()238 bool isConstant() const { return Tag == constant; } isNotConstant()239 bool isNotConstant() const { return Tag == notconstant; } isConstantRangeIncludingUndef()240 bool isConstantRangeIncludingUndef() const { 241 return Tag == constantrange_including_undef; 242 } 243 /// Returns true if this value is a constant range. Use \p UndefAllowed to 244 /// exclude non-singleton constant ranges that may also be undef. Note that 245 /// this function also returns true if the range may include undef, but only 246 /// contains a single element. In that case, it can be replaced by a constant. 247 bool isConstantRange(bool UndefAllowed = true) const { 248 return Tag == constantrange || (Tag == constantrange_including_undef && 249 (UndefAllowed || Range.isSingleElement())); 250 } isOverdefined()251 bool isOverdefined() const { return Tag == overdefined; } 252 getConstant()253 Constant *getConstant() const { 254 assert(isConstant() && "Cannot get the constant of a non-constant!"); 255 return ConstVal; 256 } 257 getNotConstant()258 Constant *getNotConstant() const { 259 assert(isNotConstant() && "Cannot get the constant of a non-notconstant!"); 260 return ConstVal; 261 } 262 263 /// Returns the constant range for this value. Use \p UndefAllowed to exclude 264 /// non-singleton constant ranges that may also be undef. Note that this 265 /// function also returns a range if the range may include undef, but only 266 /// contains a single element. In that case, it can be replaced by a constant. 267 const ConstantRange &getConstantRange(bool UndefAllowed = true) const { 268 assert(isConstantRange(UndefAllowed) && 269 "Cannot get the constant-range of a non-constant-range!"); 270 return Range; 271 } 272 asConstantInteger()273 std::optional<APInt> asConstantInteger() const { 274 if (isConstant() && isa<ConstantInt>(getConstant())) { 275 return cast<ConstantInt>(getConstant())->getValue(); 276 } else if (isConstantRange() && getConstantRange().isSingleElement()) { 277 return *getConstantRange().getSingleElement(); 278 } 279 return std::nullopt; 280 } 281 282 ConstantRange asConstantRange(unsigned BW, bool UndefAllowed = false) const { 283 if (isConstantRange(UndefAllowed)) 284 return getConstantRange(); 285 if (isConstant()) 286 return getConstant()->toConstantRange(); 287 if (isUnknown()) 288 return ConstantRange::getEmpty(BW); 289 return ConstantRange::getFull(BW); 290 } 291 292 ConstantRange asConstantRange(Type *Ty, bool UndefAllowed = false) const { 293 assert(Ty->isIntOrIntVectorTy() && "Must be integer type"); 294 return asConstantRange(Ty->getScalarSizeInBits(), UndefAllowed); 295 } 296 markOverdefined()297 bool markOverdefined() { 298 if (isOverdefined()) 299 return false; 300 destroy(); 301 Tag = overdefined; 302 return true; 303 } 304 markUndef()305 bool markUndef() { 306 if (isUndef()) 307 return false; 308 309 assert(isUnknown()); 310 Tag = undef; 311 return true; 312 } 313 314 bool markConstant(Constant *V, bool MayIncludeUndef = false) { 315 if (isa<UndefValue>(V)) 316 return markUndef(); 317 318 if (isConstant()) { 319 assert(getConstant() == V && "Marking constant with different value"); 320 return false; 321 } 322 323 if (ConstantInt *CI = dyn_cast<ConstantInt>(V)) 324 return markConstantRange( 325 ConstantRange(CI->getValue()), 326 MergeOptions().setMayIncludeUndef(MayIncludeUndef)); 327 328 assert(isUnknown() || isUndef()); 329 Tag = constant; 330 ConstVal = V; 331 return true; 332 } 333 markNotConstant(Constant * V)334 bool markNotConstant(Constant *V) { 335 assert(V && "Marking constant with NULL"); 336 if (ConstantInt *CI = dyn_cast<ConstantInt>(V)) 337 return markConstantRange( 338 ConstantRange(CI->getValue() + 1, CI->getValue())); 339 340 if (isa<UndefValue>(V)) 341 return false; 342 343 if (isNotConstant()) { 344 assert(getNotConstant() == V && "Marking !constant with different value"); 345 return false; 346 } 347 348 assert(isUnknown()); 349 Tag = notconstant; 350 ConstVal = V; 351 return true; 352 } 353 354 /// Mark the object as constant range with \p NewR. If the object is already a 355 /// constant range, nothing changes if the existing range is equal to \p 356 /// NewR and the tag. Otherwise \p NewR must be a superset of the existing 357 /// range or the object must be undef. The tag is set to 358 /// constant_range_including_undef if either the existing value or the new 359 /// range may include undef. 360 bool markConstantRange(ConstantRange NewR, 361 MergeOptions Opts = MergeOptions()) { 362 assert(!NewR.isEmptySet() && "should only be called for non-empty sets"); 363 364 if (NewR.isFullSet()) 365 return markOverdefined(); 366 367 ValueLatticeElementTy OldTag = Tag; 368 ValueLatticeElementTy NewTag = 369 (isUndef() || isConstantRangeIncludingUndef() || Opts.MayIncludeUndef) 370 ? constantrange_including_undef 371 : constantrange; 372 if (isConstantRange()) { 373 Tag = NewTag; 374 if (getConstantRange() == NewR) 375 return Tag != OldTag; 376 377 // Simple form of widening. If a range is extended multiple times, go to 378 // overdefined. 379 if (Opts.CheckWiden && ++NumRangeExtensions > Opts.MaxWidenSteps) 380 return markOverdefined(); 381 382 assert(NewR.contains(getConstantRange()) && 383 "Existing range must be a subset of NewR"); 384 Range = std::move(NewR); 385 return true; 386 } 387 388 assert(isUnknown() || isUndef() || isConstant()); 389 assert((!isConstant() || NewR.contains(getConstant()->toConstantRange())) && 390 "Constant must be subset of new range"); 391 392 NumRangeExtensions = 0; 393 Tag = NewTag; 394 new (&Range) ConstantRange(std::move(NewR)); 395 return true; 396 } 397 398 /// Updates this object to approximate both this object and RHS. Returns 399 /// true if this object has been changed. 400 bool mergeIn(const ValueLatticeElement &RHS, 401 MergeOptions Opts = MergeOptions()) { 402 if (RHS.isUnknown() || isOverdefined()) 403 return false; 404 if (RHS.isOverdefined()) { 405 markOverdefined(); 406 return true; 407 } 408 409 if (isUndef()) { 410 assert(!RHS.isUnknown()); 411 if (RHS.isUndef()) 412 return false; 413 if (RHS.isConstant()) 414 return markConstant(RHS.getConstant(), true); 415 if (RHS.isConstantRange()) 416 return markConstantRange(RHS.getConstantRange(true), 417 Opts.setMayIncludeUndef()); 418 return markOverdefined(); 419 } 420 421 if (isUnknown()) { 422 assert(!RHS.isUnknown() && "Unknow RHS should be handled earlier"); 423 *this = RHS; 424 return true; 425 } 426 427 if (isConstant()) { 428 if (RHS.isConstant() && getConstant() == RHS.getConstant()) 429 return false; 430 if (RHS.isUndef()) 431 return false; 432 // If the constant is a vector of integers, try to treat it as a range. 433 if (getConstant()->getType()->isVectorTy() && 434 getConstant()->getType()->getScalarType()->isIntegerTy()) { 435 ConstantRange L = getConstant()->toConstantRange(); 436 ConstantRange NewR = L.unionWith( 437 RHS.asConstantRange(L.getBitWidth(), /*UndefAllowed=*/true)); 438 return markConstantRange( 439 std::move(NewR), 440 Opts.setMayIncludeUndef(RHS.isConstantRangeIncludingUndef())); 441 } 442 markOverdefined(); 443 return true; 444 } 445 446 if (isNotConstant()) { 447 if (RHS.isNotConstant() && getNotConstant() == RHS.getNotConstant()) 448 return false; 449 markOverdefined(); 450 return true; 451 } 452 453 auto OldTag = Tag; 454 assert(isConstantRange() && "New ValueLattice type?"); 455 if (RHS.isUndef()) { 456 Tag = constantrange_including_undef; 457 return OldTag != Tag; 458 } 459 460 const ConstantRange &L = getConstantRange(); 461 ConstantRange NewR = L.unionWith( 462 RHS.asConstantRange(L.getBitWidth(), /*UndefAllowed=*/true)); 463 return markConstantRange( 464 std::move(NewR), 465 Opts.setMayIncludeUndef(RHS.isConstantRangeIncludingUndef())); 466 } 467 468 // Compares this symbolic value with Other using Pred and returns either 469 /// true, false or undef constants, or nullptr if the comparison cannot be 470 /// evaluated. 471 LLVM_ABI Constant *getCompare(CmpInst::Predicate Pred, Type *Ty, 472 const ValueLatticeElement &Other, 473 const DataLayout &DL) const; 474 475 /// Combine two sets of facts about the same value into a single set of 476 /// facts. Note that this method is not suitable for merging facts along 477 /// different paths in a CFG; that's what the mergeIn function is for. This 478 /// is for merging facts gathered about the same value at the same location 479 /// through two independent means. 480 /// Notes: 481 /// * This method does not promise to return the most precise possible lattice 482 /// value implied by A and B. It is allowed to return any lattice element 483 /// which is at least as strong as *either* A or B (unless our facts 484 /// conflict, see below). 485 /// * Due to unreachable code, the intersection of two lattice values could be 486 /// contradictory. If this happens, we return some valid lattice value so 487 /// as not confuse the rest of LVI. Ideally, we'd always return Undefined, 488 /// but we do not make this guarantee. TODO: This would be a useful 489 /// enhancement. 490 LLVM_ABI ValueLatticeElement 491 intersect(const ValueLatticeElement &Other) const; 492 getNumRangeExtensions()493 unsigned getNumRangeExtensions() const { return NumRangeExtensions; } setNumRangeExtensions(unsigned N)494 void setNumRangeExtensions(unsigned N) { NumRangeExtensions = N; } 495 }; 496 497 static_assert(sizeof(ValueLatticeElement) <= 40, 498 "size of ValueLatticeElement changed unexpectedly"); 499 500 LLVM_ABI raw_ostream &operator<<(raw_ostream &OS, 501 const ValueLatticeElement &Val); 502 } // end namespace llvm 503 #endif 504