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 Value *FoldAdd(Value *LHS, Value *RHS, bool HasNUW = false, 50 bool HasNSW = false) const override { 51 return simplifyAddInst(LHS, RHS, HasNUW, HasNSW, SQ); 52 } 53 54 Value *FoldAnd(Value *LHS, Value *RHS) const override { 55 return simplifyAndInst(LHS, RHS, SQ); 56 } 57 58 Value *FoldOr(Value *LHS, Value *RHS) const override { 59 return simplifyOrInst(LHS, RHS, SQ); 60 } 61 62 Value *FoldICmp(CmpInst::Predicate P, Value *LHS, Value *RHS) const override { 63 return simplifyICmpInst(P, LHS, RHS, SQ); 64 } 65 66 Value *FoldGEP(Type *Ty, Value *Ptr, ArrayRef<Value *> IdxList, 67 bool IsInBounds = false) const override { 68 return simplifyGEPInst(Ty, Ptr, IdxList, IsInBounds, SQ); 69 } 70 71 Value *FoldSelect(Value *C, Value *True, Value *False) const override { 72 return simplifySelectInst(C, True, False, SQ); 73 } 74 75 Value *FoldExtractValue(Value *Agg, 76 ArrayRef<unsigned> IdxList) const override { 77 return simplifyExtractValueInst(Agg, IdxList, SQ); 78 }; 79 80 Value *FoldInsertValue(Value *Agg, Value *Val, 81 ArrayRef<unsigned> IdxList) const override { 82 return simplifyInsertValueInst(Agg, Val, IdxList, SQ); 83 } 84 85 //===--------------------------------------------------------------------===// 86 // Binary Operators 87 //===--------------------------------------------------------------------===// 88 89 Value *CreateFAdd(Constant *LHS, Constant *RHS) const override { 90 return ConstFolder.CreateFAdd(LHS, RHS); 91 } 92 Value *CreateSub(Constant *LHS, Constant *RHS, bool HasNUW = false, 93 bool HasNSW = false) const override { 94 return ConstFolder.CreateSub(LHS, RHS, HasNUW, HasNSW); 95 } 96 Value *CreateFSub(Constant *LHS, Constant *RHS) const override { 97 return ConstFolder.CreateFSub(LHS, RHS); 98 } 99 Value *CreateMul(Constant *LHS, Constant *RHS, bool HasNUW = false, 100 bool HasNSW = false) const override { 101 return ConstFolder.CreateMul(LHS, RHS, HasNUW, HasNSW); 102 } 103 Value *CreateFMul(Constant *LHS, Constant *RHS) const override { 104 return ConstFolder.CreateFMul(LHS, RHS); 105 } 106 Value *CreateUDiv(Constant *LHS, Constant *RHS, 107 bool isExact = false) const override { 108 return ConstFolder.CreateUDiv(LHS, RHS, isExact); 109 } 110 Value *CreateSDiv(Constant *LHS, Constant *RHS, 111 bool isExact = false) const override { 112 return ConstFolder.CreateSDiv(LHS, RHS, isExact); 113 } 114 Value *CreateFDiv(Constant *LHS, Constant *RHS) const override { 115 return ConstFolder.CreateFDiv(LHS, RHS); 116 } 117 Value *CreateURem(Constant *LHS, Constant *RHS) const override { 118 return ConstFolder.CreateURem(LHS, RHS); 119 } 120 Value *CreateSRem(Constant *LHS, Constant *RHS) const override { 121 return ConstFolder.CreateSRem(LHS, RHS); 122 } 123 Value *CreateFRem(Constant *LHS, Constant *RHS) const override { 124 return ConstFolder.CreateFRem(LHS, RHS); 125 } 126 Value *CreateShl(Constant *LHS, Constant *RHS, bool HasNUW = false, 127 bool HasNSW = false) const override { 128 return ConstFolder.CreateShl(LHS, RHS, HasNUW, HasNSW); 129 } 130 Value *CreateLShr(Constant *LHS, Constant *RHS, 131 bool isExact = false) const override { 132 return ConstFolder.CreateLShr(LHS, RHS, isExact); 133 } 134 Value *CreateAShr(Constant *LHS, Constant *RHS, 135 bool isExact = false) const override { 136 return ConstFolder.CreateAShr(LHS, RHS, isExact); 137 } 138 Value *CreateXor(Constant *LHS, Constant *RHS) const override { 139 return ConstFolder.CreateXor(LHS, RHS); 140 } 141 142 Value *CreateBinOp(Instruction::BinaryOps Opc, Constant *LHS, 143 Constant *RHS) const override { 144 return ConstFolder.CreateBinOp(Opc, LHS, RHS); 145 } 146 147 //===--------------------------------------------------------------------===// 148 // Unary Operators 149 //===--------------------------------------------------------------------===// 150 151 Value *CreateNeg(Constant *C, bool HasNUW = false, 152 bool HasNSW = false) const override { 153 return ConstFolder.CreateNeg(C, HasNUW, HasNSW); 154 } 155 Value *CreateFNeg(Constant *C) const override { 156 return ConstFolder.CreateFNeg(C); 157 } 158 Value *CreateNot(Constant *C) const override { 159 return ConstFolder.CreateNot(C); 160 } 161 162 Value *CreateUnOp(Instruction::UnaryOps Opc, Constant *C) const override { 163 return ConstFolder.CreateUnOp(Opc, C); 164 } 165 166 //===--------------------------------------------------------------------===// 167 // Cast/Conversion Operators 168 //===--------------------------------------------------------------------===// 169 170 Value *CreateCast(Instruction::CastOps Op, Constant *C, 171 Type *DestTy) const override { 172 if (C->getType() == DestTy) 173 return C; // avoid calling Fold 174 return ConstFolder.CreateCast(Op, C, DestTy); 175 } 176 Value *CreateIntCast(Constant *C, Type *DestTy, 177 bool isSigned) const override { 178 if (C->getType() == DestTy) 179 return C; // avoid calling Fold 180 return ConstFolder.CreateIntCast(C, DestTy, isSigned); 181 } 182 Value *CreatePointerCast(Constant *C, Type *DestTy) const override { 183 if (C->getType() == DestTy) 184 return C; // avoid calling Fold 185 return ConstFolder.CreatePointerCast(C, DestTy); 186 } 187 Value *CreateFPCast(Constant *C, Type *DestTy) const override { 188 if (C->getType() == DestTy) 189 return C; // avoid calling Fold 190 return ConstFolder.CreateFPCast(C, DestTy); 191 } 192 Value *CreateBitCast(Constant *C, Type *DestTy) const override { 193 return ConstFolder.CreateBitCast(C, DestTy); 194 } 195 Value *CreateIntToPtr(Constant *C, Type *DestTy) const override { 196 return ConstFolder.CreateIntToPtr(C, DestTy); 197 } 198 Value *CreatePtrToInt(Constant *C, Type *DestTy) const override { 199 return ConstFolder.CreatePtrToInt(C, DestTy); 200 } 201 Value *CreateZExtOrBitCast(Constant *C, Type *DestTy) const override { 202 if (C->getType() == DestTy) 203 return C; // avoid calling Fold 204 return ConstFolder.CreateZExtOrBitCast(C, DestTy); 205 } 206 Value *CreateSExtOrBitCast(Constant *C, Type *DestTy) const override { 207 if (C->getType() == DestTy) 208 return C; // avoid calling Fold 209 return ConstFolder.CreateSExtOrBitCast(C, DestTy); 210 } 211 Value *CreateTruncOrBitCast(Constant *C, Type *DestTy) const override { 212 if (C->getType() == DestTy) 213 return C; // avoid calling Fold 214 return ConstFolder.CreateTruncOrBitCast(C, DestTy); 215 } 216 217 Value *CreatePointerBitCastOrAddrSpaceCast(Constant *C, 218 Type *DestTy) const override { 219 if (C->getType() == DestTy) 220 return C; // avoid calling Fold 221 return ConstFolder.CreatePointerBitCastOrAddrSpaceCast(C, DestTy); 222 } 223 224 //===--------------------------------------------------------------------===// 225 // Compare Instructions 226 //===--------------------------------------------------------------------===// 227 228 Value *CreateFCmp(CmpInst::Predicate P, Constant *LHS, 229 Constant *RHS) const override { 230 return ConstFolder.CreateFCmp(P, LHS, RHS); 231 } 232 233 //===--------------------------------------------------------------------===// 234 // Other Instructions 235 //===--------------------------------------------------------------------===// 236 237 Value *CreateExtractElement(Constant *Vec, Constant *Idx) const override { 238 return ConstFolder.CreateExtractElement(Vec, Idx); 239 } 240 241 Value *CreateInsertElement(Constant *Vec, Constant *NewElt, 242 Constant *Idx) const override { 243 return ConstFolder.CreateInsertElement(Vec, NewElt, Idx); 244 } 245 246 Value *CreateShuffleVector(Constant *V1, Constant *V2, 247 ArrayRef<int> Mask) const override { 248 return ConstFolder.CreateShuffleVector(V1, V2, Mask); 249 } 250 }; 251 252 } // end namespace llvm 253 254 #endif // LLVM_ANALYSIS_INSTSIMPLIFYFOLDER_H 255