1 //===- ConstantFolder.h - Constant folding helper ---------------*- 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 // This file defines the ConstantFolder class, a helper for IRBuilder. 10 // It provides IRBuilder with a set of methods for creating constants 11 // with minimal folding. For general constant creation and folding, 12 // use ConstantExpr and the routines in llvm/Analysis/ConstantFolding.h. 13 // 14 //===----------------------------------------------------------------------===// 15 16 #ifndef LLVM_IR_CONSTANTFOLDER_H 17 #define LLVM_IR_CONSTANTFOLDER_H 18 19 #include "llvm/ADT/ArrayRef.h" 20 #include "llvm/ADT/STLExtras.h" 21 #include "llvm/IR/Constants.h" 22 #include "llvm/IR/ConstantFold.h" 23 #include "llvm/IR/IRBuilderFolder.h" 24 #include "llvm/IR/Instruction.h" 25 #include "llvm/IR/Operator.h" 26 27 namespace llvm { 28 29 /// ConstantFolder - Create constants with minimum, target independent, folding. 30 class ConstantFolder final : public IRBuilderFolder { 31 virtual void anchor(); 32 33 public: 34 explicit ConstantFolder() = default; 35 36 //===--------------------------------------------------------------------===// 37 // Value-based folders. 38 // 39 // Return an existing value or a constant if the operation can be simplified. 40 // Otherwise return nullptr. 41 //===--------------------------------------------------------------------===// 42 43 Value *FoldBinOp(Instruction::BinaryOps Opc, Value *LHS, 44 Value *RHS) const override { 45 auto *LC = dyn_cast<Constant>(LHS); 46 auto *RC = dyn_cast<Constant>(RHS); 47 if (LC && RC) 48 return ConstantExpr::get(Opc, LC, RC); 49 return nullptr; 50 } 51 52 Value *FoldExactBinOp(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, 53 bool IsExact) const override { 54 auto *LC = dyn_cast<Constant>(LHS); 55 auto *RC = dyn_cast<Constant>(RHS); 56 if (LC && RC) 57 return ConstantExpr::get(Opc, LC, RC, 58 IsExact ? PossiblyExactOperator::IsExact : 0); 59 return nullptr; 60 } 61 62 Value *FoldNoWrapBinOp(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, 63 bool HasNUW, bool HasNSW) const override { 64 auto *LC = dyn_cast<Constant>(LHS); 65 auto *RC = dyn_cast<Constant>(RHS); 66 if (LC && RC) { 67 unsigned Flags = 0; 68 if (HasNUW) 69 Flags |= OverflowingBinaryOperator::NoUnsignedWrap; 70 if (HasNSW) 71 Flags |= OverflowingBinaryOperator::NoSignedWrap; 72 return ConstantExpr::get(Opc, LC, RC, Flags); 73 } 74 return nullptr; 75 } 76 77 Value *FoldBinOpFMF(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, 78 FastMathFlags FMF) const override { 79 return FoldBinOp(Opc, LHS, RHS); 80 } 81 82 Value *FoldICmp(CmpInst::Predicate P, Value *LHS, Value *RHS) const override { 83 auto *LC = dyn_cast<Constant>(LHS); 84 auto *RC = dyn_cast<Constant>(RHS); 85 if (LC && RC) 86 return ConstantExpr::getCompare(P, LC, RC); 87 return nullptr; 88 } 89 90 Value *FoldGEP(Type *Ty, Value *Ptr, ArrayRef<Value *> IdxList, 91 bool IsInBounds = false) const override { 92 if (auto *PC = dyn_cast<Constant>(Ptr)) { 93 // Every index must be constant. 94 if (any_of(IdxList, [](Value *V) { return !isa<Constant>(V); })) 95 return nullptr; 96 97 if (IsInBounds) 98 return ConstantExpr::getInBoundsGetElementPtr(Ty, PC, IdxList); 99 else 100 return ConstantExpr::getGetElementPtr(Ty, PC, IdxList); 101 } 102 return nullptr; 103 } 104 105 Value *FoldSelect(Value *C, Value *True, Value *False) const override { 106 auto *CC = dyn_cast<Constant>(C); 107 auto *TC = dyn_cast<Constant>(True); 108 auto *FC = dyn_cast<Constant>(False); 109 if (CC && TC && FC) 110 return ConstantExpr::getSelect(CC, TC, FC); 111 return nullptr; 112 } 113 114 Value *FoldExtractValue(Value *Agg, 115 ArrayRef<unsigned> IdxList) const override { 116 if (auto *CAgg = dyn_cast<Constant>(Agg)) 117 return ConstantFoldExtractValueInstruction(CAgg, IdxList); 118 return nullptr; 119 }; 120 121 Value *FoldInsertValue(Value *Agg, Value *Val, 122 ArrayRef<unsigned> IdxList) const override { 123 auto *CAgg = dyn_cast<Constant>(Agg); 124 auto *CVal = dyn_cast<Constant>(Val); 125 if (CAgg && CVal) 126 return ConstantFoldInsertValueInstruction(CAgg, CVal, IdxList); 127 return nullptr; 128 } 129 130 Value *FoldExtractElement(Value *Vec, Value *Idx) const override { 131 auto *CVec = dyn_cast<Constant>(Vec); 132 auto *CIdx = dyn_cast<Constant>(Idx); 133 if (CVec && CIdx) 134 return ConstantExpr::getExtractElement(CVec, CIdx); 135 return nullptr; 136 } 137 138 Value *FoldInsertElement(Value *Vec, Value *NewElt, 139 Value *Idx) const override { 140 auto *CVec = dyn_cast<Constant>(Vec); 141 auto *CNewElt = dyn_cast<Constant>(NewElt); 142 auto *CIdx = dyn_cast<Constant>(Idx); 143 if (CVec && CNewElt && CIdx) 144 return ConstantExpr::getInsertElement(CVec, CNewElt, CIdx); 145 return nullptr; 146 } 147 148 Value *FoldShuffleVector(Value *V1, Value *V2, 149 ArrayRef<int> Mask) const override { 150 auto *C1 = dyn_cast<Constant>(V1); 151 auto *C2 = dyn_cast<Constant>(V2); 152 if (C1 && C2) 153 return ConstantExpr::getShuffleVector(C1, C2, Mask); 154 return nullptr; 155 } 156 157 //===--------------------------------------------------------------------===// 158 // Unary Operators 159 //===--------------------------------------------------------------------===// 160 161 Constant *CreateFNeg(Constant *C) const override { 162 return ConstantExpr::getFNeg(C); 163 } 164 165 Constant *CreateUnOp(Instruction::UnaryOps Opc, Constant *C) const override { 166 return ConstantExpr::get(Opc, C); 167 } 168 169 //===--------------------------------------------------------------------===// 170 // Cast/Conversion Operators 171 //===--------------------------------------------------------------------===// 172 173 Constant *CreateCast(Instruction::CastOps Op, Constant *C, 174 Type *DestTy) const override { 175 return ConstantExpr::getCast(Op, C, DestTy); 176 } 177 178 Constant *CreatePointerCast(Constant *C, Type *DestTy) const override { 179 return ConstantExpr::getPointerCast(C, DestTy); 180 } 181 182 Constant *CreatePointerBitCastOrAddrSpaceCast(Constant *C, 183 Type *DestTy) const override { 184 return ConstantExpr::getPointerBitCastOrAddrSpaceCast(C, DestTy); 185 } 186 187 Constant *CreateIntCast(Constant *C, Type *DestTy, 188 bool isSigned) const override { 189 return ConstantExpr::getIntegerCast(C, DestTy, isSigned); 190 } 191 192 Constant *CreateFPCast(Constant *C, Type *DestTy) const override { 193 return ConstantExpr::getFPCast(C, DestTy); 194 } 195 196 Constant *CreateBitCast(Constant *C, Type *DestTy) const override { 197 return CreateCast(Instruction::BitCast, C, DestTy); 198 } 199 200 Constant *CreateIntToPtr(Constant *C, Type *DestTy) const override { 201 return CreateCast(Instruction::IntToPtr, C, DestTy); 202 } 203 204 Constant *CreatePtrToInt(Constant *C, Type *DestTy) const override { 205 return CreateCast(Instruction::PtrToInt, C, DestTy); 206 } 207 208 Constant *CreateZExtOrBitCast(Constant *C, Type *DestTy) const override { 209 return ConstantExpr::getZExtOrBitCast(C, DestTy); 210 } 211 212 Constant *CreateSExtOrBitCast(Constant *C, Type *DestTy) const override { 213 return ConstantExpr::getSExtOrBitCast(C, DestTy); 214 } 215 216 Constant *CreateTruncOrBitCast(Constant *C, Type *DestTy) const override { 217 return ConstantExpr::getTruncOrBitCast(C, DestTy); 218 } 219 220 //===--------------------------------------------------------------------===// 221 // Compare Instructions 222 //===--------------------------------------------------------------------===// 223 224 Constant *CreateFCmp(CmpInst::Predicate P, Constant *LHS, 225 Constant *RHS) const override { 226 return ConstantExpr::getCompare(P, LHS, RHS); 227 } 228 }; 229 230 } // end namespace llvm 231 232 #endif // LLVM_IR_CONSTANTFOLDER_H 233