File indexing completed on 2026-05-10 08:43:57
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #ifndef LLVM_IR_CONSTANTFOLDER_H
0017 #define LLVM_IR_CONSTANTFOLDER_H
0018
0019 #include "llvm/ADT/ArrayRef.h"
0020 #include "llvm/ADT/STLExtras.h"
0021 #include "llvm/IR/ConstantFold.h"
0022 #include "llvm/IR/Constants.h"
0023 #include "llvm/IR/IRBuilderFolder.h"
0024 #include "llvm/IR/Instruction.h"
0025 #include "llvm/IR/Operator.h"
0026
0027 namespace llvm {
0028
0029
0030 class ConstantFolder final : public IRBuilderFolder {
0031 virtual void anchor();
0032
0033 public:
0034 explicit ConstantFolder() = default;
0035
0036
0037
0038
0039
0040
0041
0042
0043 Value *FoldBinOp(Instruction::BinaryOps Opc, Value *LHS,
0044 Value *RHS) const override {
0045 auto *LC = dyn_cast<Constant>(LHS);
0046 auto *RC = dyn_cast<Constant>(RHS);
0047 if (LC && RC) {
0048 if (ConstantExpr::isDesirableBinOp(Opc))
0049 return ConstantExpr::get(Opc, LC, RC);
0050 return ConstantFoldBinaryInstruction(Opc, LC, RC);
0051 }
0052 return nullptr;
0053 }
0054
0055 Value *FoldExactBinOp(Instruction::BinaryOps Opc, Value *LHS, Value *RHS,
0056 bool IsExact) const override {
0057 auto *LC = dyn_cast<Constant>(LHS);
0058 auto *RC = dyn_cast<Constant>(RHS);
0059 if (LC && RC) {
0060 if (ConstantExpr::isDesirableBinOp(Opc))
0061 return ConstantExpr::get(Opc, LC, RC,
0062 IsExact ? PossiblyExactOperator::IsExact : 0);
0063 return ConstantFoldBinaryInstruction(Opc, LC, RC);
0064 }
0065 return nullptr;
0066 }
0067
0068 Value *FoldNoWrapBinOp(Instruction::BinaryOps Opc, Value *LHS, Value *RHS,
0069 bool HasNUW, bool HasNSW) const override {
0070 auto *LC = dyn_cast<Constant>(LHS);
0071 auto *RC = dyn_cast<Constant>(RHS);
0072 if (LC && RC) {
0073 if (ConstantExpr::isDesirableBinOp(Opc)) {
0074 unsigned Flags = 0;
0075 if (HasNUW)
0076 Flags |= OverflowingBinaryOperator::NoUnsignedWrap;
0077 if (HasNSW)
0078 Flags |= OverflowingBinaryOperator::NoSignedWrap;
0079 return ConstantExpr::get(Opc, LC, RC, Flags);
0080 }
0081 return ConstantFoldBinaryInstruction(Opc, LC, RC);
0082 }
0083 return nullptr;
0084 }
0085
0086 Value *FoldBinOpFMF(Instruction::BinaryOps Opc, Value *LHS, Value *RHS,
0087 FastMathFlags FMF) const override {
0088 return FoldBinOp(Opc, LHS, RHS);
0089 }
0090
0091 Value *FoldUnOpFMF(Instruction::UnaryOps Opc, Value *V,
0092 FastMathFlags FMF) const override {
0093 if (Constant *C = dyn_cast<Constant>(V))
0094 return ConstantFoldUnaryInstruction(Opc, C);
0095 return nullptr;
0096 }
0097
0098 Value *FoldCmp(CmpInst::Predicate P, Value *LHS, Value *RHS) const override {
0099 auto *LC = dyn_cast<Constant>(LHS);
0100 auto *RC = dyn_cast<Constant>(RHS);
0101 if (LC && RC)
0102 return ConstantFoldCompareInstruction(P, LC, RC);
0103 return nullptr;
0104 }
0105
0106 Value *FoldGEP(Type *Ty, Value *Ptr, ArrayRef<Value *> IdxList,
0107 GEPNoWrapFlags NW) const override {
0108 if (!ConstantExpr::isSupportedGetElementPtr(Ty))
0109 return nullptr;
0110
0111 if (auto *PC = dyn_cast<Constant>(Ptr)) {
0112
0113 if (any_of(IdxList, [](Value *V) { return !isa<Constant>(V); }))
0114 return nullptr;
0115
0116 return ConstantExpr::getGetElementPtr(Ty, PC, IdxList, NW);
0117 }
0118 return nullptr;
0119 }
0120
0121 Value *FoldSelect(Value *C, Value *True, Value *False) const override {
0122 auto *CC = dyn_cast<Constant>(C);
0123 auto *TC = dyn_cast<Constant>(True);
0124 auto *FC = dyn_cast<Constant>(False);
0125 if (CC && TC && FC)
0126 return ConstantFoldSelectInstruction(CC, TC, FC);
0127 return nullptr;
0128 }
0129
0130 Value *FoldExtractValue(Value *Agg,
0131 ArrayRef<unsigned> IdxList) const override {
0132 if (auto *CAgg = dyn_cast<Constant>(Agg))
0133 return ConstantFoldExtractValueInstruction(CAgg, IdxList);
0134 return nullptr;
0135 };
0136
0137 Value *FoldInsertValue(Value *Agg, Value *Val,
0138 ArrayRef<unsigned> IdxList) const override {
0139 auto *CAgg = dyn_cast<Constant>(Agg);
0140 auto *CVal = dyn_cast<Constant>(Val);
0141 if (CAgg && CVal)
0142 return ConstantFoldInsertValueInstruction(CAgg, CVal, IdxList);
0143 return nullptr;
0144 }
0145
0146 Value *FoldExtractElement(Value *Vec, Value *Idx) const override {
0147 auto *CVec = dyn_cast<Constant>(Vec);
0148 auto *CIdx = dyn_cast<Constant>(Idx);
0149 if (CVec && CIdx)
0150 return ConstantExpr::getExtractElement(CVec, CIdx);
0151 return nullptr;
0152 }
0153
0154 Value *FoldInsertElement(Value *Vec, Value *NewElt,
0155 Value *Idx) const override {
0156 auto *CVec = dyn_cast<Constant>(Vec);
0157 auto *CNewElt = dyn_cast<Constant>(NewElt);
0158 auto *CIdx = dyn_cast<Constant>(Idx);
0159 if (CVec && CNewElt && CIdx)
0160 return ConstantExpr::getInsertElement(CVec, CNewElt, CIdx);
0161 return nullptr;
0162 }
0163
0164 Value *FoldShuffleVector(Value *V1, Value *V2,
0165 ArrayRef<int> Mask) const override {
0166 auto *C1 = dyn_cast<Constant>(V1);
0167 auto *C2 = dyn_cast<Constant>(V2);
0168 if (C1 && C2)
0169 return ConstantExpr::getShuffleVector(C1, C2, Mask);
0170 return nullptr;
0171 }
0172
0173 Value *FoldCast(Instruction::CastOps Op, Value *V,
0174 Type *DestTy) const override {
0175 if (auto *C = dyn_cast<Constant>(V)) {
0176 if (ConstantExpr::isDesirableCastOp(Op))
0177 return ConstantExpr::getCast(Op, C, DestTy);
0178 return ConstantFoldCastInstruction(Op, C, DestTy);
0179 }
0180 return nullptr;
0181 }
0182
0183 Value *FoldBinaryIntrinsic(Intrinsic::ID ID, Value *LHS, Value *RHS, Type *Ty,
0184 Instruction *FMFSource) const override {
0185
0186 return nullptr;
0187 }
0188
0189
0190
0191
0192
0193 Constant *CreatePointerCast(Constant *C, Type *DestTy) const override {
0194 return ConstantExpr::getPointerCast(C, DestTy);
0195 }
0196
0197 Constant *CreatePointerBitCastOrAddrSpaceCast(Constant *C,
0198 Type *DestTy) const override {
0199 return ConstantExpr::getPointerBitCastOrAddrSpaceCast(C, DestTy);
0200 }
0201 };
0202
0203 }
0204
0205 #endif