File indexing completed on 2026-05-10 08:43:19
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef LLVM_ANALYSIS_VALUELATTICE_H
0010 #define LLVM_ANALYSIS_VALUELATTICE_H
0011
0012 #include "llvm/IR/ConstantRange.h"
0013 #include "llvm/IR/Constants.h"
0014
0015
0016
0017
0018
0019 namespace llvm {
0020
0021
0022
0023
0024
0025
0026 class ValueLatticeElement {
0027 enum ValueLatticeElementTy {
0028
0029
0030
0031
0032
0033 unknown,
0034
0035
0036
0037
0038
0039
0040
0041
0042 undef,
0043
0044
0045
0046
0047
0048
0049
0050 constant,
0051
0052
0053
0054
0055
0056
0057 notconstant,
0058
0059
0060
0061
0062
0063
0064 constantrange,
0065
0066
0067
0068
0069
0070
0071 constantrange_including_undef,
0072
0073
0074
0075 overdefined,
0076 };
0077
0078 ValueLatticeElementTy Tag : 8;
0079
0080 unsigned NumRangeExtensions : 8;
0081
0082
0083
0084
0085 union {
0086 Constant *ConstVal;
0087 ConstantRange Range;
0088 };
0089
0090
0091 void destroy() {
0092 switch (Tag) {
0093 case overdefined:
0094 case unknown:
0095 case undef:
0096 case constant:
0097 case notconstant:
0098 break;
0099 case constantrange_including_undef:
0100 case constantrange:
0101 Range.~ConstantRange();
0102 break;
0103 };
0104 }
0105
0106 public:
0107
0108 struct MergeOptions {
0109
0110 bool MayIncludeUndef;
0111
0112
0113
0114 bool CheckWiden;
0115
0116
0117
0118 unsigned MaxWidenSteps;
0119
0120 MergeOptions() : MergeOptions(false, false) {}
0121
0122 MergeOptions(bool MayIncludeUndef, bool CheckWiden,
0123 unsigned MaxWidenSteps = 1)
0124 : MayIncludeUndef(MayIncludeUndef), CheckWiden(CheckWiden),
0125 MaxWidenSteps(MaxWidenSteps) {}
0126
0127 MergeOptions &setMayIncludeUndef(bool V = true) {
0128 MayIncludeUndef = V;
0129 return *this;
0130 }
0131
0132 MergeOptions &setCheckWiden(bool V = true) {
0133 CheckWiden = V;
0134 return *this;
0135 }
0136
0137 MergeOptions &setMaxWidenSteps(unsigned Steps = 1) {
0138 CheckWiden = true;
0139 MaxWidenSteps = Steps;
0140 return *this;
0141 }
0142 };
0143
0144
0145 ValueLatticeElement() : Tag(unknown), NumRangeExtensions(0) {}
0146
0147 ~ValueLatticeElement() { destroy(); }
0148
0149 ValueLatticeElement(const ValueLatticeElement &Other)
0150 : Tag(Other.Tag), NumRangeExtensions(0) {
0151 switch (Other.Tag) {
0152 case constantrange:
0153 case constantrange_including_undef:
0154 new (&Range) ConstantRange(Other.Range);
0155 NumRangeExtensions = Other.NumRangeExtensions;
0156 break;
0157 case constant:
0158 case notconstant:
0159 ConstVal = Other.ConstVal;
0160 break;
0161 case overdefined:
0162 case unknown:
0163 case undef:
0164 break;
0165 }
0166 }
0167
0168 ValueLatticeElement(ValueLatticeElement &&Other)
0169 : Tag(Other.Tag), NumRangeExtensions(0) {
0170 switch (Other.Tag) {
0171 case constantrange:
0172 case constantrange_including_undef:
0173 new (&Range) ConstantRange(std::move(Other.Range));
0174 NumRangeExtensions = Other.NumRangeExtensions;
0175 break;
0176 case constant:
0177 case notconstant:
0178 ConstVal = Other.ConstVal;
0179 break;
0180 case overdefined:
0181 case unknown:
0182 case undef:
0183 break;
0184 }
0185 Other.Tag = unknown;
0186 }
0187
0188 ValueLatticeElement &operator=(const ValueLatticeElement &Other) {
0189 destroy();
0190 new (this) ValueLatticeElement(Other);
0191 return *this;
0192 }
0193
0194 ValueLatticeElement &operator=(ValueLatticeElement &&Other) {
0195 destroy();
0196 new (this) ValueLatticeElement(std::move(Other));
0197 return *this;
0198 }
0199
0200 static ValueLatticeElement get(Constant *C) {
0201 ValueLatticeElement Res;
0202 Res.markConstant(C);
0203 return Res;
0204 }
0205 static ValueLatticeElement getNot(Constant *C) {
0206 ValueLatticeElement Res;
0207 assert(!isa<UndefValue>(C) && "!= undef is not supported");
0208 Res.markNotConstant(C);
0209 return Res;
0210 }
0211 static ValueLatticeElement getRange(ConstantRange CR,
0212 bool MayIncludeUndef = false) {
0213 if (CR.isFullSet())
0214 return getOverdefined();
0215
0216 if (CR.isEmptySet()) {
0217 ValueLatticeElement Res;
0218 if (MayIncludeUndef)
0219 Res.markUndef();
0220 return Res;
0221 }
0222
0223 ValueLatticeElement Res;
0224 Res.markConstantRange(std::move(CR),
0225 MergeOptions().setMayIncludeUndef(MayIncludeUndef));
0226 return Res;
0227 }
0228 static ValueLatticeElement getOverdefined() {
0229 ValueLatticeElement Res;
0230 Res.markOverdefined();
0231 return Res;
0232 }
0233
0234 bool isUndef() const { return Tag == undef; }
0235 bool isUnknown() const { return Tag == unknown; }
0236 bool isUnknownOrUndef() const { return Tag == unknown || Tag == undef; }
0237 bool isConstant() const { return Tag == constant; }
0238 bool isNotConstant() const { return Tag == notconstant; }
0239 bool isConstantRangeIncludingUndef() const {
0240 return Tag == constantrange_including_undef;
0241 }
0242
0243
0244
0245
0246 bool isConstantRange(bool UndefAllowed = true) const {
0247 return Tag == constantrange || (Tag == constantrange_including_undef &&
0248 (UndefAllowed || Range.isSingleElement()));
0249 }
0250 bool isOverdefined() const { return Tag == overdefined; }
0251
0252 Constant *getConstant() const {
0253 assert(isConstant() && "Cannot get the constant of a non-constant!");
0254 return ConstVal;
0255 }
0256
0257 Constant *getNotConstant() const {
0258 assert(isNotConstant() && "Cannot get the constant of a non-notconstant!");
0259 return ConstVal;
0260 }
0261
0262
0263
0264
0265
0266 const ConstantRange &getConstantRange(bool UndefAllowed = true) const {
0267 assert(isConstantRange(UndefAllowed) &&
0268 "Cannot get the constant-range of a non-constant-range!");
0269 return Range;
0270 }
0271
0272 std::optional<APInt> asConstantInteger() const {
0273 if (isConstant() && isa<ConstantInt>(getConstant())) {
0274 return cast<ConstantInt>(getConstant())->getValue();
0275 } else if (isConstantRange() && getConstantRange().isSingleElement()) {
0276 return *getConstantRange().getSingleElement();
0277 }
0278 return std::nullopt;
0279 }
0280
0281 ConstantRange asConstantRange(unsigned BW, bool UndefAllowed = false) const {
0282 if (isConstantRange(UndefAllowed))
0283 return getConstantRange();
0284 if (isConstant())
0285 return getConstant()->toConstantRange();
0286 if (isUnknown())
0287 return ConstantRange::getEmpty(BW);
0288 return ConstantRange::getFull(BW);
0289 }
0290
0291 ConstantRange asConstantRange(Type *Ty, bool UndefAllowed = false) const {
0292 assert(Ty->isIntOrIntVectorTy() && "Must be integer type");
0293 return asConstantRange(Ty->getScalarSizeInBits(), UndefAllowed);
0294 }
0295
0296 bool markOverdefined() {
0297 if (isOverdefined())
0298 return false;
0299 destroy();
0300 Tag = overdefined;
0301 return true;
0302 }
0303
0304 bool markUndef() {
0305 if (isUndef())
0306 return false;
0307
0308 assert(isUnknown());
0309 Tag = undef;
0310 return true;
0311 }
0312
0313 bool markConstant(Constant *V, bool MayIncludeUndef = false) {
0314 if (isa<UndefValue>(V))
0315 return markUndef();
0316
0317 if (isConstant()) {
0318 assert(getConstant() == V && "Marking constant with different value");
0319 return false;
0320 }
0321
0322 if (ConstantInt *CI = dyn_cast<ConstantInt>(V))
0323 return markConstantRange(
0324 ConstantRange(CI->getValue()),
0325 MergeOptions().setMayIncludeUndef(MayIncludeUndef));
0326
0327 assert(isUnknown() || isUndef());
0328 Tag = constant;
0329 ConstVal = V;
0330 return true;
0331 }
0332
0333 bool markNotConstant(Constant *V) {
0334 assert(V && "Marking constant with NULL");
0335 if (ConstantInt *CI = dyn_cast<ConstantInt>(V))
0336 return markConstantRange(
0337 ConstantRange(CI->getValue() + 1, CI->getValue()));
0338
0339 if (isa<UndefValue>(V))
0340 return false;
0341
0342 if (isNotConstant()) {
0343 assert(getNotConstant() == V && "Marking !constant with different value");
0344 return false;
0345 }
0346
0347 assert(isUnknown());
0348 Tag = notconstant;
0349 ConstVal = V;
0350 return true;
0351 }
0352
0353
0354
0355
0356
0357
0358
0359 bool markConstantRange(ConstantRange NewR,
0360 MergeOptions Opts = MergeOptions()) {
0361 assert(!NewR.isEmptySet() && "should only be called for non-empty sets");
0362
0363 if (NewR.isFullSet())
0364 return markOverdefined();
0365
0366 ValueLatticeElementTy OldTag = Tag;
0367 ValueLatticeElementTy NewTag =
0368 (isUndef() || isConstantRangeIncludingUndef() || Opts.MayIncludeUndef)
0369 ? constantrange_including_undef
0370 : constantrange;
0371 if (isConstantRange()) {
0372 Tag = NewTag;
0373 if (getConstantRange() == NewR)
0374 return Tag != OldTag;
0375
0376
0377
0378 if (Opts.CheckWiden && ++NumRangeExtensions > Opts.MaxWidenSteps)
0379 return markOverdefined();
0380
0381 assert(NewR.contains(getConstantRange()) &&
0382 "Existing range must be a subset of NewR");
0383 Range = std::move(NewR);
0384 return true;
0385 }
0386
0387 assert(isUnknown() || isUndef() || isConstant());
0388 assert((!isConstant() || NewR.contains(getConstant()->toConstantRange())) &&
0389 "Constant must be subset of new range");
0390
0391 NumRangeExtensions = 0;
0392 Tag = NewTag;
0393 new (&Range) ConstantRange(std::move(NewR));
0394 return true;
0395 }
0396
0397
0398
0399 bool mergeIn(const ValueLatticeElement &RHS,
0400 MergeOptions Opts = MergeOptions()) {
0401 if (RHS.isUnknown() || isOverdefined())
0402 return false;
0403 if (RHS.isOverdefined()) {
0404 markOverdefined();
0405 return true;
0406 }
0407
0408 if (isUndef()) {
0409 assert(!RHS.isUnknown());
0410 if (RHS.isUndef())
0411 return false;
0412 if (RHS.isConstant())
0413 return markConstant(RHS.getConstant(), true);
0414 if (RHS.isConstantRange())
0415 return markConstantRange(RHS.getConstantRange(true),
0416 Opts.setMayIncludeUndef());
0417 return markOverdefined();
0418 }
0419
0420 if (isUnknown()) {
0421 assert(!RHS.isUnknown() && "Unknow RHS should be handled earlier");
0422 *this = RHS;
0423 return true;
0424 }
0425
0426 if (isConstant()) {
0427 if (RHS.isConstant() && getConstant() == RHS.getConstant())
0428 return false;
0429 if (RHS.isUndef())
0430 return false;
0431
0432 if (getConstant()->getType()->isVectorTy() &&
0433 getConstant()->getType()->getScalarType()->isIntegerTy()) {
0434 ConstantRange L = getConstant()->toConstantRange();
0435 ConstantRange NewR = L.unionWith(
0436 RHS.asConstantRange(L.getBitWidth(), true));
0437 return markConstantRange(
0438 std::move(NewR),
0439 Opts.setMayIncludeUndef(RHS.isConstantRangeIncludingUndef()));
0440 }
0441 markOverdefined();
0442 return true;
0443 }
0444
0445 if (isNotConstant()) {
0446 if (RHS.isNotConstant() && getNotConstant() == RHS.getNotConstant())
0447 return false;
0448 markOverdefined();
0449 return true;
0450 }
0451
0452 auto OldTag = Tag;
0453 assert(isConstantRange() && "New ValueLattice type?");
0454 if (RHS.isUndef()) {
0455 Tag = constantrange_including_undef;
0456 return OldTag != Tag;
0457 }
0458
0459 const ConstantRange &L = getConstantRange();
0460 ConstantRange NewR = L.unionWith(
0461 RHS.asConstantRange(L.getBitWidth(), true));
0462 return markConstantRange(
0463 std::move(NewR),
0464 Opts.setMayIncludeUndef(RHS.isConstantRangeIncludingUndef()));
0465 }
0466
0467
0468
0469
0470 Constant *getCompare(CmpInst::Predicate Pred, Type *Ty,
0471 const ValueLatticeElement &Other,
0472 const DataLayout &DL) const;
0473
0474
0475
0476
0477
0478
0479
0480
0481
0482
0483
0484
0485
0486
0487
0488
0489 ValueLatticeElement intersect(const ValueLatticeElement &Other) const;
0490
0491 unsigned getNumRangeExtensions() const { return NumRangeExtensions; }
0492 void setNumRangeExtensions(unsigned N) { NumRangeExtensions = N; }
0493 };
0494
0495 static_assert(sizeof(ValueLatticeElement) <= 40,
0496 "size of ValueLatticeElement changed unexpectedly");
0497
0498 raw_ostream &operator<<(raw_ostream &OS, const ValueLatticeElement &Val);
0499 }
0500 #endif