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 #include "llvm/IR/IRBuilderFolder.h" 26 27 namespace llvm { 28 29 class DataLayout; 30 31 /// TargetFolder - Create constants with target dependent folding. 32 class TargetFolder final : public IRBuilderFolder { 33 const DataLayout &DL; 34 35 /// Fold - Fold the constant using target specific information. 36 Constant *Fold(Constant *C) const { 37 return ConstantFoldConstant(C, DL); 38 } 39 40 virtual void anchor(); 41 42 public: 43 explicit TargetFolder(const DataLayout &DL) : DL(DL) {} 44 45 //===--------------------------------------------------------------------===// 46 // Value-based folders. 47 // 48 // Return an existing value or a constant if the operation can be simplified. 49 // Otherwise return nullptr. 50 //===--------------------------------------------------------------------===// 51 Value *FoldAdd(Value *LHS, Value *RHS, bool HasNUW = false, 52 bool HasNSW = false) const override { 53 auto *LC = dyn_cast<Constant>(LHS); 54 auto *RC = dyn_cast<Constant>(RHS); 55 if (LC && RC) 56 return Fold(ConstantExpr::getAdd(LC, RC, HasNUW, HasNSW)); 57 return nullptr; 58 } 59 60 Value *FoldAnd(Value *LHS, Value *RHS) const override { 61 auto *LC = dyn_cast<Constant>(LHS); 62 auto *RC = dyn_cast<Constant>(RHS); 63 if (LC && RC) 64 return Fold(ConstantExpr::getAnd(LC, RC)); 65 return nullptr; 66 } 67 68 Value *FoldOr(Value *LHS, Value *RHS) const override { 69 auto *LC = dyn_cast<Constant>(LHS); 70 auto *RC = dyn_cast<Constant>(RHS); 71 if (LC && RC) 72 return Fold(ConstantExpr::getOr(LC, RC)); 73 return nullptr; 74 } 75 76 Value *FoldICmp(CmpInst::Predicate P, Value *LHS, Value *RHS) const override { 77 auto *LC = dyn_cast<Constant>(LHS); 78 auto *RC = dyn_cast<Constant>(RHS); 79 if (LC && RC) 80 return ConstantExpr::getCompare(P, LC, RC); 81 return nullptr; 82 } 83 84 Value *FoldGEP(Type *Ty, Value *Ptr, ArrayRef<Value *> IdxList, 85 bool IsInBounds = false) const override { 86 if (auto *PC = dyn_cast<Constant>(Ptr)) { 87 // Every index must be constant. 88 if (any_of(IdxList, [](Value *V) { return !isa<Constant>(V); })) 89 return nullptr; 90 if (IsInBounds) 91 return Fold(ConstantExpr::getInBoundsGetElementPtr(Ty, PC, IdxList)); 92 else 93 return Fold(ConstantExpr::getGetElementPtr(Ty, PC, IdxList)); 94 } 95 return nullptr; 96 } 97 98 Value *FoldSelect(Value *C, Value *True, Value *False) const override { 99 auto *CC = dyn_cast<Constant>(C); 100 auto *TC = dyn_cast<Constant>(True); 101 auto *FC = dyn_cast<Constant>(False); 102 if (CC && TC && FC) 103 return Fold(ConstantExpr::getSelect(CC, TC, FC)); 104 105 return nullptr; 106 } 107 108 //===--------------------------------------------------------------------===// 109 // Binary Operators 110 //===--------------------------------------------------------------------===// 111 112 Constant *CreateFAdd(Constant *LHS, Constant *RHS) const override { 113 return Fold(ConstantExpr::getFAdd(LHS, RHS)); 114 } 115 Constant *CreateSub(Constant *LHS, Constant *RHS, 116 bool HasNUW = false, bool HasNSW = false) const override { 117 return Fold(ConstantExpr::getSub(LHS, RHS, HasNUW, HasNSW)); 118 } 119 Constant *CreateFSub(Constant *LHS, Constant *RHS) const override { 120 return Fold(ConstantExpr::getFSub(LHS, RHS)); 121 } 122 Constant *CreateMul(Constant *LHS, Constant *RHS, 123 bool HasNUW = false, bool HasNSW = false) const override { 124 return Fold(ConstantExpr::getMul(LHS, RHS, HasNUW, HasNSW)); 125 } 126 Constant *CreateFMul(Constant *LHS, Constant *RHS) const override { 127 return Fold(ConstantExpr::getFMul(LHS, RHS)); 128 } 129 Constant *CreateUDiv(Constant *LHS, Constant *RHS, 130 bool isExact = false) const override { 131 return Fold(ConstantExpr::getUDiv(LHS, RHS, isExact)); 132 } 133 Constant *CreateSDiv(Constant *LHS, Constant *RHS, 134 bool isExact = false) const override { 135 return Fold(ConstantExpr::getSDiv(LHS, RHS, isExact)); 136 } 137 Constant *CreateFDiv(Constant *LHS, Constant *RHS) const override { 138 return Fold(ConstantExpr::getFDiv(LHS, RHS)); 139 } 140 Constant *CreateURem(Constant *LHS, Constant *RHS) const override { 141 return Fold(ConstantExpr::getURem(LHS, RHS)); 142 } 143 Constant *CreateSRem(Constant *LHS, Constant *RHS) const override { 144 return Fold(ConstantExpr::getSRem(LHS, RHS)); 145 } 146 Constant *CreateFRem(Constant *LHS, Constant *RHS) const override { 147 return Fold(ConstantExpr::getFRem(LHS, RHS)); 148 } 149 Constant *CreateShl(Constant *LHS, Constant *RHS, 150 bool HasNUW = false, bool HasNSW = false) const override { 151 return Fold(ConstantExpr::getShl(LHS, RHS, HasNUW, HasNSW)); 152 } 153 Constant *CreateLShr(Constant *LHS, Constant *RHS, 154 bool isExact = false) const override { 155 return Fold(ConstantExpr::getLShr(LHS, RHS, isExact)); 156 } 157 Constant *CreateAShr(Constant *LHS, Constant *RHS, 158 bool isExact = false) const override { 159 return Fold(ConstantExpr::getAShr(LHS, RHS, isExact)); 160 } 161 Constant *CreateXor(Constant *LHS, Constant *RHS) const override { 162 return Fold(ConstantExpr::getXor(LHS, RHS)); 163 } 164 165 Constant *CreateBinOp(Instruction::BinaryOps Opc, 166 Constant *LHS, Constant *RHS) const override { 167 return Fold(ConstantExpr::get(Opc, LHS, RHS)); 168 } 169 170 //===--------------------------------------------------------------------===// 171 // Unary Operators 172 //===--------------------------------------------------------------------===// 173 174 Constant *CreateNeg(Constant *C, 175 bool HasNUW = false, bool HasNSW = false) const override { 176 return Fold(ConstantExpr::getNeg(C, HasNUW, HasNSW)); 177 } 178 Constant *CreateFNeg(Constant *C) const override { 179 return Fold(ConstantExpr::getFNeg(C)); 180 } 181 Constant *CreateNot(Constant *C) const override { 182 return Fold(ConstantExpr::getNot(C)); 183 } 184 185 Constant *CreateUnOp(Instruction::UnaryOps Opc, Constant *C) const override { 186 return Fold(ConstantExpr::get(Opc, C)); 187 } 188 189 //===--------------------------------------------------------------------===// 190 // Cast/Conversion Operators 191 //===--------------------------------------------------------------------===// 192 193 Constant *CreateCast(Instruction::CastOps Op, Constant *C, 194 Type *DestTy) const override { 195 if (C->getType() == DestTy) 196 return C; // avoid calling Fold 197 return Fold(ConstantExpr::getCast(Op, C, DestTy)); 198 } 199 Constant *CreateIntCast(Constant *C, Type *DestTy, 200 bool isSigned) const override { 201 if (C->getType() == DestTy) 202 return C; // avoid calling Fold 203 return Fold(ConstantExpr::getIntegerCast(C, DestTy, isSigned)); 204 } 205 Constant *CreatePointerCast(Constant *C, Type *DestTy) const override { 206 if (C->getType() == DestTy) 207 return C; // avoid calling Fold 208 return Fold(ConstantExpr::getPointerCast(C, DestTy)); 209 } 210 Constant *CreateFPCast(Constant *C, Type *DestTy) const override { 211 if (C->getType() == DestTy) 212 return C; // avoid calling Fold 213 return Fold(ConstantExpr::getFPCast(C, DestTy)); 214 } 215 Constant *CreateBitCast(Constant *C, Type *DestTy) const override { 216 return CreateCast(Instruction::BitCast, C, DestTy); 217 } 218 Constant *CreateIntToPtr(Constant *C, Type *DestTy) const override { 219 return CreateCast(Instruction::IntToPtr, C, DestTy); 220 } 221 Constant *CreatePtrToInt(Constant *C, Type *DestTy) const override { 222 return CreateCast(Instruction::PtrToInt, C, DestTy); 223 } 224 Constant *CreateZExtOrBitCast(Constant *C, Type *DestTy) const override { 225 if (C->getType() == DestTy) 226 return C; // avoid calling Fold 227 return Fold(ConstantExpr::getZExtOrBitCast(C, DestTy)); 228 } 229 Constant *CreateSExtOrBitCast(Constant *C, Type *DestTy) const override { 230 if (C->getType() == DestTy) 231 return C; // avoid calling Fold 232 return Fold(ConstantExpr::getSExtOrBitCast(C, DestTy)); 233 } 234 Constant *CreateTruncOrBitCast(Constant *C, Type *DestTy) const override { 235 if (C->getType() == DestTy) 236 return C; // avoid calling Fold 237 return Fold(ConstantExpr::getTruncOrBitCast(C, DestTy)); 238 } 239 240 Constant *CreatePointerBitCastOrAddrSpaceCast(Constant *C, 241 Type *DestTy) const override { 242 if (C->getType() == DestTy) 243 return C; // avoid calling Fold 244 return Fold(ConstantExpr::getPointerBitCastOrAddrSpaceCast(C, DestTy)); 245 } 246 247 //===--------------------------------------------------------------------===// 248 // Compare Instructions 249 //===--------------------------------------------------------------------===// 250 251 Constant *CreateFCmp(CmpInst::Predicate P, Constant *LHS, 252 Constant *RHS) const override { 253 return Fold(ConstantExpr::getCompare(P, LHS, RHS)); 254 } 255 256 //===--------------------------------------------------------------------===// 257 // Other Instructions 258 //===--------------------------------------------------------------------===// 259 260 Constant *CreateExtractElement(Constant *Vec, Constant *Idx) const override { 261 return Fold(ConstantExpr::getExtractElement(Vec, Idx)); 262 } 263 264 Constant *CreateInsertElement(Constant *Vec, Constant *NewElt, 265 Constant *Idx) const override { 266 return Fold(ConstantExpr::getInsertElement(Vec, NewElt, Idx)); 267 } 268 269 Constant *CreateShuffleVector(Constant *V1, Constant *V2, 270 ArrayRef<int> Mask) const override { 271 return Fold(ConstantExpr::getShuffleVector(V1, V2, Mask)); 272 } 273 274 Constant *CreateExtractValue(Constant *Agg, 275 ArrayRef<unsigned> IdxList) const override { 276 return Fold(ConstantExpr::getExtractValue(Agg, IdxList)); 277 } 278 279 Constant *CreateInsertValue(Constant *Agg, Constant *Val, 280 ArrayRef<unsigned> IdxList) const override { 281 return Fold(ConstantExpr::getInsertValue(Agg, Val, IdxList)); 282 } 283 }; 284 285 } 286 287 #endif 288