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. 35 Constant *Fold(Constant *C) const { 36 if (Constant *CF = ConstantFoldConstant(C, DL)) 37 return CF; 38 return C; 39 } 40 41 public: 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 } 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 } 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 } 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 } 75 Constant *CreateFDiv(Constant *LHS, Constant *RHS) const { 76 return Fold(ConstantExpr::getFDiv(LHS, RHS)); 77 } 78 Constant *CreateURem(Constant *LHS, Constant *RHS) const { 79 return Fold(ConstantExpr::getURem(LHS, RHS)); 80 } 81 Constant *CreateSRem(Constant *LHS, Constant *RHS) const { 82 return Fold(ConstantExpr::getSRem(LHS, RHS)); 83 } 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 } 97 Constant *CreateAnd(Constant *LHS, Constant *RHS) const { 98 return Fold(ConstantExpr::getAnd(LHS, RHS)); 99 } 100 Constant *CreateOr(Constant *LHS, Constant *RHS) const { 101 return Fold(ConstantExpr::getOr(LHS, RHS)); 102 } 103 Constant *CreateXor(Constant *LHS, Constant *RHS) const { 104 return Fold(ConstantExpr::getXor(LHS, RHS)); 105 } 106 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 } 120 Constant *CreateFNeg(Constant *C) const { 121 return Fold(ConstantExpr::getFNeg(C)); 122 } 123 Constant *CreateNot(Constant *C) const { 124 return Fold(ConstantExpr::getNot(C)); 125 } 126 127 Constant *CreateUnOp(Instruction::UnaryOps Opc, Constant *C) const { 128 return Fold(ConstantExpr::get(Opc, C)); 129 } 130 131 //===--------------------------------------------------------------------===// 132 // Memory Instructions 133 //===--------------------------------------------------------------------===// 134 135 Constant *CreateGetElementPtr(Type *Ty, Constant *C, 136 ArrayRef<Constant *> IdxList) const { 137 return Fold(ConstantExpr::getGetElementPtr(Ty, C, IdxList)); 138 } 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 } 145 Constant *CreateGetElementPtr(Type *Ty, Constant *C, 146 ArrayRef<Value *> IdxList) const { 147 return Fold(ConstantExpr::getGetElementPtr(Ty, C, IdxList)); 148 } 149 150 Constant *CreateInBoundsGetElementPtr(Type *Ty, Constant *C, 151 ArrayRef<Constant *> IdxList) const { 152 return Fold(ConstantExpr::getInBoundsGetElementPtr(Ty, C, IdxList)); 153 } 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 } 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 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 } 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 } 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 } 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 } 192 Constant *CreateBitCast(Constant *C, Type *DestTy) const { 193 return CreateCast(Instruction::BitCast, C, DestTy); 194 } 195 Constant *CreateIntToPtr(Constant *C, Type *DestTy) const { 196 return CreateCast(Instruction::IntToPtr, C, DestTy); 197 } 198 Constant *CreatePtrToInt(Constant *C, Type *DestTy) const { 199 return CreateCast(Instruction::PtrToInt, C, DestTy); 200 } 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 } 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 } 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 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 228 Constant *CreateICmp(CmpInst::Predicate P, Constant *LHS, 229 Constant *RHS) const { 230 return Fold(ConstantExpr::getCompare(P, LHS, RHS)); 231 } 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 241 Constant *CreateSelect(Constant *C, Constant *True, Constant *False) const { 242 return Fold(ConstantExpr::getSelect(C, True, False)); 243 } 244 245 Constant *CreateExtractElement(Constant *Vec, Constant *Idx) const { 246 return Fold(ConstantExpr::getExtractElement(Vec, Idx)); 247 } 248 249 Constant *CreateInsertElement(Constant *Vec, Constant *NewElt, 250 Constant *Idx) const { 251 return Fold(ConstantExpr::getInsertElement(Vec, NewElt, Idx)); 252 } 253 254 Constant *CreateShuffleVector(Constant *V1, Constant *V2, 255 Constant *Mask) const { 256 return Fold(ConstantExpr::getShuffleVector(V1, V2, Mask)); 257 } 258 259 Constant *CreateExtractValue(Constant *Agg, 260 ArrayRef<unsigned> IdxList) const { 261 return Fold(ConstantExpr::getExtractValue(Agg, IdxList)); 262 } 263 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