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 #include "llvm/Support/Compiler.h" 27 28 namespace llvm { 29 30 class Constant; 31 class DataLayout; 32 class Type; 33 34 /// TargetFolder - Create constants with target dependent folding. 35 class LLVM_ABI TargetFolder final : public IRBuilderFolder { 36 const DataLayout &DL; 37 38 /// Fold - Fold the constant using target specific information. Fold(Constant * C)39 Constant *Fold(Constant *C) const { 40 return ConstantFoldConstant(C, DL); 41 } 42 43 LLVM_DECLARE_VIRTUAL_ANCHOR_FUNCTION(); 44 45 public: TargetFolder(const DataLayout & DL)46 explicit TargetFolder(const DataLayout &DL) : DL(DL) {} 47 48 //===--------------------------------------------------------------------===// 49 // Value-based folders. 50 // 51 // Return an existing value or a constant if the operation can be simplified. 52 // Otherwise return nullptr. 53 //===--------------------------------------------------------------------===// 54 FoldBinOp(Instruction::BinaryOps Opc,Value * LHS,Value * RHS)55 Value *FoldBinOp(Instruction::BinaryOps Opc, Value *LHS, 56 Value *RHS) const override { 57 auto *LC = dyn_cast<Constant>(LHS); 58 auto *RC = dyn_cast<Constant>(RHS); 59 if (LC && RC) { 60 if (ConstantExpr::isDesirableBinOp(Opc)) 61 return Fold(ConstantExpr::get(Opc, LC, RC)); 62 return ConstantFoldBinaryOpOperands(Opc, LC, RC, DL); 63 } 64 return nullptr; 65 } 66 FoldExactBinOp(Instruction::BinaryOps Opc,Value * LHS,Value * RHS,bool IsExact)67 Value *FoldExactBinOp(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, 68 bool IsExact) const override { 69 auto *LC = dyn_cast<Constant>(LHS); 70 auto *RC = dyn_cast<Constant>(RHS); 71 if (LC && RC) { 72 if (ConstantExpr::isDesirableBinOp(Opc)) 73 return Fold(ConstantExpr::get( 74 Opc, LC, RC, IsExact ? PossiblyExactOperator::IsExact : 0)); 75 return ConstantFoldBinaryOpOperands(Opc, LC, RC, DL); 76 } 77 return nullptr; 78 } 79 FoldNoWrapBinOp(Instruction::BinaryOps Opc,Value * LHS,Value * RHS,bool HasNUW,bool HasNSW)80 Value *FoldNoWrapBinOp(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, 81 bool HasNUW, bool HasNSW) const override { 82 auto *LC = dyn_cast<Constant>(LHS); 83 auto *RC = dyn_cast<Constant>(RHS); 84 if (LC && RC) { 85 if (ConstantExpr::isDesirableBinOp(Opc)) { 86 unsigned Flags = 0; 87 if (HasNUW) 88 Flags |= OverflowingBinaryOperator::NoUnsignedWrap; 89 if (HasNSW) 90 Flags |= OverflowingBinaryOperator::NoSignedWrap; 91 return Fold(ConstantExpr::get(Opc, LC, RC, Flags)); 92 } 93 return ConstantFoldBinaryOpOperands(Opc, LC, RC, DL); 94 } 95 return nullptr; 96 } 97 FoldBinOpFMF(Instruction::BinaryOps Opc,Value * LHS,Value * RHS,FastMathFlags FMF)98 Value *FoldBinOpFMF(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, 99 FastMathFlags FMF) const override { 100 return FoldBinOp(Opc, LHS, RHS); 101 } 102 FoldCmp(CmpInst::Predicate P,Value * LHS,Value * RHS)103 Value *FoldCmp(CmpInst::Predicate P, Value *LHS, Value *RHS) const override { 104 auto *LC = dyn_cast<Constant>(LHS); 105 auto *RC = dyn_cast<Constant>(RHS); 106 if (LC && RC) 107 return ConstantFoldCompareInstOperands(P, LC, RC, DL); 108 return nullptr; 109 } 110 FoldUnOpFMF(Instruction::UnaryOps Opc,Value * V,FastMathFlags FMF)111 Value *FoldUnOpFMF(Instruction::UnaryOps Opc, Value *V, 112 FastMathFlags FMF) const override { 113 if (Constant *C = dyn_cast<Constant>(V)) 114 return ConstantFoldUnaryOpOperand(Opc, C, DL); 115 return nullptr; 116 } 117 FoldGEP(Type * Ty,Value * Ptr,ArrayRef<Value * > IdxList,GEPNoWrapFlags NW)118 Value *FoldGEP(Type *Ty, Value *Ptr, ArrayRef<Value *> IdxList, 119 GEPNoWrapFlags NW) const override { 120 if (!ConstantExpr::isSupportedGetElementPtr(Ty)) 121 return nullptr; 122 123 if (auto *PC = dyn_cast<Constant>(Ptr)) { 124 // Every index must be constant. 125 if (any_of(IdxList, [](Value *V) { return !isa<Constant>(V); })) 126 return nullptr; 127 return Fold(ConstantExpr::getGetElementPtr(Ty, PC, IdxList, NW)); 128 } 129 return nullptr; 130 } 131 FoldSelect(Value * C,Value * True,Value * False)132 Value *FoldSelect(Value *C, Value *True, Value *False) const override { 133 auto *CC = dyn_cast<Constant>(C); 134 auto *TC = dyn_cast<Constant>(True); 135 auto *FC = dyn_cast<Constant>(False); 136 if (CC && TC && FC) 137 return ConstantFoldSelectInstruction(CC, TC, FC); 138 139 return nullptr; 140 } 141 FoldExtractValue(Value * Agg,ArrayRef<unsigned> IdxList)142 Value *FoldExtractValue(Value *Agg, 143 ArrayRef<unsigned> IdxList) const override { 144 if (auto *CAgg = dyn_cast<Constant>(Agg)) 145 return ConstantFoldExtractValueInstruction(CAgg, IdxList); 146 return nullptr; 147 }; 148 FoldInsertValue(Value * Agg,Value * Val,ArrayRef<unsigned> IdxList)149 Value *FoldInsertValue(Value *Agg, Value *Val, 150 ArrayRef<unsigned> IdxList) const override { 151 auto *CAgg = dyn_cast<Constant>(Agg); 152 auto *CVal = dyn_cast<Constant>(Val); 153 if (CAgg && CVal) 154 return ConstantFoldInsertValueInstruction(CAgg, CVal, IdxList); 155 return nullptr; 156 } 157 FoldExtractElement(Value * Vec,Value * Idx)158 Value *FoldExtractElement(Value *Vec, Value *Idx) const override { 159 auto *CVec = dyn_cast<Constant>(Vec); 160 auto *CIdx = dyn_cast<Constant>(Idx); 161 if (CVec && CIdx) 162 return Fold(ConstantExpr::getExtractElement(CVec, CIdx)); 163 return nullptr; 164 } 165 FoldInsertElement(Value * Vec,Value * NewElt,Value * Idx)166 Value *FoldInsertElement(Value *Vec, Value *NewElt, 167 Value *Idx) const override { 168 auto *CVec = dyn_cast<Constant>(Vec); 169 auto *CNewElt = dyn_cast<Constant>(NewElt); 170 auto *CIdx = dyn_cast<Constant>(Idx); 171 if (CVec && CNewElt && CIdx) 172 return Fold(ConstantExpr::getInsertElement(CVec, CNewElt, CIdx)); 173 return nullptr; 174 } 175 FoldShuffleVector(Value * V1,Value * V2,ArrayRef<int> Mask)176 Value *FoldShuffleVector(Value *V1, Value *V2, 177 ArrayRef<int> Mask) const override { 178 auto *C1 = dyn_cast<Constant>(V1); 179 auto *C2 = dyn_cast<Constant>(V2); 180 if (C1 && C2) 181 return Fold(ConstantExpr::getShuffleVector(C1, C2, Mask)); 182 return nullptr; 183 } 184 FoldCast(Instruction::CastOps Op,Value * V,Type * DestTy)185 Value *FoldCast(Instruction::CastOps Op, Value *V, 186 Type *DestTy) const override { 187 if (auto *C = dyn_cast<Constant>(V)) 188 return ConstantFoldCastOperand(Op, C, DestTy, DL); 189 return nullptr; 190 } 191 FoldBinaryIntrinsic(Intrinsic::ID ID,Value * LHS,Value * RHS,Type * Ty,Instruction * FMFSource)192 Value *FoldBinaryIntrinsic(Intrinsic::ID ID, Value *LHS, Value *RHS, Type *Ty, 193 Instruction *FMFSource) const override { 194 auto *C1 = dyn_cast<Constant>(LHS); 195 auto *C2 = dyn_cast<Constant>(RHS); 196 if (C1 && C2) 197 return ConstantFoldBinaryIntrinsic(ID, C1, C2, Ty, FMFSource); 198 return nullptr; 199 } 200 201 //===--------------------------------------------------------------------===// 202 // Cast/Conversion Operators 203 //===--------------------------------------------------------------------===// 204 CreatePointerCast(Constant * C,Type * DestTy)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 CreatePointerBitCastOrAddrSpaceCast(Constant * C,Type * DestTy)211 Constant *CreatePointerBitCastOrAddrSpaceCast(Constant *C, 212 Type *DestTy) const override { 213 if (C->getType() == DestTy) 214 return C; // avoid calling Fold 215 return Fold(ConstantExpr::getPointerBitCastOrAddrSpaceCast(C, DestTy)); 216 } 217 }; 218 } 219 220 #endif 221