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/IRBuilderFolder.h" 26 #include "llvm/IR/Instruction.h" 27 28 namespace llvm { 29 class Constant; 30 31 /// InstSimplifyFolder - Use InstructionSimplify to fold operations to existing 32 /// values. Also applies target-specific constant folding when not using 33 /// InstructionSimplify. 34 class InstSimplifyFolder final : public IRBuilderFolder { 35 TargetFolder ConstFolder; 36 SimplifyQuery SQ; 37 38 virtual void anchor(); 39 40 public: 41 InstSimplifyFolder(const DataLayout &DL) : ConstFolder(DL), SQ(DL) {} 42 43 //===--------------------------------------------------------------------===// 44 // Value-based folders. 45 // 46 // Return an existing value or a constant if the operation can be simplified. 47 // Otherwise return nullptr. 48 //===--------------------------------------------------------------------===// 49 50 Value *FoldBinOp(Instruction::BinaryOps Opc, Value *LHS, 51 Value *RHS) const override { 52 return simplifyBinOp(Opc, LHS, RHS, SQ); 53 } 54 55 Value *FoldExactBinOp(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, 56 bool IsExact) const override { 57 return simplifyBinOp(Opc, LHS, RHS, SQ); 58 } 59 60 Value *FoldNoWrapBinOp(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, 61 bool HasNUW, bool HasNSW) const override { 62 return simplifyBinOp(Opc, LHS, RHS, SQ); 63 } 64 65 Value *FoldBinOpFMF(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, 66 FastMathFlags FMF) const override { 67 return simplifyBinOp(Opc, LHS, RHS, FMF, SQ); 68 } 69 70 Value *FoldICmp(CmpInst::Predicate P, Value *LHS, Value *RHS) const override { 71 return simplifyICmpInst(P, LHS, RHS, SQ); 72 } 73 74 Value *FoldGEP(Type *Ty, Value *Ptr, ArrayRef<Value *> IdxList, 75 bool IsInBounds = false) const override { 76 return simplifyGEPInst(Ty, Ptr, IdxList, IsInBounds, SQ); 77 } 78 79 Value *FoldSelect(Value *C, Value *True, Value *False) const override { 80 return simplifySelectInst(C, True, False, SQ); 81 } 82 83 Value *FoldExtractValue(Value *Agg, 84 ArrayRef<unsigned> IdxList) const override { 85 return simplifyExtractValueInst(Agg, IdxList, SQ); 86 }; 87 88 Value *FoldInsertValue(Value *Agg, Value *Val, 89 ArrayRef<unsigned> IdxList) const override { 90 return simplifyInsertValueInst(Agg, Val, IdxList, SQ); 91 } 92 93 Value *FoldExtractElement(Value *Vec, Value *Idx) const override { 94 return simplifyExtractElementInst(Vec, Idx, SQ); 95 } 96 97 Value *FoldInsertElement(Value *Vec, Value *NewElt, 98 Value *Idx) const override { 99 return simplifyInsertElementInst(Vec, NewElt, Idx, SQ); 100 } 101 102 Value *FoldShuffleVector(Value *V1, Value *V2, 103 ArrayRef<int> Mask) const override { 104 Type *RetTy = VectorType::get( 105 cast<VectorType>(V1->getType())->getElementType(), Mask.size(), 106 isa<ScalableVectorType>(V1->getType())); 107 return simplifyShuffleVectorInst(V1, V2, Mask, RetTy, SQ); 108 } 109 110 //===--------------------------------------------------------------------===// 111 // Unary Operators 112 //===--------------------------------------------------------------------===// 113 114 Value *CreateFNeg(Constant *C) const override { 115 return ConstFolder.CreateFNeg(C); 116 } 117 118 Value *CreateUnOp(Instruction::UnaryOps Opc, Constant *C) const override { 119 return ConstFolder.CreateUnOp(Opc, C); 120 } 121 122 //===--------------------------------------------------------------------===// 123 // Cast/Conversion Operators 124 //===--------------------------------------------------------------------===// 125 126 Value *CreateCast(Instruction::CastOps Op, Constant *C, 127 Type *DestTy) const override { 128 if (C->getType() == DestTy) 129 return C; // avoid calling Fold 130 return ConstFolder.CreateCast(Op, C, DestTy); 131 } 132 Value *CreateIntCast(Constant *C, Type *DestTy, 133 bool isSigned) const override { 134 if (C->getType() == DestTy) 135 return C; // avoid calling Fold 136 return ConstFolder.CreateIntCast(C, DestTy, isSigned); 137 } 138 Value *CreatePointerCast(Constant *C, Type *DestTy) const override { 139 if (C->getType() == DestTy) 140 return C; // avoid calling Fold 141 return ConstFolder.CreatePointerCast(C, DestTy); 142 } 143 Value *CreateFPCast(Constant *C, Type *DestTy) const override { 144 if (C->getType() == DestTy) 145 return C; // avoid calling Fold 146 return ConstFolder.CreateFPCast(C, DestTy); 147 } 148 Value *CreateBitCast(Constant *C, Type *DestTy) const override { 149 return ConstFolder.CreateBitCast(C, DestTy); 150 } 151 Value *CreateIntToPtr(Constant *C, Type *DestTy) const override { 152 return ConstFolder.CreateIntToPtr(C, DestTy); 153 } 154 Value *CreatePtrToInt(Constant *C, Type *DestTy) const override { 155 return ConstFolder.CreatePtrToInt(C, DestTy); 156 } 157 Value *CreateZExtOrBitCast(Constant *C, Type *DestTy) const override { 158 if (C->getType() == DestTy) 159 return C; // avoid calling Fold 160 return ConstFolder.CreateZExtOrBitCast(C, DestTy); 161 } 162 Value *CreateSExtOrBitCast(Constant *C, Type *DestTy) const override { 163 if (C->getType() == DestTy) 164 return C; // avoid calling Fold 165 return ConstFolder.CreateSExtOrBitCast(C, DestTy); 166 } 167 Value *CreateTruncOrBitCast(Constant *C, Type *DestTy) const override { 168 if (C->getType() == DestTy) 169 return C; // avoid calling Fold 170 return ConstFolder.CreateTruncOrBitCast(C, DestTy); 171 } 172 173 Value *CreatePointerBitCastOrAddrSpaceCast(Constant *C, 174 Type *DestTy) const override { 175 if (C->getType() == DestTy) 176 return C; // avoid calling Fold 177 return ConstFolder.CreatePointerBitCastOrAddrSpaceCast(C, DestTy); 178 } 179 180 //===--------------------------------------------------------------------===// 181 // Compare Instructions 182 //===--------------------------------------------------------------------===// 183 184 Value *CreateFCmp(CmpInst::Predicate P, Constant *LHS, 185 Constant *RHS) const override { 186 return ConstFolder.CreateFCmp(P, LHS, RHS); 187 } 188 }; 189 190 } // end namespace llvm 191 192 #endif // LLVM_ANALYSIS_INSTSIMPLIFYFOLDER_H 193