1 //===- InstSimplifyFolder.h - InstSimplify 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 InstSimplifyFolder class, a helper for IRBuilder. 10 // It provides IRBuilder with a set of methods for folding operations to 11 // existing values using InstructionSimplify. At the moment, only a subset of 12 // the implementation uses InstructionSimplify. The rest of the implementation 13 // only folds constants. 14 // 15 // The folder also applies target-specific constant folding. 16 // 17 //===----------------------------------------------------------------------===// 18 19 #ifndef LLVM_ANALYSIS_INSTSIMPLIFYFOLDER_H 20 #define LLVM_ANALYSIS_INSTSIMPLIFYFOLDER_H 21 22 #include "llvm/ADT/ArrayRef.h" 23 #include "llvm/Analysis/InstructionSimplify.h" 24 #include "llvm/Analysis/TargetFolder.h" 25 #include "llvm/IR/CmpPredicate.h" 26 #include "llvm/IR/IRBuilderFolder.h" 27 #include "llvm/IR/Instruction.h" 28 #include "llvm/Support/Compiler.h" 29 30 namespace llvm { 31 class Constant; 32 33 /// InstSimplifyFolder - Use InstructionSimplify to fold operations to existing 34 /// values. Also applies target-specific constant folding when not using 35 /// InstructionSimplify. 36 class LLVM_ABI InstSimplifyFolder final : public IRBuilderFolder { 37 TargetFolder ConstFolder; 38 SimplifyQuery SQ; 39 40 LLVM_DECLARE_VIRTUAL_ANCHOR_FUNCTION(); 41 42 public: InstSimplifyFolder(const DataLayout & DL)43 explicit InstSimplifyFolder(const DataLayout &DL) : ConstFolder(DL), SQ(DL) {} 44 45 //===--------------------------------------------------------------------===// 46 // Value-based folders. 47 // 48 // Return an existing value or a constant if the operation can be simplified. 49 // Otherwise return nullptr. 50 //===--------------------------------------------------------------------===// 51 FoldBinOp(Instruction::BinaryOps Opc,Value * LHS,Value * RHS)52 Value *FoldBinOp(Instruction::BinaryOps Opc, Value *LHS, 53 Value *RHS) const override { 54 return simplifyBinOp(Opc, LHS, RHS, SQ); 55 } 56 FoldExactBinOp(Instruction::BinaryOps Opc,Value * LHS,Value * RHS,bool IsExact)57 Value *FoldExactBinOp(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, 58 bool IsExact) const override { 59 return simplifyBinOp(Opc, LHS, RHS, SQ); 60 } 61 FoldNoWrapBinOp(Instruction::BinaryOps Opc,Value * LHS,Value * RHS,bool HasNUW,bool HasNSW)62 Value *FoldNoWrapBinOp(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, 63 bool HasNUW, bool HasNSW) const override { 64 return simplifyBinOp(Opc, LHS, RHS, SQ); 65 } 66 FoldBinOpFMF(Instruction::BinaryOps Opc,Value * LHS,Value * RHS,FastMathFlags FMF)67 Value *FoldBinOpFMF(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, 68 FastMathFlags FMF) const override { 69 return simplifyBinOp(Opc, LHS, RHS, FMF, SQ); 70 } 71 FoldUnOpFMF(Instruction::UnaryOps Opc,Value * V,FastMathFlags FMF)72 Value *FoldUnOpFMF(Instruction::UnaryOps Opc, Value *V, 73 FastMathFlags FMF) const override { 74 return simplifyUnOp(Opc, V, FMF, SQ); 75 } 76 FoldCmp(CmpInst::Predicate P,Value * LHS,Value * RHS)77 Value *FoldCmp(CmpInst::Predicate P, Value *LHS, Value *RHS) const override { 78 return simplifyCmpInst(P, LHS, RHS, SQ); 79 } 80 FoldGEP(Type * Ty,Value * Ptr,ArrayRef<Value * > IdxList,GEPNoWrapFlags NW)81 Value *FoldGEP(Type *Ty, Value *Ptr, ArrayRef<Value *> IdxList, 82 GEPNoWrapFlags NW) const override { 83 return simplifyGEPInst(Ty, Ptr, IdxList, NW, SQ); 84 } 85 FoldSelect(Value * C,Value * True,Value * False)86 Value *FoldSelect(Value *C, Value *True, Value *False) const override { 87 return simplifySelectInst(C, True, False, SQ); 88 } 89 FoldExtractValue(Value * Agg,ArrayRef<unsigned> IdxList)90 Value *FoldExtractValue(Value *Agg, 91 ArrayRef<unsigned> IdxList) const override { 92 return simplifyExtractValueInst(Agg, IdxList, SQ); 93 }; 94 FoldInsertValue(Value * Agg,Value * Val,ArrayRef<unsigned> IdxList)95 Value *FoldInsertValue(Value *Agg, Value *Val, 96 ArrayRef<unsigned> IdxList) const override { 97 return simplifyInsertValueInst(Agg, Val, IdxList, SQ); 98 } 99 FoldExtractElement(Value * Vec,Value * Idx)100 Value *FoldExtractElement(Value *Vec, Value *Idx) const override { 101 return simplifyExtractElementInst(Vec, Idx, SQ); 102 } 103 FoldInsertElement(Value * Vec,Value * NewElt,Value * Idx)104 Value *FoldInsertElement(Value *Vec, Value *NewElt, 105 Value *Idx) const override { 106 return simplifyInsertElementInst(Vec, NewElt, Idx, SQ); 107 } 108 FoldShuffleVector(Value * V1,Value * V2,ArrayRef<int> Mask)109 Value *FoldShuffleVector(Value *V1, Value *V2, 110 ArrayRef<int> Mask) const override { 111 Type *RetTy = VectorType::get( 112 cast<VectorType>(V1->getType())->getElementType(), Mask.size(), 113 isa<ScalableVectorType>(V1->getType())); 114 return simplifyShuffleVectorInst(V1, V2, Mask, RetTy, SQ); 115 } 116 FoldCast(Instruction::CastOps Op,Value * V,Type * DestTy)117 Value *FoldCast(Instruction::CastOps Op, Value *V, 118 Type *DestTy) const override { 119 return simplifyCastInst(Op, V, DestTy, SQ); 120 } 121 FoldBinaryIntrinsic(Intrinsic::ID ID,Value * LHS,Value * RHS,Type * Ty,Instruction * FMFSource)122 Value *FoldBinaryIntrinsic(Intrinsic::ID ID, Value *LHS, Value *RHS, Type *Ty, 123 Instruction *FMFSource) const override { 124 return simplifyBinaryIntrinsic(ID, Ty, LHS, RHS, SQ, 125 dyn_cast_if_present<CallBase>(FMFSource)); 126 } 127 128 //===--------------------------------------------------------------------===// 129 // Cast/Conversion Operators 130 //===--------------------------------------------------------------------===// 131 CreatePointerCast(Constant * C,Type * DestTy)132 Value *CreatePointerCast(Constant *C, Type *DestTy) const override { 133 if (C->getType() == DestTy) 134 return C; // avoid calling Fold 135 return ConstFolder.CreatePointerCast(C, DestTy); 136 } 137 CreatePointerBitCastOrAddrSpaceCast(Constant * C,Type * DestTy)138 Value *CreatePointerBitCastOrAddrSpaceCast(Constant *C, 139 Type *DestTy) const override { 140 if (C->getType() == DestTy) 141 return C; // avoid calling Fold 142 return ConstFolder.CreatePointerBitCastOrAddrSpaceCast(C, DestTy); 143 } 144 }; 145 146 } // end namespace llvm 147 148 #endif // LLVM_ANALYSIS_INSTSIMPLIFYFOLDER_H 149