File indexing completed on 2026-05-10 08:44:08
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef LLVM_IR_OPERATOR_H
0015 #define LLVM_IR_OPERATOR_H
0016
0017 #include "llvm/ADT/MapVector.h"
0018 #include "llvm/IR/Constants.h"
0019 #include "llvm/IR/FMF.h"
0020 #include "llvm/IR/GEPNoWrapFlags.h"
0021 #include "llvm/IR/Instruction.h"
0022 #include "llvm/IR/Type.h"
0023 #include "llvm/IR/Value.h"
0024 #include "llvm/Support/Casting.h"
0025 #include <cstddef>
0026 #include <optional>
0027
0028 namespace llvm {
0029
0030
0031
0032 class Operator : public User {
0033 public:
0034
0035
0036 Operator() = delete;
0037 ~Operator() = delete;
0038
0039 void *operator new(size_t s) = delete;
0040
0041
0042 unsigned getOpcode() const {
0043 if (const Instruction *I = dyn_cast<Instruction>(this))
0044 return I->getOpcode();
0045 return cast<ConstantExpr>(this)->getOpcode();
0046 }
0047
0048
0049
0050 static unsigned getOpcode(const Value *V) {
0051 if (const Instruction *I = dyn_cast<Instruction>(V))
0052 return I->getOpcode();
0053 if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(V))
0054 return CE->getOpcode();
0055 return Instruction::UserOp1;
0056 }
0057
0058 static bool classof(const Instruction *) { return true; }
0059 static bool classof(const ConstantExpr *) { return true; }
0060 static bool classof(const Value *V) {
0061 return isa<Instruction>(V) || isa<ConstantExpr>(V);
0062 }
0063
0064
0065
0066 bool hasPoisonGeneratingFlags() const;
0067
0068
0069
0070
0071 bool hasPoisonGeneratingAnnotations() const;
0072 };
0073
0074
0075
0076
0077 class OverflowingBinaryOperator : public Operator {
0078 public:
0079 enum {
0080 AnyWrap = 0,
0081 NoUnsignedWrap = (1 << 0),
0082 NoSignedWrap = (1 << 1)
0083 };
0084
0085 private:
0086 friend class Instruction;
0087 friend class ConstantExpr;
0088
0089 void setHasNoUnsignedWrap(bool B) {
0090 SubclassOptionalData =
0091 (SubclassOptionalData & ~NoUnsignedWrap) | (B * NoUnsignedWrap);
0092 }
0093 void setHasNoSignedWrap(bool B) {
0094 SubclassOptionalData =
0095 (SubclassOptionalData & ~NoSignedWrap) | (B * NoSignedWrap);
0096 }
0097
0098 public:
0099
0100 DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
0101
0102
0103
0104 bool hasNoUnsignedWrap() const {
0105 return SubclassOptionalData & NoUnsignedWrap;
0106 }
0107
0108
0109
0110 bool hasNoSignedWrap() const {
0111 return (SubclassOptionalData & NoSignedWrap) != 0;
0112 }
0113
0114
0115 unsigned getNoWrapKind() const {
0116 unsigned NoWrapKind = 0;
0117 if (hasNoUnsignedWrap())
0118 NoWrapKind |= NoUnsignedWrap;
0119
0120 if (hasNoSignedWrap())
0121 NoWrapKind |= NoSignedWrap;
0122
0123 return NoWrapKind;
0124 }
0125
0126
0127 bool isCommutative() const { return Instruction::isCommutative(getOpcode()); }
0128
0129 static bool classof(const Instruction *I) {
0130 return I->getOpcode() == Instruction::Add ||
0131 I->getOpcode() == Instruction::Sub ||
0132 I->getOpcode() == Instruction::Mul ||
0133 I->getOpcode() == Instruction::Shl;
0134 }
0135 static bool classof(const ConstantExpr *CE) {
0136 return CE->getOpcode() == Instruction::Add ||
0137 CE->getOpcode() == Instruction::Sub ||
0138 CE->getOpcode() == Instruction::Mul ||
0139 CE->getOpcode() == Instruction::Shl;
0140 }
0141 static bool classof(const Value *V) {
0142 return (isa<Instruction>(V) && classof(cast<Instruction>(V))) ||
0143 (isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V)));
0144 }
0145 };
0146
0147 template <>
0148 struct OperandTraits<OverflowingBinaryOperator>
0149 : public FixedNumOperandTraits<OverflowingBinaryOperator, 2> {};
0150
0151 DEFINE_TRANSPARENT_OPERAND_ACCESSORS(OverflowingBinaryOperator, Value)
0152
0153
0154
0155 class PossiblyExactOperator : public Operator {
0156 public:
0157 enum {
0158 IsExact = (1 << 0)
0159 };
0160
0161 private:
0162 friend class Instruction;
0163 friend class ConstantExpr;
0164
0165 void setIsExact(bool B) {
0166 SubclassOptionalData = (SubclassOptionalData & ~IsExact) | (B * IsExact);
0167 }
0168
0169 public:
0170
0171 DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
0172
0173
0174 bool isExact() const {
0175 return SubclassOptionalData & IsExact;
0176 }
0177
0178 static bool isPossiblyExactOpcode(unsigned OpC) {
0179 return OpC == Instruction::SDiv ||
0180 OpC == Instruction::UDiv ||
0181 OpC == Instruction::AShr ||
0182 OpC == Instruction::LShr;
0183 }
0184
0185 static bool classof(const ConstantExpr *CE) {
0186 return isPossiblyExactOpcode(CE->getOpcode());
0187 }
0188 static bool classof(const Instruction *I) {
0189 return isPossiblyExactOpcode(I->getOpcode());
0190 }
0191 static bool classof(const Value *V) {
0192 return (isa<Instruction>(V) && classof(cast<Instruction>(V))) ||
0193 (isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V)));
0194 }
0195 };
0196
0197 template <>
0198 struct OperandTraits<PossiblyExactOperator>
0199 : public FixedNumOperandTraits<PossiblyExactOperator, 2> {};
0200
0201 DEFINE_TRANSPARENT_OPERAND_ACCESSORS(PossiblyExactOperator, Value)
0202
0203
0204
0205 class FPMathOperator : public Operator {
0206 private:
0207 friend class Instruction;
0208
0209
0210 void setFast(bool B) {
0211 setHasAllowReassoc(B);
0212 setHasNoNaNs(B);
0213 setHasNoInfs(B);
0214 setHasNoSignedZeros(B);
0215 setHasAllowReciprocal(B);
0216 setHasAllowContract(B);
0217 setHasApproxFunc(B);
0218 }
0219
0220 void setHasAllowReassoc(bool B) {
0221 SubclassOptionalData =
0222 (SubclassOptionalData & ~FastMathFlags::AllowReassoc) |
0223 (B * FastMathFlags::AllowReassoc);
0224 }
0225
0226 void setHasNoNaNs(bool B) {
0227 SubclassOptionalData =
0228 (SubclassOptionalData & ~FastMathFlags::NoNaNs) |
0229 (B * FastMathFlags::NoNaNs);
0230 }
0231
0232 void setHasNoInfs(bool B) {
0233 SubclassOptionalData =
0234 (SubclassOptionalData & ~FastMathFlags::NoInfs) |
0235 (B * FastMathFlags::NoInfs);
0236 }
0237
0238 void setHasNoSignedZeros(bool B) {
0239 SubclassOptionalData =
0240 (SubclassOptionalData & ~FastMathFlags::NoSignedZeros) |
0241 (B * FastMathFlags::NoSignedZeros);
0242 }
0243
0244 void setHasAllowReciprocal(bool B) {
0245 SubclassOptionalData =
0246 (SubclassOptionalData & ~FastMathFlags::AllowReciprocal) |
0247 (B * FastMathFlags::AllowReciprocal);
0248 }
0249
0250 void setHasAllowContract(bool B) {
0251 SubclassOptionalData =
0252 (SubclassOptionalData & ~FastMathFlags::AllowContract) |
0253 (B * FastMathFlags::AllowContract);
0254 }
0255
0256 void setHasApproxFunc(bool B) {
0257 SubclassOptionalData =
0258 (SubclassOptionalData & ~FastMathFlags::ApproxFunc) |
0259 (B * FastMathFlags::ApproxFunc);
0260 }
0261
0262
0263
0264 void setFastMathFlags(FastMathFlags FMF) {
0265 SubclassOptionalData |= FMF.Flags;
0266 }
0267
0268
0269
0270 void copyFastMathFlags(FastMathFlags FMF) {
0271 SubclassOptionalData = FMF.Flags;
0272 }
0273
0274
0275
0276 static bool isComposedOfHomogeneousFloatingPointTypes(Type *Ty) {
0277 if (auto *StructTy = dyn_cast<StructType>(Ty)) {
0278 if (!StructTy->isLiteral() || !StructTy->containsHomogeneousTypes())
0279 return false;
0280 Ty = StructTy->elements().front();
0281 } else if (auto *ArrayTy = dyn_cast<ArrayType>(Ty)) {
0282 do {
0283 Ty = ArrayTy->getElementType();
0284 } while ((ArrayTy = dyn_cast<ArrayType>(Ty)));
0285 }
0286 return Ty->isFPOrFPVectorTy();
0287 };
0288
0289 public:
0290
0291 bool isFast() const {
0292 return ((SubclassOptionalData & FastMathFlags::AllowReassoc) != 0 &&
0293 (SubclassOptionalData & FastMathFlags::NoNaNs) != 0 &&
0294 (SubclassOptionalData & FastMathFlags::NoInfs) != 0 &&
0295 (SubclassOptionalData & FastMathFlags::NoSignedZeros) != 0 &&
0296 (SubclassOptionalData & FastMathFlags::AllowReciprocal) != 0 &&
0297 (SubclassOptionalData & FastMathFlags::AllowContract) != 0 &&
0298 (SubclassOptionalData & FastMathFlags::ApproxFunc) != 0);
0299 }
0300
0301
0302 bool hasAllowReassoc() const {
0303 return (SubclassOptionalData & FastMathFlags::AllowReassoc) != 0;
0304 }
0305
0306
0307 bool hasNoNaNs() const {
0308 return (SubclassOptionalData & FastMathFlags::NoNaNs) != 0;
0309 }
0310
0311
0312 bool hasNoInfs() const {
0313 return (SubclassOptionalData & FastMathFlags::NoInfs) != 0;
0314 }
0315
0316
0317 bool hasNoSignedZeros() const {
0318 return (SubclassOptionalData & FastMathFlags::NoSignedZeros) != 0;
0319 }
0320
0321
0322 bool hasAllowReciprocal() const {
0323 return (SubclassOptionalData & FastMathFlags::AllowReciprocal) != 0;
0324 }
0325
0326
0327 bool hasAllowContract() const {
0328 return (SubclassOptionalData & FastMathFlags::AllowContract) != 0;
0329 }
0330
0331
0332
0333 bool hasApproxFunc() const {
0334 return (SubclassOptionalData & FastMathFlags::ApproxFunc) != 0;
0335 }
0336
0337
0338 FastMathFlags getFastMathFlags() const {
0339 return FastMathFlags(SubclassOptionalData);
0340 }
0341
0342
0343
0344
0345 float getFPAccuracy() const;
0346
0347
0348
0349 static bool isSupportedFloatingPointType(Type *Ty) {
0350 return Ty->isFPOrFPVectorTy() ||
0351 isComposedOfHomogeneousFloatingPointTypes(Ty);
0352 }
0353
0354 static bool classof(const Value *V) {
0355 unsigned Opcode;
0356 if (auto *I = dyn_cast<Instruction>(V))
0357 Opcode = I->getOpcode();
0358 else
0359 return false;
0360
0361 switch (Opcode) {
0362 case Instruction::FNeg:
0363 case Instruction::FAdd:
0364 case Instruction::FSub:
0365 case Instruction::FMul:
0366 case Instruction::FDiv:
0367 case Instruction::FRem:
0368 case Instruction::FPTrunc:
0369 case Instruction::FPExt:
0370
0371
0372
0373
0374
0375 case Instruction::FCmp:
0376 return true;
0377 case Instruction::PHI:
0378 case Instruction::Select:
0379 case Instruction::Call: {
0380 return isSupportedFloatingPointType(V->getType());
0381 }
0382 default:
0383 return false;
0384 }
0385 }
0386 };
0387
0388
0389 template<typename SuperClass, unsigned Opc>
0390 class ConcreteOperator : public SuperClass {
0391 public:
0392 static bool classof(const Instruction *I) {
0393 return I->getOpcode() == Opc;
0394 }
0395 static bool classof(const ConstantExpr *CE) {
0396 return CE->getOpcode() == Opc;
0397 }
0398 static bool classof(const Value *V) {
0399 return (isa<Instruction>(V) && classof(cast<Instruction>(V))) ||
0400 (isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V)));
0401 }
0402 };
0403
0404 class AddOperator
0405 : public ConcreteOperator<OverflowingBinaryOperator, Instruction::Add> {
0406 };
0407 class SubOperator
0408 : public ConcreteOperator<OverflowingBinaryOperator, Instruction::Sub> {
0409 };
0410 class MulOperator
0411 : public ConcreteOperator<OverflowingBinaryOperator, Instruction::Mul> {
0412 };
0413 class ShlOperator
0414 : public ConcreteOperator<OverflowingBinaryOperator, Instruction::Shl> {
0415 };
0416
0417 class AShrOperator
0418 : public ConcreteOperator<PossiblyExactOperator, Instruction::AShr> {
0419 };
0420 class LShrOperator
0421 : public ConcreteOperator<PossiblyExactOperator, Instruction::LShr> {
0422 };
0423
0424 class GEPOperator
0425 : public ConcreteOperator<Operator, Instruction::GetElementPtr> {
0426 public:
0427
0428 DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
0429
0430 GEPNoWrapFlags getNoWrapFlags() const {
0431 return GEPNoWrapFlags::fromRaw(SubclassOptionalData);
0432 }
0433
0434
0435 bool isInBounds() const { return getNoWrapFlags().isInBounds(); }
0436
0437 bool hasNoUnsignedSignedWrap() const {
0438 return getNoWrapFlags().hasNoUnsignedSignedWrap();
0439 }
0440
0441 bool hasNoUnsignedWrap() const {
0442 return getNoWrapFlags().hasNoUnsignedWrap();
0443 }
0444
0445
0446
0447 std::optional<ConstantRange> getInRange() const;
0448
0449 inline op_iterator idx_begin() { return op_begin()+1; }
0450 inline const_op_iterator idx_begin() const { return op_begin()+1; }
0451 inline op_iterator idx_end() { return op_end(); }
0452 inline const_op_iterator idx_end() const { return op_end(); }
0453
0454 inline iterator_range<op_iterator> indices() {
0455 return make_range(idx_begin(), idx_end());
0456 }
0457
0458 inline iterator_range<const_op_iterator> indices() const {
0459 return make_range(idx_begin(), idx_end());
0460 }
0461
0462 Value *getPointerOperand() {
0463 return getOperand(0);
0464 }
0465 const Value *getPointerOperand() const {
0466 return getOperand(0);
0467 }
0468 static unsigned getPointerOperandIndex() {
0469 return 0U;
0470 }
0471
0472
0473 Type *getPointerOperandType() const {
0474 return getPointerOperand()->getType();
0475 }
0476
0477 Type *getSourceElementType() const;
0478 Type *getResultElementType() const;
0479
0480
0481 unsigned getPointerAddressSpace() const {
0482 return getPointerOperandType()->getPointerAddressSpace();
0483 }
0484
0485 unsigned getNumIndices() const {
0486 return getNumOperands() - 1;
0487 }
0488
0489 bool hasIndices() const {
0490 return getNumOperands() > 1;
0491 }
0492
0493
0494
0495
0496 bool hasAllZeroIndices() const {
0497 for (const_op_iterator I = idx_begin(), E = idx_end(); I != E; ++I) {
0498 if (ConstantInt *C = dyn_cast<ConstantInt>(I))
0499 if (C->isZero())
0500 continue;
0501 return false;
0502 }
0503 return true;
0504 }
0505
0506
0507
0508
0509 bool hasAllConstantIndices() const {
0510 for (const_op_iterator I = idx_begin(), E = idx_end(); I != E; ++I) {
0511 if (!isa<ConstantInt>(I))
0512 return false;
0513 }
0514 return true;
0515 }
0516
0517 unsigned countNonConstantIndices() const {
0518 return count_if(indices(), [](const Use& use) {
0519 return !isa<ConstantInt>(*use);
0520 });
0521 }
0522
0523
0524 Align getMaxPreservedAlignment(const DataLayout &DL) const;
0525
0526
0527
0528
0529
0530
0531
0532
0533
0534
0535
0536
0537
0538
0539
0540
0541
0542
0543 bool accumulateConstantOffset(
0544 const DataLayout &DL, APInt &Offset,
0545 function_ref<bool(Value &, APInt &)> ExternalAnalysis = nullptr) const;
0546
0547 static bool accumulateConstantOffset(
0548 Type *SourceType, ArrayRef<const Value *> Index, const DataLayout &DL,
0549 APInt &Offset,
0550 function_ref<bool(Value &, APInt &)> ExternalAnalysis = nullptr);
0551
0552
0553
0554 bool collectOffset(const DataLayout &DL, unsigned BitWidth,
0555 SmallMapVector<Value *, APInt, 4> &VariableOffsets,
0556 APInt &ConstantOffset) const;
0557 };
0558
0559 template <>
0560 struct OperandTraits<GEPOperator> : public VariadicOperandTraits<GEPOperator> {
0561 };
0562
0563 DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GEPOperator, Value)
0564
0565 class PtrToIntOperator
0566 : public ConcreteOperator<Operator, Instruction::PtrToInt> {
0567 friend class PtrToInt;
0568 friend class ConstantExpr;
0569
0570 public:
0571
0572 DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
0573
0574 Value *getPointerOperand() {
0575 return getOperand(0);
0576 }
0577 const Value *getPointerOperand() const {
0578 return getOperand(0);
0579 }
0580
0581 static unsigned getPointerOperandIndex() {
0582 return 0U;
0583 }
0584
0585
0586 Type *getPointerOperandType() const {
0587 return getPointerOperand()->getType();
0588 }
0589
0590
0591 unsigned getPointerAddressSpace() const {
0592 return cast<PointerType>(getPointerOperandType())->getAddressSpace();
0593 }
0594 };
0595
0596 template <>
0597 struct OperandTraits<PtrToIntOperator>
0598 : public FixedNumOperandTraits<PtrToIntOperator, 1> {};
0599
0600 DEFINE_TRANSPARENT_OPERAND_ACCESSORS(PtrToIntOperator, Value)
0601
0602 class BitCastOperator
0603 : public ConcreteOperator<Operator, Instruction::BitCast> {
0604 friend class BitCastInst;
0605 friend class ConstantExpr;
0606
0607 public:
0608
0609 DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
0610
0611 Type *getSrcTy() const {
0612 return getOperand(0)->getType();
0613 }
0614
0615 Type *getDestTy() const {
0616 return getType();
0617 }
0618 };
0619
0620 template <>
0621 struct OperandTraits<BitCastOperator>
0622 : public FixedNumOperandTraits<BitCastOperator, 1> {};
0623
0624 DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BitCastOperator, Value)
0625
0626 class AddrSpaceCastOperator
0627 : public ConcreteOperator<Operator, Instruction::AddrSpaceCast> {
0628 friend class AddrSpaceCastInst;
0629 friend class ConstantExpr;
0630
0631 public:
0632
0633 DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
0634
0635 Value *getPointerOperand() { return getOperand(0); }
0636
0637 const Value *getPointerOperand() const { return getOperand(0); }
0638
0639 unsigned getSrcAddressSpace() const {
0640 return getPointerOperand()->getType()->getPointerAddressSpace();
0641 }
0642
0643 unsigned getDestAddressSpace() const {
0644 return getType()->getPointerAddressSpace();
0645 }
0646 };
0647
0648 template <>
0649 struct OperandTraits<AddrSpaceCastOperator>
0650 : public FixedNumOperandTraits<AddrSpaceCastOperator, 1> {};
0651
0652 DEFINE_TRANSPARENT_OPERAND_ACCESSORS(AddrSpaceCastOperator, Value)
0653
0654 }
0655
0656 #endif