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