1 //====- TargetFolder.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 TargetFolder class, a helper for IRBuilder. 10 // It provides IRBuilder with a set of methods for creating constants with 11 // target dependent folding, in addition to the same target-independent 12 // folding that the ConstantFolder class provides. For general constant 13 // creation and folding, use ConstantExpr and the routines in 14 // llvm/Analysis/ConstantFolding.h. 15 // 16 //===----------------------------------------------------------------------===// 17 18 #ifndef LLVM_ANALYSIS_TARGETFOLDER_H 19 #define LLVM_ANALYSIS_TARGETFOLDER_H 20 21 #include "llvm/ADT/ArrayRef.h" 22 #include "llvm/Analysis/ConstantFolding.h" 23 #include "llvm/IR/Constants.h" 24 #include "llvm/IR/InstrTypes.h" 25 26 namespace llvm { 27 28 class DataLayout; 29 30 /// TargetFolder - Create constants with target dependent folding. 31 class TargetFolder { 32 const DataLayout &DL; 33 34 /// Fold - Fold the constant using target specific information. Fold(Constant * C)35 Constant *Fold(Constant *C) const { 36 if (Constant *CF = ConstantFoldConstant(C, DL)) 37 return CF; 38 return C; 39 } 40 41 public: TargetFolder(const DataLayout & DL)42 explicit TargetFolder(const DataLayout &DL) : DL(DL) {} 43 44 //===--------------------------------------------------------------------===// 45 // Binary Operators 46 //===--------------------------------------------------------------------===// 47 48 Constant *CreateAdd(Constant *LHS, Constant *RHS, 49 bool HasNUW = false, bool HasNSW = false) const { 50 return Fold(ConstantExpr::getAdd(LHS, RHS, HasNUW, HasNSW)); 51 } CreateFAdd(Constant * LHS,Constant * RHS)52 Constant *CreateFAdd(Constant *LHS, Constant *RHS) const { 53 return Fold(ConstantExpr::getFAdd(LHS, RHS)); 54 } 55 Constant *CreateSub(Constant *LHS, Constant *RHS, 56 bool HasNUW = false, bool HasNSW = false) const { 57 return Fold(ConstantExpr::getSub(LHS, RHS, HasNUW, HasNSW)); 58 } CreateFSub(Constant * LHS,Constant * RHS)59 Constant *CreateFSub(Constant *LHS, Constant *RHS) const { 60 return Fold(ConstantExpr::getFSub(LHS, RHS)); 61 } 62 Constant *CreateMul(Constant *LHS, Constant *RHS, 63 bool HasNUW = false, bool HasNSW = false) const { 64 return Fold(ConstantExpr::getMul(LHS, RHS, HasNUW, HasNSW)); 65 } CreateFMul(Constant * LHS,Constant * RHS)66 Constant *CreateFMul(Constant *LHS, Constant *RHS) const { 67 return Fold(ConstantExpr::getFMul(LHS, RHS)); 68 } 69 Constant *CreateUDiv(Constant *LHS, Constant *RHS, bool isExact = false)const{ 70 return Fold(ConstantExpr::getUDiv(LHS, RHS, isExact)); 71 } 72 Constant *CreateSDiv(Constant *LHS, Constant *RHS, bool isExact = false)const{ 73 return Fold(ConstantExpr::getSDiv(LHS, RHS, isExact)); 74 } CreateFDiv(Constant * LHS,Constant * RHS)75 Constant *CreateFDiv(Constant *LHS, Constant *RHS) const { 76 return Fold(ConstantExpr::getFDiv(LHS, RHS)); 77 } CreateURem(Constant * LHS,Constant * RHS)78 Constant *CreateURem(Constant *LHS, Constant *RHS) const { 79 return Fold(ConstantExpr::getURem(LHS, RHS)); 80 } CreateSRem(Constant * LHS,Constant * RHS)81 Constant *CreateSRem(Constant *LHS, Constant *RHS) const { 82 return Fold(ConstantExpr::getSRem(LHS, RHS)); 83 } CreateFRem(Constant * LHS,Constant * RHS)84 Constant *CreateFRem(Constant *LHS, Constant *RHS) const { 85 return Fold(ConstantExpr::getFRem(LHS, RHS)); 86 } 87 Constant *CreateShl(Constant *LHS, Constant *RHS, 88 bool HasNUW = false, bool HasNSW = false) const { 89 return Fold(ConstantExpr::getShl(LHS, RHS, HasNUW, HasNSW)); 90 } 91 Constant *CreateLShr(Constant *LHS, Constant *RHS, bool isExact = false)const{ 92 return Fold(ConstantExpr::getLShr(LHS, RHS, isExact)); 93 } 94 Constant *CreateAShr(Constant *LHS, Constant *RHS, bool isExact = false)const{ 95 return Fold(ConstantExpr::getAShr(LHS, RHS, isExact)); 96 } CreateAnd(Constant * LHS,Constant * RHS)97 Constant *CreateAnd(Constant *LHS, Constant *RHS) const { 98 return Fold(ConstantExpr::getAnd(LHS, RHS)); 99 } CreateOr(Constant * LHS,Constant * RHS)100 Constant *CreateOr(Constant *LHS, Constant *RHS) const { 101 return Fold(ConstantExpr::getOr(LHS, RHS)); 102 } CreateXor(Constant * LHS,Constant * RHS)103 Constant *CreateXor(Constant *LHS, Constant *RHS) const { 104 return Fold(ConstantExpr::getXor(LHS, RHS)); 105 } 106 CreateBinOp(Instruction::BinaryOps Opc,Constant * LHS,Constant * RHS)107 Constant *CreateBinOp(Instruction::BinaryOps Opc, 108 Constant *LHS, Constant *RHS) const { 109 return Fold(ConstantExpr::get(Opc, LHS, RHS)); 110 } 111 112 //===--------------------------------------------------------------------===// 113 // Unary Operators 114 //===--------------------------------------------------------------------===// 115 116 Constant *CreateNeg(Constant *C, 117 bool HasNUW = false, bool HasNSW = false) const { 118 return Fold(ConstantExpr::getNeg(C, HasNUW, HasNSW)); 119 } CreateFNeg(Constant * C)120 Constant *CreateFNeg(Constant *C) const { 121 return Fold(ConstantExpr::getFNeg(C)); 122 } CreateNot(Constant * C)123 Constant *CreateNot(Constant *C) const { 124 return Fold(ConstantExpr::getNot(C)); 125 } 126 CreateUnOp(Instruction::UnaryOps Opc,Constant * C)127 Constant *CreateUnOp(Instruction::UnaryOps Opc, Constant *C) const { 128 return Fold(ConstantExpr::get(Opc, C)); 129 } 130 131 //===--------------------------------------------------------------------===// 132 // Memory Instructions 133 //===--------------------------------------------------------------------===// 134 CreateGetElementPtr(Type * Ty,Constant * C,ArrayRef<Constant * > IdxList)135 Constant *CreateGetElementPtr(Type *Ty, Constant *C, 136 ArrayRef<Constant *> IdxList) const { 137 return Fold(ConstantExpr::getGetElementPtr(Ty, C, IdxList)); 138 } CreateGetElementPtr(Type * Ty,Constant * C,Constant * Idx)139 Constant *CreateGetElementPtr(Type *Ty, Constant *C, Constant *Idx) const { 140 // This form of the function only exists to avoid ambiguous overload 141 // warnings about whether to convert Idx to ArrayRef<Constant *> or 142 // ArrayRef<Value *>. 143 return Fold(ConstantExpr::getGetElementPtr(Ty, C, Idx)); 144 } CreateGetElementPtr(Type * Ty,Constant * C,ArrayRef<Value * > IdxList)145 Constant *CreateGetElementPtr(Type *Ty, Constant *C, 146 ArrayRef<Value *> IdxList) const { 147 return Fold(ConstantExpr::getGetElementPtr(Ty, C, IdxList)); 148 } 149 CreateInBoundsGetElementPtr(Type * Ty,Constant * C,ArrayRef<Constant * > IdxList)150 Constant *CreateInBoundsGetElementPtr(Type *Ty, Constant *C, 151 ArrayRef<Constant *> IdxList) const { 152 return Fold(ConstantExpr::getInBoundsGetElementPtr(Ty, C, IdxList)); 153 } CreateInBoundsGetElementPtr(Type * Ty,Constant * C,Constant * Idx)154 Constant *CreateInBoundsGetElementPtr(Type *Ty, Constant *C, 155 Constant *Idx) const { 156 // This form of the function only exists to avoid ambiguous overload 157 // warnings about whether to convert Idx to ArrayRef<Constant *> or 158 // ArrayRef<Value *>. 159 return Fold(ConstantExpr::getInBoundsGetElementPtr(Ty, C, Idx)); 160 } CreateInBoundsGetElementPtr(Type * Ty,Constant * C,ArrayRef<Value * > IdxList)161 Constant *CreateInBoundsGetElementPtr(Type *Ty, Constant *C, 162 ArrayRef<Value *> IdxList) const { 163 return Fold(ConstantExpr::getInBoundsGetElementPtr(Ty, C, IdxList)); 164 } 165 166 //===--------------------------------------------------------------------===// 167 // Cast/Conversion Operators 168 //===--------------------------------------------------------------------===// 169 CreateCast(Instruction::CastOps Op,Constant * C,Type * DestTy)170 Constant *CreateCast(Instruction::CastOps Op, Constant *C, 171 Type *DestTy) const { 172 if (C->getType() == DestTy) 173 return C; // avoid calling Fold 174 return Fold(ConstantExpr::getCast(Op, C, DestTy)); 175 } CreateIntCast(Constant * C,Type * DestTy,bool isSigned)176 Constant *CreateIntCast(Constant *C, Type *DestTy, 177 bool isSigned) const { 178 if (C->getType() == DestTy) 179 return C; // avoid calling Fold 180 return Fold(ConstantExpr::getIntegerCast(C, DestTy, isSigned)); 181 } CreatePointerCast(Constant * C,Type * DestTy)182 Constant *CreatePointerCast(Constant *C, Type *DestTy) const { 183 if (C->getType() == DestTy) 184 return C; // avoid calling Fold 185 return Fold(ConstantExpr::getPointerCast(C, DestTy)); 186 } CreateFPCast(Constant * C,Type * DestTy)187 Constant *CreateFPCast(Constant *C, Type *DestTy) const { 188 if (C->getType() == DestTy) 189 return C; // avoid calling Fold 190 return Fold(ConstantExpr::getFPCast(C, DestTy)); 191 } CreateBitCast(Constant * C,Type * DestTy)192 Constant *CreateBitCast(Constant *C, Type *DestTy) const { 193 return CreateCast(Instruction::BitCast, C, DestTy); 194 } CreateIntToPtr(Constant * C,Type * DestTy)195 Constant *CreateIntToPtr(Constant *C, Type *DestTy) const { 196 return CreateCast(Instruction::IntToPtr, C, DestTy); 197 } CreatePtrToInt(Constant * C,Type * DestTy)198 Constant *CreatePtrToInt(Constant *C, Type *DestTy) const { 199 return CreateCast(Instruction::PtrToInt, C, DestTy); 200 } CreateZExtOrBitCast(Constant * C,Type * DestTy)201 Constant *CreateZExtOrBitCast(Constant *C, Type *DestTy) const { 202 if (C->getType() == DestTy) 203 return C; // avoid calling Fold 204 return Fold(ConstantExpr::getZExtOrBitCast(C, DestTy)); 205 } CreateSExtOrBitCast(Constant * C,Type * DestTy)206 Constant *CreateSExtOrBitCast(Constant *C, Type *DestTy) const { 207 if (C->getType() == DestTy) 208 return C; // avoid calling Fold 209 return Fold(ConstantExpr::getSExtOrBitCast(C, DestTy)); 210 } CreateTruncOrBitCast(Constant * C,Type * DestTy)211 Constant *CreateTruncOrBitCast(Constant *C, Type *DestTy) const { 212 if (C->getType() == DestTy) 213 return C; // avoid calling Fold 214 return Fold(ConstantExpr::getTruncOrBitCast(C, DestTy)); 215 } 216 CreatePointerBitCastOrAddrSpaceCast(Constant * C,Type * DestTy)217 Constant *CreatePointerBitCastOrAddrSpaceCast(Constant *C, 218 Type *DestTy) const { 219 if (C->getType() == DestTy) 220 return C; // avoid calling Fold 221 return Fold(ConstantExpr::getPointerBitCastOrAddrSpaceCast(C, DestTy)); 222 } 223 224 //===--------------------------------------------------------------------===// 225 // Compare Instructions 226 //===--------------------------------------------------------------------===// 227 CreateICmp(CmpInst::Predicate P,Constant * LHS,Constant * RHS)228 Constant *CreateICmp(CmpInst::Predicate P, Constant *LHS, 229 Constant *RHS) const { 230 return Fold(ConstantExpr::getCompare(P, LHS, RHS)); 231 } CreateFCmp(CmpInst::Predicate P,Constant * LHS,Constant * RHS)232 Constant *CreateFCmp(CmpInst::Predicate P, Constant *LHS, 233 Constant *RHS) const { 234 return Fold(ConstantExpr::getCompare(P, LHS, RHS)); 235 } 236 237 //===--------------------------------------------------------------------===// 238 // Other Instructions 239 //===--------------------------------------------------------------------===// 240 CreateSelect(Constant * C,Constant * True,Constant * False)241 Constant *CreateSelect(Constant *C, Constant *True, Constant *False) const { 242 return Fold(ConstantExpr::getSelect(C, True, False)); 243 } 244 CreateExtractElement(Constant * Vec,Constant * Idx)245 Constant *CreateExtractElement(Constant *Vec, Constant *Idx) const { 246 return Fold(ConstantExpr::getExtractElement(Vec, Idx)); 247 } 248 CreateInsertElement(Constant * Vec,Constant * NewElt,Constant * Idx)249 Constant *CreateInsertElement(Constant *Vec, Constant *NewElt, 250 Constant *Idx) const { 251 return Fold(ConstantExpr::getInsertElement(Vec, NewElt, Idx)); 252 } 253 CreateShuffleVector(Constant * V1,Constant * V2,Constant * Mask)254 Constant *CreateShuffleVector(Constant *V1, Constant *V2, 255 Constant *Mask) const { 256 return Fold(ConstantExpr::getShuffleVector(V1, V2, Mask)); 257 } 258 CreateExtractValue(Constant * Agg,ArrayRef<unsigned> IdxList)259 Constant *CreateExtractValue(Constant *Agg, 260 ArrayRef<unsigned> IdxList) const { 261 return Fold(ConstantExpr::getExtractValue(Agg, IdxList)); 262 } 263 CreateInsertValue(Constant * Agg,Constant * Val,ArrayRef<unsigned> IdxList)264 Constant *CreateInsertValue(Constant *Agg, Constant *Val, 265 ArrayRef<unsigned> IdxList) const { 266 return Fold(ConstantExpr::getInsertValue(Agg, Val, IdxList)); 267 } 268 }; 269 270 } 271 272 #endif 273