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 // Value-based folders. 42 // 43 // Return an existing value or a constant if the operation can be simplified. 44 // Otherwise return nullptr. 45 //===--------------------------------------------------------------------===// 46 Value *FoldAdd(Value *LHS, Value *RHS, bool HasNUW = false, 47 bool HasNSW = false) const override { 48 return nullptr; 49 } 50 51 Value *FoldAnd(Value *LHS, Value *RHS) const override { return nullptr; } 52 53 Value *FoldOr(Value *LHS, Value *RHS) const override { return nullptr; } 54 55 Value *FoldICmp(CmpInst::Predicate P, Value *LHS, Value *RHS) const override { 56 return nullptr; 57 } 58 59 Value *FoldGEP(Type *Ty, Value *Ptr, ArrayRef<Value *> IdxList, 60 bool IsInBounds = false) const override { 61 return nullptr; 62 } 63 64 Value *FoldSelect(Value *C, Value *True, Value *False) const override { 65 return nullptr; 66 } 67 68 //===--------------------------------------------------------------------===// 69 // Binary Operators 70 //===--------------------------------------------------------------------===// 71 72 Instruction *CreateFAdd(Constant *LHS, Constant *RHS) const override { 73 return BinaryOperator::CreateFAdd(LHS, RHS); 74 } 75 76 Instruction *CreateSub(Constant *LHS, Constant *RHS, 77 bool HasNUW = false, 78 bool HasNSW = false) const override { 79 BinaryOperator *BO = BinaryOperator::CreateSub(LHS, RHS); 80 if (HasNUW) BO->setHasNoUnsignedWrap(); 81 if (HasNSW) BO->setHasNoSignedWrap(); 82 return BO; 83 } 84 85 Instruction *CreateFSub(Constant *LHS, Constant *RHS) const override { 86 return BinaryOperator::CreateFSub(LHS, RHS); 87 } 88 89 Instruction *CreateMul(Constant *LHS, Constant *RHS, 90 bool HasNUW = false, 91 bool HasNSW = false) const override { 92 BinaryOperator *BO = BinaryOperator::CreateMul(LHS, RHS); 93 if (HasNUW) BO->setHasNoUnsignedWrap(); 94 if (HasNSW) BO->setHasNoSignedWrap(); 95 return BO; 96 } 97 98 Instruction *CreateFMul(Constant *LHS, Constant *RHS) const override { 99 return BinaryOperator::CreateFMul(LHS, RHS); 100 } 101 102 Instruction *CreateUDiv(Constant *LHS, Constant *RHS, 103 bool isExact = false) const override { 104 if (!isExact) 105 return BinaryOperator::CreateUDiv(LHS, RHS); 106 return BinaryOperator::CreateExactUDiv(LHS, RHS); 107 } 108 109 Instruction *CreateSDiv(Constant *LHS, Constant *RHS, 110 bool isExact = false) const override { 111 if (!isExact) 112 return BinaryOperator::CreateSDiv(LHS, RHS); 113 return BinaryOperator::CreateExactSDiv(LHS, RHS); 114 } 115 116 Instruction *CreateFDiv(Constant *LHS, Constant *RHS) const override { 117 return BinaryOperator::CreateFDiv(LHS, RHS); 118 } 119 120 Instruction *CreateURem(Constant *LHS, Constant *RHS) const override { 121 return BinaryOperator::CreateURem(LHS, RHS); 122 } 123 124 Instruction *CreateSRem(Constant *LHS, Constant *RHS) const override { 125 return BinaryOperator::CreateSRem(LHS, RHS); 126 } 127 128 Instruction *CreateFRem(Constant *LHS, Constant *RHS) const override { 129 return BinaryOperator::CreateFRem(LHS, RHS); 130 } 131 132 Instruction *CreateShl(Constant *LHS, Constant *RHS, bool HasNUW = false, 133 bool HasNSW = false) const override { 134 BinaryOperator *BO = BinaryOperator::CreateShl(LHS, RHS); 135 if (HasNUW) BO->setHasNoUnsignedWrap(); 136 if (HasNSW) BO->setHasNoSignedWrap(); 137 return BO; 138 } 139 140 Instruction *CreateLShr(Constant *LHS, Constant *RHS, 141 bool isExact = false) const override { 142 if (!isExact) 143 return BinaryOperator::CreateLShr(LHS, RHS); 144 return BinaryOperator::CreateExactLShr(LHS, RHS); 145 } 146 147 Instruction *CreateAShr(Constant *LHS, Constant *RHS, 148 bool isExact = false) const override { 149 if (!isExact) 150 return BinaryOperator::CreateAShr(LHS, RHS); 151 return BinaryOperator::CreateExactAShr(LHS, RHS); 152 } 153 154 Instruction *CreateXor(Constant *LHS, Constant *RHS) const override { 155 return BinaryOperator::CreateXor(LHS, RHS); 156 } 157 158 Instruction *CreateBinOp(Instruction::BinaryOps Opc, 159 Constant *LHS, Constant *RHS) const override { 160 return BinaryOperator::Create(Opc, LHS, RHS); 161 } 162 163 //===--------------------------------------------------------------------===// 164 // Unary Operators 165 //===--------------------------------------------------------------------===// 166 167 Instruction *CreateNeg(Constant *C, 168 bool HasNUW = false, 169 bool HasNSW = false) const override { 170 BinaryOperator *BO = BinaryOperator::CreateNeg(C); 171 if (HasNUW) BO->setHasNoUnsignedWrap(); 172 if (HasNSW) BO->setHasNoSignedWrap(); 173 return BO; 174 } 175 176 Instruction *CreateFNeg(Constant *C) const override { 177 return UnaryOperator::CreateFNeg(C); 178 } 179 180 Instruction *CreateNot(Constant *C) const override { 181 return BinaryOperator::CreateNot(C); 182 } 183 184 Instruction *CreateUnOp(Instruction::UnaryOps Opc, 185 Constant *C) const override { 186 return UnaryOperator::Create(Opc, C); 187 } 188 189 //===--------------------------------------------------------------------===// 190 // Cast/Conversion Operators 191 //===--------------------------------------------------------------------===// 192 193 Instruction *CreateCast(Instruction::CastOps Op, Constant *C, 194 Type *DestTy) const override { 195 return CastInst::Create(Op, C, DestTy); 196 } 197 198 Instruction *CreatePointerCast(Constant *C, Type *DestTy) const override { 199 return CastInst::CreatePointerCast(C, DestTy); 200 } 201 202 Instruction *CreatePointerBitCastOrAddrSpaceCast( 203 Constant *C, Type *DestTy) const override { 204 return CastInst::CreatePointerBitCastOrAddrSpaceCast(C, DestTy); 205 } 206 207 Instruction *CreateIntCast(Constant *C, Type *DestTy, 208 bool isSigned) const override { 209 return CastInst::CreateIntegerCast(C, DestTy, isSigned); 210 } 211 212 Instruction *CreateFPCast(Constant *C, Type *DestTy) const override { 213 return CastInst::CreateFPCast(C, DestTy); 214 } 215 216 Instruction *CreateBitCast(Constant *C, Type *DestTy) const override { 217 return CreateCast(Instruction::BitCast, C, DestTy); 218 } 219 220 Instruction *CreateIntToPtr(Constant *C, Type *DestTy) const override { 221 return CreateCast(Instruction::IntToPtr, C, DestTy); 222 } 223 224 Instruction *CreatePtrToInt(Constant *C, Type *DestTy) const override { 225 return CreateCast(Instruction::PtrToInt, C, DestTy); 226 } 227 228 Instruction *CreateZExtOrBitCast(Constant *C, Type *DestTy) const override { 229 return CastInst::CreateZExtOrBitCast(C, DestTy); 230 } 231 232 Instruction *CreateSExtOrBitCast(Constant *C, Type *DestTy) const override { 233 return CastInst::CreateSExtOrBitCast(C, DestTy); 234 } 235 236 Instruction *CreateTruncOrBitCast(Constant *C, Type *DestTy) const override { 237 return CastInst::CreateTruncOrBitCast(C, DestTy); 238 } 239 240 //===--------------------------------------------------------------------===// 241 // Compare Instructions 242 //===--------------------------------------------------------------------===// 243 244 Instruction *CreateFCmp(CmpInst::Predicate P, 245 Constant *LHS, Constant *RHS) const override { 246 return new FCmpInst(P, LHS, RHS); 247 } 248 249 //===--------------------------------------------------------------------===// 250 // Other Instructions 251 //===--------------------------------------------------------------------===// 252 253 Instruction *CreateExtractElement(Constant *Vec, 254 Constant *Idx) const override { 255 return ExtractElementInst::Create(Vec, Idx); 256 } 257 258 Instruction *CreateInsertElement(Constant *Vec, Constant *NewElt, 259 Constant *Idx) const override { 260 return InsertElementInst::Create(Vec, NewElt, Idx); 261 } 262 263 Instruction *CreateShuffleVector(Constant *V1, Constant *V2, 264 ArrayRef<int> Mask) const override { 265 return new ShuffleVectorInst(V1, V2, Mask); 266 } 267 268 Instruction *CreateExtractValue(Constant *Agg, 269 ArrayRef<unsigned> IdxList) const override { 270 return ExtractValueInst::Create(Agg, IdxList); 271 } 272 273 Instruction *CreateInsertValue(Constant *Agg, Constant *Val, 274 ArrayRef<unsigned> IdxList) const override { 275 return InsertValueInst::Create(Agg, Val, IdxList); 276 } 277 }; 278 279 } // end namespace llvm 280 281 #endif // LLVM_IR_NOFOLDER_H 282