1 //===- NoFolder.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 NoFolder class, a helper for IRBuilder. It provides 10 // IRBuilder with a set of methods for creating unfolded constants. This is 11 // useful for learners trying to understand how LLVM IR works, and who don't 12 // want details to be hidden by the constant folder. For general constant 13 // creation and folding, use ConstantExpr and the routines in 14 // llvm/Analysis/ConstantFolding.h. 15 // 16 // Note: since it is not actually possible to create unfolded constants, this 17 // class returns instructions rather than constants. 18 // 19 //===----------------------------------------------------------------------===// 20 21 #ifndef LLVM_IR_NOFOLDER_H 22 #define LLVM_IR_NOFOLDER_H 23 24 #include "llvm/ADT/ArrayRef.h" 25 #include "llvm/IR/Constants.h" 26 #include "llvm/IR/InstrTypes.h" 27 #include "llvm/IR/Instruction.h" 28 #include "llvm/IR/Instructions.h" 29 30 namespace llvm { 31 32 /// NoFolder - Create "constants" (actually, instructions) with no folding. 33 class NoFolder { 34 public: 35 explicit NoFolder() = default; 36 37 //===--------------------------------------------------------------------===// 38 // Binary Operators 39 //===--------------------------------------------------------------------===// 40 41 Instruction *CreateAdd(Constant *LHS, Constant *RHS, 42 bool HasNUW = false, bool HasNSW = false) const { 43 BinaryOperator *BO = BinaryOperator::CreateAdd(LHS, RHS); 44 if (HasNUW) BO->setHasNoUnsignedWrap(); 45 if (HasNSW) BO->setHasNoSignedWrap(); 46 return BO; 47 } 48 CreateNSWAdd(Constant * LHS,Constant * RHS)49 Instruction *CreateNSWAdd(Constant *LHS, Constant *RHS) const { 50 return BinaryOperator::CreateNSWAdd(LHS, RHS); 51 } 52 CreateNUWAdd(Constant * LHS,Constant * RHS)53 Instruction *CreateNUWAdd(Constant *LHS, Constant *RHS) const { 54 return BinaryOperator::CreateNUWAdd(LHS, RHS); 55 } 56 CreateFAdd(Constant * LHS,Constant * RHS)57 Instruction *CreateFAdd(Constant *LHS, Constant *RHS) const { 58 return BinaryOperator::CreateFAdd(LHS, RHS); 59 } 60 61 Instruction *CreateSub(Constant *LHS, Constant *RHS, 62 bool HasNUW = false, bool HasNSW = false) const { 63 BinaryOperator *BO = BinaryOperator::CreateSub(LHS, RHS); 64 if (HasNUW) BO->setHasNoUnsignedWrap(); 65 if (HasNSW) BO->setHasNoSignedWrap(); 66 return BO; 67 } 68 CreateNSWSub(Constant * LHS,Constant * RHS)69 Instruction *CreateNSWSub(Constant *LHS, Constant *RHS) const { 70 return BinaryOperator::CreateNSWSub(LHS, RHS); 71 } 72 CreateNUWSub(Constant * LHS,Constant * RHS)73 Instruction *CreateNUWSub(Constant *LHS, Constant *RHS) const { 74 return BinaryOperator::CreateNUWSub(LHS, RHS); 75 } 76 CreateFSub(Constant * LHS,Constant * RHS)77 Instruction *CreateFSub(Constant *LHS, Constant *RHS) const { 78 return BinaryOperator::CreateFSub(LHS, RHS); 79 } 80 81 Instruction *CreateMul(Constant *LHS, Constant *RHS, 82 bool HasNUW = false, bool HasNSW = false) const { 83 BinaryOperator *BO = BinaryOperator::CreateMul(LHS, RHS); 84 if (HasNUW) BO->setHasNoUnsignedWrap(); 85 if (HasNSW) BO->setHasNoSignedWrap(); 86 return BO; 87 } 88 CreateNSWMul(Constant * LHS,Constant * RHS)89 Instruction *CreateNSWMul(Constant *LHS, Constant *RHS) const { 90 return BinaryOperator::CreateNSWMul(LHS, RHS); 91 } 92 CreateNUWMul(Constant * LHS,Constant * RHS)93 Instruction *CreateNUWMul(Constant *LHS, Constant *RHS) const { 94 return BinaryOperator::CreateNUWMul(LHS, RHS); 95 } 96 CreateFMul(Constant * LHS,Constant * RHS)97 Instruction *CreateFMul(Constant *LHS, Constant *RHS) const { 98 return BinaryOperator::CreateFMul(LHS, RHS); 99 } 100 101 Instruction *CreateUDiv(Constant *LHS, Constant *RHS, 102 bool isExact = false) const { 103 if (!isExact) 104 return BinaryOperator::CreateUDiv(LHS, RHS); 105 return BinaryOperator::CreateExactUDiv(LHS, RHS); 106 } 107 CreateExactUDiv(Constant * LHS,Constant * RHS)108 Instruction *CreateExactUDiv(Constant *LHS, Constant *RHS) const { 109 return BinaryOperator::CreateExactUDiv(LHS, RHS); 110 } 111 112 Instruction *CreateSDiv(Constant *LHS, Constant *RHS, 113 bool isExact = false) const { 114 if (!isExact) 115 return BinaryOperator::CreateSDiv(LHS, RHS); 116 return BinaryOperator::CreateExactSDiv(LHS, RHS); 117 } 118 CreateExactSDiv(Constant * LHS,Constant * RHS)119 Instruction *CreateExactSDiv(Constant *LHS, Constant *RHS) const { 120 return BinaryOperator::CreateExactSDiv(LHS, RHS); 121 } 122 CreateFDiv(Constant * LHS,Constant * RHS)123 Instruction *CreateFDiv(Constant *LHS, Constant *RHS) const { 124 return BinaryOperator::CreateFDiv(LHS, RHS); 125 } 126 CreateURem(Constant * LHS,Constant * RHS)127 Instruction *CreateURem(Constant *LHS, Constant *RHS) const { 128 return BinaryOperator::CreateURem(LHS, RHS); 129 } 130 CreateSRem(Constant * LHS,Constant * RHS)131 Instruction *CreateSRem(Constant *LHS, Constant *RHS) const { 132 return BinaryOperator::CreateSRem(LHS, RHS); 133 } 134 CreateFRem(Constant * LHS,Constant * RHS)135 Instruction *CreateFRem(Constant *LHS, Constant *RHS) const { 136 return BinaryOperator::CreateFRem(LHS, RHS); 137 } 138 139 Instruction *CreateShl(Constant *LHS, Constant *RHS, bool HasNUW = false, 140 bool HasNSW = false) const { 141 BinaryOperator *BO = BinaryOperator::CreateShl(LHS, RHS); 142 if (HasNUW) BO->setHasNoUnsignedWrap(); 143 if (HasNSW) BO->setHasNoSignedWrap(); 144 return BO; 145 } 146 147 Instruction *CreateLShr(Constant *LHS, Constant *RHS, 148 bool isExact = false) const { 149 if (!isExact) 150 return BinaryOperator::CreateLShr(LHS, RHS); 151 return BinaryOperator::CreateExactLShr(LHS, RHS); 152 } 153 154 Instruction *CreateAShr(Constant *LHS, Constant *RHS, 155 bool isExact = false) const { 156 if (!isExact) 157 return BinaryOperator::CreateAShr(LHS, RHS); 158 return BinaryOperator::CreateExactAShr(LHS, RHS); 159 } 160 CreateAnd(Constant * LHS,Constant * RHS)161 Instruction *CreateAnd(Constant *LHS, Constant *RHS) const { 162 return BinaryOperator::CreateAnd(LHS, RHS); 163 } 164 CreateOr(Constant * LHS,Constant * RHS)165 Instruction *CreateOr(Constant *LHS, Constant *RHS) const { 166 return BinaryOperator::CreateOr(LHS, RHS); 167 } 168 CreateXor(Constant * LHS,Constant * RHS)169 Instruction *CreateXor(Constant *LHS, Constant *RHS) const { 170 return BinaryOperator::CreateXor(LHS, RHS); 171 } 172 CreateBinOp(Instruction::BinaryOps Opc,Constant * LHS,Constant * RHS)173 Instruction *CreateBinOp(Instruction::BinaryOps Opc, 174 Constant *LHS, Constant *RHS) const { 175 return BinaryOperator::Create(Opc, LHS, RHS); 176 } 177 178 //===--------------------------------------------------------------------===// 179 // Unary Operators 180 //===--------------------------------------------------------------------===// 181 182 Instruction *CreateNeg(Constant *C, 183 bool HasNUW = false, bool HasNSW = false) const { 184 BinaryOperator *BO = BinaryOperator::CreateNeg(C); 185 if (HasNUW) BO->setHasNoUnsignedWrap(); 186 if (HasNSW) BO->setHasNoSignedWrap(); 187 return BO; 188 } 189 CreateNSWNeg(Constant * C)190 Instruction *CreateNSWNeg(Constant *C) const { 191 return BinaryOperator::CreateNSWNeg(C); 192 } 193 CreateNUWNeg(Constant * C)194 Instruction *CreateNUWNeg(Constant *C) const { 195 return BinaryOperator::CreateNUWNeg(C); 196 } 197 CreateFNeg(Constant * C)198 Instruction *CreateFNeg(Constant *C) const { 199 return UnaryOperator::CreateFNeg(C); 200 } 201 CreateNot(Constant * C)202 Instruction *CreateNot(Constant *C) const { 203 return BinaryOperator::CreateNot(C); 204 } 205 CreateUnOp(Instruction::UnaryOps Opc,Constant * C)206 Instruction *CreateUnOp(Instruction::UnaryOps Opc, Constant *C) const { 207 return UnaryOperator::Create(Opc, C); 208 } 209 210 //===--------------------------------------------------------------------===// 211 // Memory Instructions 212 //===--------------------------------------------------------------------===// 213 CreateGetElementPtr(Type * Ty,Constant * C,ArrayRef<Constant * > IdxList)214 Constant *CreateGetElementPtr(Type *Ty, Constant *C, 215 ArrayRef<Constant *> IdxList) const { 216 return ConstantExpr::getGetElementPtr(Ty, C, IdxList); 217 } 218 CreateGetElementPtr(Type * Ty,Constant * C,Constant * Idx)219 Constant *CreateGetElementPtr(Type *Ty, Constant *C, Constant *Idx) const { 220 // This form of the function only exists to avoid ambiguous overload 221 // warnings about whether to convert Idx to ArrayRef<Constant *> or 222 // ArrayRef<Value *>. 223 return ConstantExpr::getGetElementPtr(Ty, C, Idx); 224 } 225 CreateGetElementPtr(Type * Ty,Constant * C,ArrayRef<Value * > IdxList)226 Instruction *CreateGetElementPtr(Type *Ty, Constant *C, 227 ArrayRef<Value *> IdxList) const { 228 return GetElementPtrInst::Create(Ty, C, IdxList); 229 } 230 CreateInBoundsGetElementPtr(Type * Ty,Constant * C,ArrayRef<Constant * > IdxList)231 Constant *CreateInBoundsGetElementPtr(Type *Ty, Constant *C, 232 ArrayRef<Constant *> IdxList) const { 233 return ConstantExpr::getInBoundsGetElementPtr(Ty, C, IdxList); 234 } 235 CreateInBoundsGetElementPtr(Type * Ty,Constant * C,Constant * Idx)236 Constant *CreateInBoundsGetElementPtr(Type *Ty, Constant *C, 237 Constant *Idx) const { 238 // This form of the function only exists to avoid ambiguous overload 239 // warnings about whether to convert Idx to ArrayRef<Constant *> or 240 // ArrayRef<Value *>. 241 return ConstantExpr::getInBoundsGetElementPtr(Ty, C, Idx); 242 } 243 CreateInBoundsGetElementPtr(Type * Ty,Constant * C,ArrayRef<Value * > IdxList)244 Instruction *CreateInBoundsGetElementPtr(Type *Ty, Constant *C, 245 ArrayRef<Value *> IdxList) const { 246 return GetElementPtrInst::CreateInBounds(Ty, C, IdxList); 247 } 248 249 //===--------------------------------------------------------------------===// 250 // Cast/Conversion Operators 251 //===--------------------------------------------------------------------===// 252 CreateCast(Instruction::CastOps Op,Constant * C,Type * DestTy)253 Instruction *CreateCast(Instruction::CastOps Op, Constant *C, 254 Type *DestTy) const { 255 return CastInst::Create(Op, C, DestTy); 256 } 257 CreatePointerCast(Constant * C,Type * DestTy)258 Instruction *CreatePointerCast(Constant *C, Type *DestTy) const { 259 return CastInst::CreatePointerCast(C, DestTy); 260 } 261 CreateIntCast(Constant * C,Type * DestTy,bool isSigned)262 Instruction *CreateIntCast(Constant *C, Type *DestTy, 263 bool isSigned) const { 264 return CastInst::CreateIntegerCast(C, DestTy, isSigned); 265 } 266 CreateFPCast(Constant * C,Type * DestTy)267 Instruction *CreateFPCast(Constant *C, Type *DestTy) const { 268 return CastInst::CreateFPCast(C, DestTy); 269 } 270 CreateBitCast(Constant * C,Type * DestTy)271 Instruction *CreateBitCast(Constant *C, Type *DestTy) const { 272 return CreateCast(Instruction::BitCast, C, DestTy); 273 } 274 CreateIntToPtr(Constant * C,Type * DestTy)275 Instruction *CreateIntToPtr(Constant *C, Type *DestTy) const { 276 return CreateCast(Instruction::IntToPtr, C, DestTy); 277 } 278 CreatePtrToInt(Constant * C,Type * DestTy)279 Instruction *CreatePtrToInt(Constant *C, Type *DestTy) const { 280 return CreateCast(Instruction::PtrToInt, C, DestTy); 281 } 282 CreateZExtOrBitCast(Constant * C,Type * DestTy)283 Instruction *CreateZExtOrBitCast(Constant *C, Type *DestTy) const { 284 return CastInst::CreateZExtOrBitCast(C, DestTy); 285 } 286 CreateSExtOrBitCast(Constant * C,Type * DestTy)287 Instruction *CreateSExtOrBitCast(Constant *C, Type *DestTy) const { 288 return CastInst::CreateSExtOrBitCast(C, DestTy); 289 } 290 CreateTruncOrBitCast(Constant * C,Type * DestTy)291 Instruction *CreateTruncOrBitCast(Constant *C, Type *DestTy) const { 292 return CastInst::CreateTruncOrBitCast(C, DestTy); 293 } 294 295 //===--------------------------------------------------------------------===// 296 // Compare Instructions 297 //===--------------------------------------------------------------------===// 298 CreateICmp(CmpInst::Predicate P,Constant * LHS,Constant * RHS)299 Instruction *CreateICmp(CmpInst::Predicate P, 300 Constant *LHS, Constant *RHS) const { 301 return new ICmpInst(P, LHS, RHS); 302 } 303 CreateFCmp(CmpInst::Predicate P,Constant * LHS,Constant * RHS)304 Instruction *CreateFCmp(CmpInst::Predicate P, 305 Constant *LHS, Constant *RHS) const { 306 return new FCmpInst(P, LHS, RHS); 307 } 308 309 //===--------------------------------------------------------------------===// 310 // Other Instructions 311 //===--------------------------------------------------------------------===// 312 CreateSelect(Constant * C,Constant * True,Constant * False)313 Instruction *CreateSelect(Constant *C, 314 Constant *True, Constant *False) const { 315 return SelectInst::Create(C, True, False); 316 } 317 CreateExtractElement(Constant * Vec,Constant * Idx)318 Instruction *CreateExtractElement(Constant *Vec, Constant *Idx) const { 319 return ExtractElementInst::Create(Vec, Idx); 320 } 321 CreateInsertElement(Constant * Vec,Constant * NewElt,Constant * Idx)322 Instruction *CreateInsertElement(Constant *Vec, Constant *NewElt, 323 Constant *Idx) const { 324 return InsertElementInst::Create(Vec, NewElt, Idx); 325 } 326 CreateShuffleVector(Constant * V1,Constant * V2,Constant * Mask)327 Instruction *CreateShuffleVector(Constant *V1, Constant *V2, 328 Constant *Mask) const { 329 return new ShuffleVectorInst(V1, V2, Mask); 330 } 331 CreateExtractValue(Constant * Agg,ArrayRef<unsigned> IdxList)332 Instruction *CreateExtractValue(Constant *Agg, 333 ArrayRef<unsigned> IdxList) const { 334 return ExtractValueInst::Create(Agg, IdxList); 335 } 336 CreateInsertValue(Constant * Agg,Constant * Val,ArrayRef<unsigned> IdxList)337 Instruction *CreateInsertValue(Constant *Agg, Constant *Val, 338 ArrayRef<unsigned> IdxList) const { 339 return InsertValueInst::Create(Agg, Val, IdxList); 340 } 341 }; 342 343 } // end namespace llvm 344 345 #endif // LLVM_IR_NOFOLDER_H 346