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 Fold(ConstantExpr::getCompare(P, LC, RC)); 107 return nullptr; 108 } 109 110 Value *FoldUnOpFMF(Instruction::UnaryOps Opc, Value *V, 111 FastMathFlags FMF) const override { 112 if (Constant *C = dyn_cast<Constant>(V)) 113 return ConstantFoldUnaryOpOperand(Opc, C, DL); 114 return nullptr; 115 } 116 117 Value *FoldGEP(Type *Ty, Value *Ptr, ArrayRef<Value *> IdxList, 118 bool IsInBounds = false) const override { 119 if (auto *PC = dyn_cast<Constant>(Ptr)) { 120 // Every index must be constant. 121 if (any_of(IdxList, [](Value *V) { return !isa<Constant>(V); })) 122 return nullptr; 123 if (IsInBounds) 124 return Fold(ConstantExpr::getInBoundsGetElementPtr(Ty, PC, IdxList)); 125 else 126 return Fold(ConstantExpr::getGetElementPtr(Ty, PC, IdxList)); 127 } 128 return nullptr; 129 } 130 131 Value *FoldSelect(Value *C, Value *True, Value *False) const override { 132 auto *CC = dyn_cast<Constant>(C); 133 auto *TC = dyn_cast<Constant>(True); 134 auto *FC = dyn_cast<Constant>(False); 135 if (CC && TC && FC) 136 return Fold(ConstantExpr::getSelect(CC, TC, FC)); 137 138 return nullptr; 139 } 140 141 Value *FoldExtractValue(Value *Agg, 142 ArrayRef<unsigned> IdxList) const override { 143 if (auto *CAgg = dyn_cast<Constant>(Agg)) 144 return ConstantFoldExtractValueInstruction(CAgg, IdxList); 145 return nullptr; 146 }; 147 148 Value *FoldInsertValue(Value *Agg, Value *Val, 149 ArrayRef<unsigned> IdxList) const override { 150 auto *CAgg = dyn_cast<Constant>(Agg); 151 auto *CVal = dyn_cast<Constant>(Val); 152 if (CAgg && CVal) 153 return ConstantFoldInsertValueInstruction(CAgg, CVal, IdxList); 154 return nullptr; 155 } 156 157 Value *FoldExtractElement(Value *Vec, Value *Idx) const override { 158 auto *CVec = dyn_cast<Constant>(Vec); 159 auto *CIdx = dyn_cast<Constant>(Idx); 160 if (CVec && CIdx) 161 return Fold(ConstantExpr::getExtractElement(CVec, CIdx)); 162 return nullptr; 163 } 164 165 Value *FoldInsertElement(Value *Vec, Value *NewElt, 166 Value *Idx) const override { 167 auto *CVec = dyn_cast<Constant>(Vec); 168 auto *CNewElt = dyn_cast<Constant>(NewElt); 169 auto *CIdx = dyn_cast<Constant>(Idx); 170 if (CVec && CNewElt && CIdx) 171 return Fold(ConstantExpr::getInsertElement(CVec, CNewElt, CIdx)); 172 return nullptr; 173 } 174 175 Value *FoldShuffleVector(Value *V1, Value *V2, 176 ArrayRef<int> Mask) const override { 177 auto *C1 = dyn_cast<Constant>(V1); 178 auto *C2 = dyn_cast<Constant>(V2); 179 if (C1 && C2) 180 return Fold(ConstantExpr::getShuffleVector(C1, C2, Mask)); 181 return nullptr; 182 } 183 184 //===--------------------------------------------------------------------===// 185 // Cast/Conversion Operators 186 //===--------------------------------------------------------------------===// 187 188 Constant *CreateCast(Instruction::CastOps Op, Constant *C, 189 Type *DestTy) const override { 190 if (C->getType() == DestTy) 191 return C; // avoid calling Fold 192 return Fold(ConstantExpr::getCast(Op, C, DestTy)); 193 } 194 Constant *CreateIntCast(Constant *C, Type *DestTy, 195 bool isSigned) const override { 196 if (C->getType() == DestTy) 197 return C; // avoid calling Fold 198 return Fold(ConstantExpr::getIntegerCast(C, DestTy, isSigned)); 199 } 200 Constant *CreatePointerCast(Constant *C, Type *DestTy) const override { 201 if (C->getType() == DestTy) 202 return C; // avoid calling Fold 203 return Fold(ConstantExpr::getPointerCast(C, DestTy)); 204 } 205 Constant *CreateFPCast(Constant *C, Type *DestTy) const override { 206 if (C->getType() == DestTy) 207 return C; // avoid calling Fold 208 return Fold(ConstantExpr::getFPCast(C, DestTy)); 209 } 210 Constant *CreateBitCast(Constant *C, Type *DestTy) const override { 211 return CreateCast(Instruction::BitCast, C, DestTy); 212 } 213 Constant *CreateIntToPtr(Constant *C, Type *DestTy) const override { 214 return CreateCast(Instruction::IntToPtr, C, DestTy); 215 } 216 Constant *CreatePtrToInt(Constant *C, Type *DestTy) const override { 217 return CreateCast(Instruction::PtrToInt, C, DestTy); 218 } 219 Constant *CreateZExtOrBitCast(Constant *C, Type *DestTy) const override { 220 if (C->getType() == DestTy) 221 return C; // avoid calling Fold 222 return Fold(ConstantExpr::getZExtOrBitCast(C, DestTy)); 223 } 224 Constant *CreateSExtOrBitCast(Constant *C, Type *DestTy) const override { 225 if (C->getType() == DestTy) 226 return C; // avoid calling Fold 227 return Fold(ConstantExpr::getSExtOrBitCast(C, DestTy)); 228 } 229 Constant *CreateTruncOrBitCast(Constant *C, Type *DestTy) const override { 230 if (C->getType() == DestTy) 231 return C; // avoid calling Fold 232 return Fold(ConstantExpr::getTruncOrBitCast(C, DestTy)); 233 } 234 235 Constant *CreatePointerBitCastOrAddrSpaceCast(Constant *C, 236 Type *DestTy) const override { 237 if (C->getType() == DestTy) 238 return C; // avoid calling Fold 239 return Fold(ConstantExpr::getPointerBitCastOrAddrSpaceCast(C, DestTy)); 240 } 241 242 //===--------------------------------------------------------------------===// 243 // Compare Instructions 244 //===--------------------------------------------------------------------===// 245 246 Constant *CreateFCmp(CmpInst::Predicate P, Constant *LHS, 247 Constant *RHS) const override { 248 return Fold(ConstantExpr::getCompare(P, LHS, RHS)); 249 } 250 }; 251 252 } 253 254 #endif 255