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