1 //===- ConstantFolder.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 ConstantFolder class, a helper for IRBuilder. 10 // It provides IRBuilder with a set of methods for creating constants 11 // with minimal folding. For general constant creation and folding, 12 // use ConstantExpr and the routines in llvm/Analysis/ConstantFolding.h. 13 // 14 //===----------------------------------------------------------------------===// 15 16 #ifndef LLVM_IR_CONSTANTFOLDER_H 17 #define LLVM_IR_CONSTANTFOLDER_H 18 19 #include "llvm/ADT/ArrayRef.h" 20 #include "llvm/ADT/STLExtras.h" 21 #include "llvm/IR/Constants.h" 22 #include "llvm/IR/ConstantFold.h" 23 #include "llvm/IR/IRBuilderFolder.h" 24 #include "llvm/IR/Instruction.h" 25 #include "llvm/IR/Operator.h" 26 27 namespace llvm { 28 29 /// ConstantFolder - Create constants with minimum, target independent, folding. 30 class ConstantFolder final : public IRBuilderFolder { 31 virtual void anchor(); 32 33 public: 34 explicit ConstantFolder() = default; 35 36 //===--------------------------------------------------------------------===// 37 // Value-based folders. 38 // 39 // Return an existing value or a constant if the operation can be simplified. 40 // Otherwise return nullptr. 41 //===--------------------------------------------------------------------===// 42 FoldBinOp(Instruction::BinaryOps Opc,Value * LHS,Value * RHS)43 Value *FoldBinOp(Instruction::BinaryOps Opc, Value *LHS, 44 Value *RHS) const override { 45 auto *LC = dyn_cast<Constant>(LHS); 46 auto *RC = dyn_cast<Constant>(RHS); 47 if (LC && RC) { 48 if (ConstantExpr::isDesirableBinOp(Opc)) 49 return ConstantExpr::get(Opc, LC, RC); 50 return ConstantFoldBinaryInstruction(Opc, LC, RC); 51 } 52 return nullptr; 53 } 54 FoldExactBinOp(Instruction::BinaryOps Opc,Value * LHS,Value * RHS,bool IsExact)55 Value *FoldExactBinOp(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, 56 bool IsExact) 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 ConstantExpr::get(Opc, LC, RC, 62 IsExact ? PossiblyExactOperator::IsExact : 0); 63 return ConstantFoldBinaryInstruction(Opc, LC, RC); 64 } 65 return nullptr; 66 } 67 FoldNoWrapBinOp(Instruction::BinaryOps Opc,Value * LHS,Value * RHS,bool HasNUW,bool HasNSW)68 Value *FoldNoWrapBinOp(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, 69 bool HasNUW, bool HasNSW) const override { 70 auto *LC = dyn_cast<Constant>(LHS); 71 auto *RC = dyn_cast<Constant>(RHS); 72 if (LC && RC) { 73 if (ConstantExpr::isDesirableBinOp(Opc)) { 74 unsigned Flags = 0; 75 if (HasNUW) 76 Flags |= OverflowingBinaryOperator::NoUnsignedWrap; 77 if (HasNSW) 78 Flags |= OverflowingBinaryOperator::NoSignedWrap; 79 return ConstantExpr::get(Opc, LC, RC, Flags); 80 } 81 return ConstantFoldBinaryInstruction(Opc, LC, RC); 82 } 83 return nullptr; 84 } 85 FoldBinOpFMF(Instruction::BinaryOps Opc,Value * LHS,Value * RHS,FastMathFlags FMF)86 Value *FoldBinOpFMF(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, 87 FastMathFlags FMF) const override { 88 return FoldBinOp(Opc, LHS, RHS); 89 } 90 FoldUnOpFMF(Instruction::UnaryOps Opc,Value * V,FastMathFlags FMF)91 Value *FoldUnOpFMF(Instruction::UnaryOps Opc, Value *V, 92 FastMathFlags FMF) const override { 93 if (Constant *C = dyn_cast<Constant>(V)) 94 return ConstantFoldUnaryInstruction(Opc, C); 95 return nullptr; 96 } 97 FoldICmp(CmpInst::Predicate P,Value * LHS,Value * RHS)98 Value *FoldICmp(CmpInst::Predicate P, Value *LHS, Value *RHS) const override { 99 auto *LC = dyn_cast<Constant>(LHS); 100 auto *RC = dyn_cast<Constant>(RHS); 101 if (LC && RC) 102 return ConstantExpr::getCompare(P, LC, RC); 103 return nullptr; 104 } 105 106 Value *FoldGEP(Type *Ty, Value *Ptr, ArrayRef<Value *> IdxList, 107 bool IsInBounds = false) const override { 108 if (!ConstantExpr::isSupportedGetElementPtr(Ty)) 109 return nullptr; 110 111 if (auto *PC = dyn_cast<Constant>(Ptr)) { 112 // Every index must be constant. 113 if (any_of(IdxList, [](Value *V) { return !isa<Constant>(V); })) 114 return nullptr; 115 116 if (IsInBounds) 117 return ConstantExpr::getInBoundsGetElementPtr(Ty, PC, IdxList); 118 else 119 return ConstantExpr::getGetElementPtr(Ty, PC, IdxList); 120 } 121 return nullptr; 122 } 123 FoldSelect(Value * C,Value * True,Value * False)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 ConstantFoldSelectInstruction(CC, TC, FC); 130 return nullptr; 131 } 132 FoldExtractValue(Value * Agg,ArrayRef<unsigned> IdxList)133 Value *FoldExtractValue(Value *Agg, 134 ArrayRef<unsigned> IdxList) const override { 135 if (auto *CAgg = dyn_cast<Constant>(Agg)) 136 return ConstantFoldExtractValueInstruction(CAgg, IdxList); 137 return nullptr; 138 }; 139 FoldInsertValue(Value * Agg,Value * Val,ArrayRef<unsigned> IdxList)140 Value *FoldInsertValue(Value *Agg, Value *Val, 141 ArrayRef<unsigned> IdxList) const override { 142 auto *CAgg = dyn_cast<Constant>(Agg); 143 auto *CVal = dyn_cast<Constant>(Val); 144 if (CAgg && CVal) 145 return ConstantFoldInsertValueInstruction(CAgg, CVal, IdxList); 146 return nullptr; 147 } 148 FoldExtractElement(Value * Vec,Value * Idx)149 Value *FoldExtractElement(Value *Vec, Value *Idx) const override { 150 auto *CVec = dyn_cast<Constant>(Vec); 151 auto *CIdx = dyn_cast<Constant>(Idx); 152 if (CVec && CIdx) 153 return ConstantExpr::getExtractElement(CVec, CIdx); 154 return nullptr; 155 } 156 FoldInsertElement(Value * Vec,Value * NewElt,Value * Idx)157 Value *FoldInsertElement(Value *Vec, Value *NewElt, 158 Value *Idx) const override { 159 auto *CVec = dyn_cast<Constant>(Vec); 160 auto *CNewElt = dyn_cast<Constant>(NewElt); 161 auto *CIdx = dyn_cast<Constant>(Idx); 162 if (CVec && CNewElt && CIdx) 163 return ConstantExpr::getInsertElement(CVec, CNewElt, CIdx); 164 return nullptr; 165 } 166 FoldShuffleVector(Value * V1,Value * V2,ArrayRef<int> Mask)167 Value *FoldShuffleVector(Value *V1, Value *V2, 168 ArrayRef<int> Mask) const override { 169 auto *C1 = dyn_cast<Constant>(V1); 170 auto *C2 = dyn_cast<Constant>(V2); 171 if (C1 && C2) 172 return ConstantExpr::getShuffleVector(C1, C2, Mask); 173 return nullptr; 174 } 175 FoldCast(Instruction::CastOps Op,Value * V,Type * DestTy)176 Value *FoldCast(Instruction::CastOps Op, Value *V, 177 Type *DestTy) const override { 178 if (auto *C = dyn_cast<Constant>(V)) { 179 if (ConstantExpr::isDesirableCastOp(Op)) 180 return ConstantExpr::getCast(Op, C, DestTy); 181 return ConstantFoldCastInstruction(Op, C, DestTy); 182 } 183 return nullptr; 184 } 185 186 //===--------------------------------------------------------------------===// 187 // Cast/Conversion Operators 188 //===--------------------------------------------------------------------===// 189 CreatePointerCast(Constant * C,Type * DestTy)190 Constant *CreatePointerCast(Constant *C, Type *DestTy) const override { 191 return ConstantExpr::getPointerCast(C, DestTy); 192 } 193 CreatePointerBitCastOrAddrSpaceCast(Constant * C,Type * DestTy)194 Constant *CreatePointerBitCastOrAddrSpaceCast(Constant *C, 195 Type *DestTy) const override { 196 return ConstantExpr::getPointerBitCastOrAddrSpaceCast(C, DestTy); 197 } 198 199 //===--------------------------------------------------------------------===// 200 // Compare Instructions 201 //===--------------------------------------------------------------------===// 202 CreateFCmp(CmpInst::Predicate P,Constant * LHS,Constant * RHS)203 Constant *CreateFCmp(CmpInst::Predicate P, Constant *LHS, 204 Constant *RHS) const override { 205 return ConstantExpr::getCompare(P, LHS, RHS); 206 } 207 }; 208 209 } // end namespace llvm 210 211 #endif // LLVM_IR_CONSTANTFOLDER_H 212