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. Fold(Constant * C)38 Constant *Fold(Constant *C) const { 39 return ConstantFoldConstant(C, DL); 40 } 41 42 virtual void anchor(); 43 44 public: TargetFolder(const DataLayout & DL)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 FoldBinOp(Instruction::BinaryOps Opc,Value * LHS,Value * RHS)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 FoldExactBinOp(Instruction::BinaryOps Opc,Value * LHS,Value * RHS,bool IsExact)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 FoldNoWrapBinOp(Instruction::BinaryOps Opc,Value * LHS,Value * RHS,bool HasNUW,bool HasNSW)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 FoldBinOpFMF(Instruction::BinaryOps Opc,Value * LHS,Value * RHS,FastMathFlags FMF)97 Value *FoldBinOpFMF(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, 98 FastMathFlags FMF) const override { 99 return FoldBinOp(Opc, LHS, RHS); 100 } 101 FoldCmp(CmpInst::Predicate P,Value * LHS,Value * RHS)102 Value *FoldCmp(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 ConstantFoldCompareInstOperands(P, LC, RC, DL); 107 return nullptr; 108 } 109 FoldUnOpFMF(Instruction::UnaryOps Opc,Value * V,FastMathFlags FMF)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 FoldGEP(Type * Ty,Value * Ptr,ArrayRef<Value * > IdxList,GEPNoWrapFlags NW)117 Value *FoldGEP(Type *Ty, Value *Ptr, ArrayRef<Value *> IdxList, 118 GEPNoWrapFlags NW) const override { 119 if (!ConstantExpr::isSupportedGetElementPtr(Ty)) 120 return nullptr; 121 122 if (auto *PC = dyn_cast<Constant>(Ptr)) { 123 // Every index must be constant. 124 if (any_of(IdxList, [](Value *V) { return !isa<Constant>(V); })) 125 return nullptr; 126 return Fold(ConstantExpr::getGetElementPtr(Ty, PC, IdxList, NW)); 127 } 128 return nullptr; 129 } 130 FoldSelect(Value * C,Value * True,Value * False)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 ConstantFoldSelectInstruction(CC, TC, FC); 137 138 return nullptr; 139 } 140 FoldExtractValue(Value * Agg,ArrayRef<unsigned> IdxList)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 FoldInsertValue(Value * Agg,Value * Val,ArrayRef<unsigned> IdxList)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 FoldExtractElement(Value * Vec,Value * Idx)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 FoldInsertElement(Value * Vec,Value * NewElt,Value * Idx)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 FoldShuffleVector(Value * V1,Value * V2,ArrayRef<int> Mask)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 FoldCast(Instruction::CastOps Op,Value * V,Type * DestTy)184 Value *FoldCast(Instruction::CastOps Op, Value *V, 185 Type *DestTy) const override { 186 if (auto *C = dyn_cast<Constant>(V)) 187 return ConstantFoldCastOperand(Op, C, DestTy, DL); 188 return nullptr; 189 } 190 FoldBinaryIntrinsic(Intrinsic::ID ID,Value * LHS,Value * RHS,Type * Ty,Instruction * FMFSource)191 Value *FoldBinaryIntrinsic(Intrinsic::ID ID, Value *LHS, Value *RHS, Type *Ty, 192 Instruction *FMFSource) const override { 193 auto *C1 = dyn_cast<Constant>(LHS); 194 auto *C2 = dyn_cast<Constant>(RHS); 195 if (C1 && C2) 196 return ConstantFoldBinaryIntrinsic(ID, C1, C2, Ty, FMFSource); 197 return nullptr; 198 } 199 200 //===--------------------------------------------------------------------===// 201 // Cast/Conversion Operators 202 //===--------------------------------------------------------------------===// 203 CreatePointerCast(Constant * C,Type * DestTy)204 Constant *CreatePointerCast(Constant *C, Type *DestTy) const override { 205 if (C->getType() == DestTy) 206 return C; // avoid calling Fold 207 return Fold(ConstantExpr::getPointerCast(C, DestTy)); 208 } 209 CreatePointerBitCastOrAddrSpaceCast(Constant * C,Type * DestTy)210 Constant *CreatePointerBitCastOrAddrSpaceCast(Constant *C, 211 Type *DestTy) const override { 212 if (C->getType() == DestTy) 213 return C; // avoid calling Fold 214 return Fold(ConstantExpr::getPointerBitCastOrAddrSpaceCast(C, DestTy)); 215 } 216 }; 217 218 } 219 220 #endif 221