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 FoldICmp(CmpInst::Predicate P,Value * LHS,Value * RHS)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 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 117 Value *FoldGEP(Type *Ty, Value *Ptr, ArrayRef<Value *> IdxList, 118 bool IsInBounds = false) 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 if (IsInBounds) 127 return Fold(ConstantExpr::getInBoundsGetElementPtr(Ty, PC, IdxList)); 128 else 129 return Fold(ConstantExpr::getGetElementPtr(Ty, PC, IdxList)); 130 } 131 return nullptr; 132 } 133 FoldSelect(Value * C,Value * True,Value * False)134 Value *FoldSelect(Value *C, Value *True, Value *False) const override { 135 auto *CC = dyn_cast<Constant>(C); 136 auto *TC = dyn_cast<Constant>(True); 137 auto *FC = dyn_cast<Constant>(False); 138 if (CC && TC && FC) 139 return ConstantFoldSelectInstruction(CC, TC, FC); 140 141 return nullptr; 142 } 143 FoldExtractValue(Value * Agg,ArrayRef<unsigned> IdxList)144 Value *FoldExtractValue(Value *Agg, 145 ArrayRef<unsigned> IdxList) const override { 146 if (auto *CAgg = dyn_cast<Constant>(Agg)) 147 return ConstantFoldExtractValueInstruction(CAgg, IdxList); 148 return nullptr; 149 }; 150 FoldInsertValue(Value * Agg,Value * Val,ArrayRef<unsigned> IdxList)151 Value *FoldInsertValue(Value *Agg, Value *Val, 152 ArrayRef<unsigned> IdxList) const override { 153 auto *CAgg = dyn_cast<Constant>(Agg); 154 auto *CVal = dyn_cast<Constant>(Val); 155 if (CAgg && CVal) 156 return ConstantFoldInsertValueInstruction(CAgg, CVal, IdxList); 157 return nullptr; 158 } 159 FoldExtractElement(Value * Vec,Value * Idx)160 Value *FoldExtractElement(Value *Vec, Value *Idx) const override { 161 auto *CVec = dyn_cast<Constant>(Vec); 162 auto *CIdx = dyn_cast<Constant>(Idx); 163 if (CVec && CIdx) 164 return Fold(ConstantExpr::getExtractElement(CVec, CIdx)); 165 return nullptr; 166 } 167 FoldInsertElement(Value * Vec,Value * NewElt,Value * Idx)168 Value *FoldInsertElement(Value *Vec, Value *NewElt, 169 Value *Idx) const override { 170 auto *CVec = dyn_cast<Constant>(Vec); 171 auto *CNewElt = dyn_cast<Constant>(NewElt); 172 auto *CIdx = dyn_cast<Constant>(Idx); 173 if (CVec && CNewElt && CIdx) 174 return Fold(ConstantExpr::getInsertElement(CVec, CNewElt, CIdx)); 175 return nullptr; 176 } 177 FoldShuffleVector(Value * V1,Value * V2,ArrayRef<int> Mask)178 Value *FoldShuffleVector(Value *V1, Value *V2, 179 ArrayRef<int> Mask) const override { 180 auto *C1 = dyn_cast<Constant>(V1); 181 auto *C2 = dyn_cast<Constant>(V2); 182 if (C1 && C2) 183 return Fold(ConstantExpr::getShuffleVector(C1, C2, Mask)); 184 return nullptr; 185 } 186 FoldCast(Instruction::CastOps Op,Value * V,Type * DestTy)187 Value *FoldCast(Instruction::CastOps Op, Value *V, 188 Type *DestTy) const override { 189 if (auto *C = dyn_cast<Constant>(V)) 190 return ConstantFoldCastOperand(Op, C, DestTy, DL); 191 return nullptr; 192 } 193 194 //===--------------------------------------------------------------------===// 195 // Cast/Conversion Operators 196 //===--------------------------------------------------------------------===// 197 CreatePointerCast(Constant * C,Type * DestTy)198 Constant *CreatePointerCast(Constant *C, Type *DestTy) const override { 199 if (C->getType() == DestTy) 200 return C; // avoid calling Fold 201 return Fold(ConstantExpr::getPointerCast(C, DestTy)); 202 } 203 CreatePointerBitCastOrAddrSpaceCast(Constant * C,Type * DestTy)204 Constant *CreatePointerBitCastOrAddrSpaceCast(Constant *C, 205 Type *DestTy) const override { 206 if (C->getType() == DestTy) 207 return C; // avoid calling Fold 208 return Fold(ConstantExpr::getPointerBitCastOrAddrSpaceCast(C, DestTy)); 209 } 210 211 //===--------------------------------------------------------------------===// 212 // Compare Instructions 213 //===--------------------------------------------------------------------===// 214 CreateFCmp(CmpInst::Predicate P,Constant * LHS,Constant * RHS)215 Constant *CreateFCmp(CmpInst::Predicate P, Constant *LHS, 216 Constant *RHS) const override { 217 return Fold(ConstantExpr::getCompare(P, LHS, RHS)); 218 } 219 }; 220 221 } 222 223 #endif 224