File indexing completed on 2026-05-10 08:44:32
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef LLVM_SUPPORT_KNOWNBITS_H
0015 #define LLVM_SUPPORT_KNOWNBITS_H
0016
0017 #include "llvm/ADT/APInt.h"
0018 #include <optional>
0019
0020 namespace llvm {
0021
0022
0023 struct KnownBits {
0024 APInt Zero;
0025 APInt One;
0026
0027 private:
0028
0029 KnownBits(APInt Zero, APInt One)
0030 : Zero(std::move(Zero)), One(std::move(One)) {}
0031
0032
0033 static KnownBits flipSignBit(const KnownBits &Val);
0034
0035 public:
0036
0037 KnownBits() = default;
0038
0039
0040 KnownBits(unsigned BitWidth) : Zero(BitWidth, 0), One(BitWidth, 0) {}
0041
0042
0043 unsigned getBitWidth() const {
0044 assert(Zero.getBitWidth() == One.getBitWidth() &&
0045 "Zero and One should have the same width!");
0046 return Zero.getBitWidth();
0047 }
0048
0049
0050 bool hasConflict() const { return Zero.intersects(One); }
0051
0052
0053 bool isConstant() const {
0054 return Zero.popcount() + One.popcount() == getBitWidth();
0055 }
0056
0057
0058
0059 const APInt &getConstant() const {
0060 assert(isConstant() && "Can only get value when all bits are known");
0061 return One;
0062 }
0063
0064
0065 bool isUnknown() const { return Zero.isZero() && One.isZero(); }
0066
0067
0068 bool isSignUnknown() const {
0069 return !Zero.isSignBitSet() && !One.isSignBitSet();
0070 }
0071
0072
0073 void resetAll() {
0074 Zero.clearAllBits();
0075 One.clearAllBits();
0076 }
0077
0078
0079 bool isZero() const { return Zero.isAllOnes(); }
0080
0081
0082 bool isAllOnes() const { return One.isAllOnes(); }
0083
0084
0085 void setAllZero() {
0086 Zero.setAllBits();
0087 One.clearAllBits();
0088 }
0089
0090
0091 void setAllOnes() {
0092 Zero.clearAllBits();
0093 One.setAllBits();
0094 }
0095
0096
0097 bool isNegative() const { return One.isSignBitSet(); }
0098
0099
0100 bool isNonNegative() const { return Zero.isSignBitSet(); }
0101
0102
0103 bool isNonZero() const { return !One.isZero(); }
0104
0105
0106 bool isStrictlyPositive() const {
0107 return Zero.isSignBitSet() && !One.isZero();
0108 }
0109
0110
0111 void makeNegative() {
0112 One.setSignBit();
0113 }
0114
0115
0116 void makeNonNegative() {
0117 Zero.setSignBit();
0118 }
0119
0120
0121 APInt getMinValue() const {
0122
0123 return One;
0124 }
0125
0126
0127 APInt getSignedMinValue() const {
0128
0129 APInt Min = One;
0130
0131 if (Zero.isSignBitClear())
0132 Min.setSignBit();
0133 return Min;
0134 }
0135
0136
0137 APInt getMaxValue() const {
0138
0139 return ~Zero;
0140 }
0141
0142
0143 APInt getSignedMaxValue() const {
0144
0145 APInt Max = ~Zero;
0146
0147 if (One.isSignBitClear())
0148 Max.clearSignBit();
0149 return Max;
0150 }
0151
0152
0153 KnownBits trunc(unsigned BitWidth) const {
0154 return KnownBits(Zero.trunc(BitWidth), One.trunc(BitWidth));
0155 }
0156
0157
0158
0159 KnownBits anyext(unsigned BitWidth) const {
0160 return KnownBits(Zero.zext(BitWidth), One.zext(BitWidth));
0161 }
0162
0163
0164 KnownBits zext(unsigned BitWidth) const {
0165 unsigned OldBitWidth = getBitWidth();
0166 APInt NewZero = Zero.zext(BitWidth);
0167 NewZero.setBitsFrom(OldBitWidth);
0168 return KnownBits(NewZero, One.zext(BitWidth));
0169 }
0170
0171
0172 KnownBits sext(unsigned BitWidth) const {
0173 return KnownBits(Zero.sext(BitWidth), One.sext(BitWidth));
0174 }
0175
0176
0177
0178 KnownBits anyextOrTrunc(unsigned BitWidth) const {
0179 if (BitWidth > getBitWidth())
0180 return anyext(BitWidth);
0181 if (BitWidth < getBitWidth())
0182 return trunc(BitWidth);
0183 return *this;
0184 }
0185
0186
0187
0188 KnownBits zextOrTrunc(unsigned BitWidth) const {
0189 if (BitWidth > getBitWidth())
0190 return zext(BitWidth);
0191 if (BitWidth < getBitWidth())
0192 return trunc(BitWidth);
0193 return *this;
0194 }
0195
0196
0197
0198 KnownBits sextOrTrunc(unsigned BitWidth) const {
0199 if (BitWidth > getBitWidth())
0200 return sext(BitWidth);
0201 if (BitWidth < getBitWidth())
0202 return trunc(BitWidth);
0203 return *this;
0204 }
0205
0206
0207
0208 KnownBits sextInReg(unsigned SrcBitWidth) const;
0209
0210
0211 void insertBits(const KnownBits &SubBits, unsigned BitPosition) {
0212 Zero.insertBits(SubBits.Zero, BitPosition);
0213 One.insertBits(SubBits.One, BitPosition);
0214 }
0215
0216
0217 KnownBits extractBits(unsigned NumBits, unsigned BitPosition) const {
0218 return KnownBits(Zero.extractBits(NumBits, BitPosition),
0219 One.extractBits(NumBits, BitPosition));
0220 }
0221
0222
0223
0224
0225 KnownBits concat(const KnownBits &Lo) const {
0226 return KnownBits(Zero.concat(Lo.Zero), One.concat(Lo.One));
0227 }
0228
0229
0230
0231 KnownBits makeGE(const APInt &Val) const;
0232
0233
0234 unsigned countMinTrailingZeros() const { return Zero.countr_one(); }
0235
0236
0237 unsigned countMinTrailingOnes() const { return One.countr_one(); }
0238
0239
0240 unsigned countMinLeadingZeros() const { return Zero.countl_one(); }
0241
0242
0243 unsigned countMinLeadingOnes() const { return One.countl_one(); }
0244
0245
0246
0247 unsigned countMinSignBits() const {
0248 if (isNonNegative())
0249 return countMinLeadingZeros();
0250 if (isNegative())
0251 return countMinLeadingOnes();
0252
0253 return 1;
0254 }
0255
0256
0257
0258
0259
0260
0261 unsigned countMaxSignificantBits() const {
0262 return getBitWidth() - countMinSignBits() + 1;
0263 }
0264
0265
0266 unsigned countMaxTrailingZeros() const { return One.countr_zero(); }
0267
0268
0269 unsigned countMaxTrailingOnes() const { return Zero.countr_zero(); }
0270
0271
0272 unsigned countMaxLeadingZeros() const { return One.countl_zero(); }
0273
0274
0275 unsigned countMaxLeadingOnes() const { return Zero.countl_zero(); }
0276
0277
0278 unsigned countMinPopulation() const { return One.popcount(); }
0279
0280
0281 unsigned countMaxPopulation() const {
0282 return getBitWidth() - Zero.popcount();
0283 }
0284
0285
0286
0287
0288 unsigned countMaxActiveBits() const {
0289 return getBitWidth() - countMinLeadingZeros();
0290 }
0291
0292
0293 static KnownBits makeConstant(const APInt &C) {
0294 return KnownBits(~C, C);
0295 }
0296
0297
0298
0299
0300
0301
0302
0303 KnownBits intersectWith(const KnownBits &RHS) const {
0304 return KnownBits(Zero & RHS.Zero, One & RHS.One);
0305 }
0306
0307
0308
0309
0310
0311
0312
0313 KnownBits unionWith(const KnownBits &RHS) const {
0314 return KnownBits(Zero | RHS.Zero, One | RHS.One);
0315 }
0316
0317
0318 static bool haveNoCommonBitsSet(const KnownBits &LHS, const KnownBits &RHS) {
0319 return (LHS.Zero | RHS.Zero).isAllOnes();
0320 }
0321
0322
0323 static KnownBits computeForAddCarry(
0324 const KnownBits &LHS, const KnownBits &RHS, const KnownBits &Carry);
0325
0326
0327 static KnownBits computeForAddSub(bool Add, bool NSW, bool NUW,
0328 const KnownBits &LHS, const KnownBits &RHS);
0329
0330
0331
0332 static KnownBits computeForSubBorrow(const KnownBits &LHS, KnownBits RHS,
0333 const KnownBits &Borrow);
0334
0335
0336 static KnownBits add(const KnownBits &LHS, const KnownBits &RHS,
0337 bool NSW = false, bool NUW = false) {
0338 return computeForAddSub(true, NSW, NUW, LHS, RHS);
0339 }
0340
0341
0342 static KnownBits sub(const KnownBits &LHS, const KnownBits &RHS,
0343 bool NSW = false, bool NUW = false) {
0344 return computeForAddSub(false, NSW, NUW, LHS, RHS);
0345 }
0346
0347
0348 static KnownBits sadd_sat(const KnownBits &LHS, const KnownBits &RHS);
0349
0350
0351 static KnownBits uadd_sat(const KnownBits &LHS, const KnownBits &RHS);
0352
0353
0354 static KnownBits ssub_sat(const KnownBits &LHS, const KnownBits &RHS);
0355
0356
0357 static KnownBits usub_sat(const KnownBits &LHS, const KnownBits &RHS);
0358
0359
0360 static KnownBits avgFloorS(const KnownBits &LHS, const KnownBits &RHS);
0361
0362
0363 static KnownBits avgFloorU(const KnownBits &LHS, const KnownBits &RHS);
0364
0365
0366 static KnownBits avgCeilS(const KnownBits &LHS, const KnownBits &RHS);
0367
0368
0369 static KnownBits avgCeilU(const KnownBits &LHS, const KnownBits &RHS);
0370
0371
0372 static KnownBits mul(const KnownBits &LHS, const KnownBits &RHS,
0373 bool NoUndefSelfMultiply = false);
0374
0375
0376 static KnownBits mulhs(const KnownBits &LHS, const KnownBits &RHS);
0377
0378
0379 static KnownBits mulhu(const KnownBits &LHS, const KnownBits &RHS);
0380
0381
0382 static KnownBits sdiv(const KnownBits &LHS, const KnownBits &RHS,
0383 bool Exact = false);
0384
0385
0386 static KnownBits udiv(const KnownBits &LHS, const KnownBits &RHS,
0387 bool Exact = false);
0388
0389
0390 static KnownBits urem(const KnownBits &LHS, const KnownBits &RHS);
0391
0392
0393 static KnownBits srem(const KnownBits &LHS, const KnownBits &RHS);
0394
0395
0396 static KnownBits umax(const KnownBits &LHS, const KnownBits &RHS);
0397
0398
0399 static KnownBits umin(const KnownBits &LHS, const KnownBits &RHS);
0400
0401
0402 static KnownBits smax(const KnownBits &LHS, const KnownBits &RHS);
0403
0404
0405 static KnownBits smin(const KnownBits &LHS, const KnownBits &RHS);
0406
0407
0408 static KnownBits abdu(const KnownBits &LHS, const KnownBits &RHS);
0409
0410
0411 static KnownBits abds(KnownBits LHS, KnownBits RHS);
0412
0413
0414
0415 static KnownBits shl(const KnownBits &LHS, const KnownBits &RHS,
0416 bool NUW = false, bool NSW = false,
0417 bool ShAmtNonZero = false);
0418
0419
0420
0421 static KnownBits lshr(const KnownBits &LHS, const KnownBits &RHS,
0422 bool ShAmtNonZero = false, bool Exact = false);
0423
0424
0425
0426 static KnownBits ashr(const KnownBits &LHS, const KnownBits &RHS,
0427 bool ShAmtNonZero = false, bool Exact = false);
0428
0429
0430 static std::optional<bool> eq(const KnownBits &LHS, const KnownBits &RHS);
0431
0432
0433 static std::optional<bool> ne(const KnownBits &LHS, const KnownBits &RHS);
0434
0435
0436 static std::optional<bool> ugt(const KnownBits &LHS, const KnownBits &RHS);
0437
0438
0439 static std::optional<bool> uge(const KnownBits &LHS, const KnownBits &RHS);
0440
0441
0442 static std::optional<bool> ult(const KnownBits &LHS, const KnownBits &RHS);
0443
0444
0445 static std::optional<bool> ule(const KnownBits &LHS, const KnownBits &RHS);
0446
0447
0448 static std::optional<bool> sgt(const KnownBits &LHS, const KnownBits &RHS);
0449
0450
0451 static std::optional<bool> sge(const KnownBits &LHS, const KnownBits &RHS);
0452
0453
0454 static std::optional<bool> slt(const KnownBits &LHS, const KnownBits &RHS);
0455
0456
0457 static std::optional<bool> sle(const KnownBits &LHS, const KnownBits &RHS);
0458
0459
0460 KnownBits &operator&=(const KnownBits &RHS);
0461
0462
0463 KnownBits &operator|=(const KnownBits &RHS);
0464
0465
0466 KnownBits &operator^=(const KnownBits &RHS);
0467
0468
0469 KnownBits abs(bool IntMinIsPoison = false) const;
0470
0471 KnownBits byteSwap() const {
0472 return KnownBits(Zero.byteSwap(), One.byteSwap());
0473 }
0474
0475 KnownBits reverseBits() const {
0476 return KnownBits(Zero.reverseBits(), One.reverseBits());
0477 }
0478
0479
0480
0481 KnownBits blsi() const;
0482
0483
0484
0485 KnownBits blsmsk() const;
0486
0487 bool operator==(const KnownBits &Other) const {
0488 return Zero == Other.Zero && One == Other.One;
0489 }
0490
0491 bool operator!=(const KnownBits &Other) const { return !(*this == Other); }
0492
0493 void print(raw_ostream &OS) const;
0494 void dump() const;
0495
0496 private:
0497
0498
0499 static KnownBits remGetLowBits(const KnownBits &LHS, const KnownBits &RHS);
0500 };
0501
0502 inline KnownBits operator&(KnownBits LHS, const KnownBits &RHS) {
0503 LHS &= RHS;
0504 return LHS;
0505 }
0506
0507 inline KnownBits operator&(const KnownBits &LHS, KnownBits &&RHS) {
0508 RHS &= LHS;
0509 return std::move(RHS);
0510 }
0511
0512 inline KnownBits operator|(KnownBits LHS, const KnownBits &RHS) {
0513 LHS |= RHS;
0514 return LHS;
0515 }
0516
0517 inline KnownBits operator|(const KnownBits &LHS, KnownBits &&RHS) {
0518 RHS |= LHS;
0519 return std::move(RHS);
0520 }
0521
0522 inline KnownBits operator^(KnownBits LHS, const KnownBits &RHS) {
0523 LHS ^= RHS;
0524 return LHS;
0525 }
0526
0527 inline KnownBits operator^(const KnownBits &LHS, KnownBits &&RHS) {
0528 RHS ^= LHS;
0529 return std::move(RHS);
0530 }
0531
0532 inline raw_ostream &operator<<(raw_ostream &OS, const KnownBits &Known) {
0533 Known.print(OS);
0534 return OS;
0535 }
0536
0537 }
0538
0539 #endif