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 #include "llvm/IR/Operator.h" 26 27 namespace llvm { 28 29 class Constant; 30 class DataLayout; 31 class Type; 32 33 /// TargetFolder - Create constants with target dependent folding. 34 class TargetFolder final : public IRBuilderFolder { 35 const DataLayout &DL; 36 37 /// Fold - Fold the constant using target specific information. 38 Constant *Fold(Constant *C) const { 39 return ConstantFoldConstant(C, DL); 40 } 41 42 virtual void anchor(); 43 44 public: 45 explicit TargetFolder(const DataLayout &DL) : DL(DL) {} 46 47 //===--------------------------------------------------------------------===// 48 // Value-based folders. 49 // 50 // Return an existing value or a constant if the operation can be simplified. 51 // Otherwise return nullptr. 52 //===--------------------------------------------------------------------===// 53 54 Value *FoldBinOp(Instruction::BinaryOps Opc, Value *LHS, 55 Value *RHS) const override { 56 auto *LC = dyn_cast<Constant>(LHS); 57 auto *RC = dyn_cast<Constant>(RHS); 58 if (LC && RC) { 59 if (ConstantExpr::isDesirableBinOp(Opc)) 60 return Fold(ConstantExpr::get(Opc, LC, RC)); 61 return ConstantFoldBinaryOpOperands(Opc, LC, RC, DL); 62 } 63 return nullptr; 64 } 65 66 Value *FoldExactBinOp(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, 67 bool IsExact) const override { 68 auto *LC = dyn_cast<Constant>(LHS); 69 auto *RC = dyn_cast<Constant>(RHS); 70 if (LC && RC) { 71 if (ConstantExpr::isDesirableBinOp(Opc)) 72 return Fold(ConstantExpr::get( 73 Opc, LC, RC, IsExact ? PossiblyExactOperator::IsExact : 0)); 74 return ConstantFoldBinaryOpOperands(Opc, LC, RC, DL); 75 } 76 return nullptr; 77 } 78 79 Value *FoldNoWrapBinOp(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, 80 bool HasNUW, bool HasNSW) const override { 81 auto *LC = dyn_cast<Constant>(LHS); 82 auto *RC = dyn_cast<Constant>(RHS); 83 if (LC && RC) { 84 if (ConstantExpr::isDesirableBinOp(Opc)) { 85 unsigned Flags = 0; 86 if (HasNUW) 87 Flags |= OverflowingBinaryOperator::NoUnsignedWrap; 88 if (HasNSW) 89 Flags |= OverflowingBinaryOperator::NoSignedWrap; 90 return Fold(ConstantExpr::get(Opc, LC, RC, Flags)); 91 } 92 return ConstantFoldBinaryOpOperands(Opc, LC, RC, DL); 93 } 94 return nullptr; 95 } 96 97 Value *FoldBinOpFMF(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, 98 FastMathFlags FMF) const override { 99 return FoldBinOp(Opc, LHS, RHS); 100 } 101 102 Value *FoldICmp(CmpInst::Predicate P, Value *LHS, Value *RHS) const override { 103 auto *LC = dyn_cast<Constant>(LHS); 104 auto *RC = dyn_cast<Constant>(RHS); 105 if (LC && RC) 106 return ConstantExpr::getCompare(P, LC, RC); 107 return nullptr; 108 } 109 110 Value *FoldGEP(Type *Ty, Value *Ptr, ArrayRef<Value *> IdxList, 111 bool IsInBounds = false) const override { 112 if (auto *PC = dyn_cast<Constant>(Ptr)) { 113 // Every index must be constant. 114 if (any_of(IdxList, [](Value *V) { return !isa<Constant>(V); })) 115 return nullptr; 116 if (IsInBounds) 117 return Fold(ConstantExpr::getInBoundsGetElementPtr(Ty, PC, IdxList)); 118 else 119 return Fold(ConstantExpr::getGetElementPtr(Ty, PC, IdxList)); 120 } 121 return nullptr; 122 } 123 124 Value *FoldSelect(Value *C, Value *True, Value *False) const override { 125 auto *CC = dyn_cast<Constant>(C); 126 auto *TC = dyn_cast<Constant>(True); 127 auto *FC = dyn_cast<Constant>(False); 128 if (CC && TC && FC) 129 return Fold(ConstantExpr::getSelect(CC, TC, FC)); 130 131 return nullptr; 132 } 133 134 Value *FoldExtractValue(Value *Agg, 135 ArrayRef<unsigned> IdxList) const override { 136 if (auto *CAgg = dyn_cast<Constant>(Agg)) 137 return ConstantFoldExtractValueInstruction(CAgg, IdxList); 138 return nullptr; 139 }; 140 141 Value *FoldInsertValue(Value *Agg, Value *Val, 142 ArrayRef<unsigned> IdxList) const override { 143 auto *CAgg = dyn_cast<Constant>(Agg); 144 auto *CVal = dyn_cast<Constant>(Val); 145 if (CAgg && CVal) 146 return ConstantFoldInsertValueInstruction(CAgg, CVal, IdxList); 147 return nullptr; 148 } 149 150 Value *FoldExtractElement(Value *Vec, Value *Idx) const override { 151 auto *CVec = dyn_cast<Constant>(Vec); 152 auto *CIdx = dyn_cast<Constant>(Idx); 153 if (CVec && CIdx) 154 return Fold(ConstantExpr::getExtractElement(CVec, CIdx)); 155 return nullptr; 156 } 157 158 Value *FoldInsertElement(Value *Vec, Value *NewElt, 159 Value *Idx) const override { 160 auto *CVec = dyn_cast<Constant>(Vec); 161 auto *CNewElt = dyn_cast<Constant>(NewElt); 162 auto *CIdx = dyn_cast<Constant>(Idx); 163 if (CVec && CNewElt && CIdx) 164 return Fold(ConstantExpr::getInsertElement(CVec, CNewElt, CIdx)); 165 return nullptr; 166 } 167 168 Value *FoldShuffleVector(Value *V1, Value *V2, 169 ArrayRef<int> Mask) const override { 170 auto *C1 = dyn_cast<Constant>(V1); 171 auto *C2 = dyn_cast<Constant>(V2); 172 if (C1 && C2) 173 return Fold(ConstantExpr::getShuffleVector(C1, C2, Mask)); 174 return nullptr; 175 } 176 177 //===--------------------------------------------------------------------===// 178 // Unary Operators 179 //===--------------------------------------------------------------------===// 180 181 Constant *CreateFNeg(Constant *C) const override { 182 return Fold(ConstantExpr::getFNeg(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 } 258 259 #endif 260