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/Constants.h" 26 #include "llvm/IR/IRBuilderFolder.h" 27 #include "llvm/IR/InstrTypes.h" 28 #include "llvm/IR/Instruction.h" 29 30 namespace llvm { 31 32 /// InstSimplifyFolder - Use InstructionSimplify to fold operations to existing 33 /// values. Also applies target-specific constant folding when not using 34 /// InstructionSimplify. 35 class InstSimplifyFolder final : public IRBuilderFolder { 36 TargetFolder ConstFolder; 37 SimplifyQuery SQ; 38 39 virtual void anchor(); 40 41 public: 42 InstSimplifyFolder(const DataLayout &DL) : ConstFolder(DL), SQ(DL) {} 43 44 //===--------------------------------------------------------------------===// 45 // Value-based folders. 46 // 47 // Return an existing value or a constant if the operation can be simplified. 48 // Otherwise return nullptr. 49 //===--------------------------------------------------------------------===// 50 Value *FoldAdd(Value *LHS, Value *RHS, bool HasNUW = false, 51 bool HasNSW = false) const override { 52 return SimplifyAddInst(LHS, RHS, HasNUW, HasNSW, SQ); 53 } 54 55 Value *FoldOr(Value *LHS, Value *RHS) const override { 56 return SimplifyOrInst(LHS, RHS, SQ); 57 } 58 59 Value *FoldICmp(CmpInst::Predicate P, Value *LHS, Value *RHS) const override { 60 return SimplifyICmpInst(P, LHS, RHS, SQ); 61 } 62 63 Value *FoldGEP(Type *Ty, Value *Ptr, ArrayRef<Value *> IdxList, 64 bool IsInBounds = false) const override { 65 return SimplifyGEPInst(Ty, Ptr, IdxList, IsInBounds, SQ); 66 } 67 68 Value *FoldSelect(Value *C, Value *True, Value *False) const override { 69 return SimplifySelectInst(C, True, False, SQ); 70 } 71 72 //===--------------------------------------------------------------------===// 73 // Binary Operators 74 //===--------------------------------------------------------------------===// 75 76 Value *CreateFAdd(Constant *LHS, Constant *RHS) const override { 77 return ConstFolder.CreateFAdd(LHS, RHS); 78 } 79 Value *CreateSub(Constant *LHS, Constant *RHS, bool HasNUW = false, 80 bool HasNSW = false) const override { 81 return ConstFolder.CreateSub(LHS, RHS, HasNUW, HasNSW); 82 } 83 Value *CreateFSub(Constant *LHS, Constant *RHS) const override { 84 return ConstFolder.CreateFSub(LHS, RHS); 85 } 86 Value *CreateMul(Constant *LHS, Constant *RHS, bool HasNUW = false, 87 bool HasNSW = false) const override { 88 return ConstFolder.CreateMul(LHS, RHS, HasNUW, HasNSW); 89 } 90 Value *CreateFMul(Constant *LHS, Constant *RHS) const override { 91 return ConstFolder.CreateFMul(LHS, RHS); 92 } 93 Value *CreateUDiv(Constant *LHS, Constant *RHS, 94 bool isExact = false) const override { 95 return ConstFolder.CreateUDiv(LHS, RHS, isExact); 96 } 97 Value *CreateSDiv(Constant *LHS, Constant *RHS, 98 bool isExact = false) const override { 99 return ConstFolder.CreateSDiv(LHS, RHS, isExact); 100 } 101 Value *CreateFDiv(Constant *LHS, Constant *RHS) const override { 102 return ConstFolder.CreateFDiv(LHS, RHS); 103 } 104 Value *CreateURem(Constant *LHS, Constant *RHS) const override { 105 return ConstFolder.CreateURem(LHS, RHS); 106 } 107 Value *CreateSRem(Constant *LHS, Constant *RHS) const override { 108 return ConstFolder.CreateSRem(LHS, RHS); 109 } 110 Value *CreateFRem(Constant *LHS, Constant *RHS) const override { 111 return ConstFolder.CreateFRem(LHS, RHS); 112 } 113 Value *CreateShl(Constant *LHS, Constant *RHS, bool HasNUW = false, 114 bool HasNSW = false) const override { 115 return ConstFolder.CreateShl(LHS, RHS, HasNUW, HasNSW); 116 } 117 Value *CreateLShr(Constant *LHS, Constant *RHS, 118 bool isExact = false) const override { 119 return ConstFolder.CreateLShr(LHS, RHS, isExact); 120 } 121 Value *CreateAShr(Constant *LHS, Constant *RHS, 122 bool isExact = false) const override { 123 return ConstFolder.CreateAShr(LHS, RHS, isExact); 124 } 125 Value *CreateAnd(Constant *LHS, Constant *RHS) const override { 126 return ConstFolder.CreateAnd(LHS, RHS); 127 } 128 Value *CreateXor(Constant *LHS, Constant *RHS) const override { 129 return ConstFolder.CreateXor(LHS, RHS); 130 } 131 132 Value *CreateBinOp(Instruction::BinaryOps Opc, Constant *LHS, 133 Constant *RHS) const override { 134 return ConstFolder.CreateBinOp(Opc, LHS, RHS); 135 } 136 137 //===--------------------------------------------------------------------===// 138 // Unary Operators 139 //===--------------------------------------------------------------------===// 140 141 Value *CreateNeg(Constant *C, bool HasNUW = false, 142 bool HasNSW = false) const override { 143 return ConstFolder.CreateNeg(C, HasNUW, HasNSW); 144 } 145 Value *CreateFNeg(Constant *C) const override { 146 return ConstFolder.CreateFNeg(C); 147 } 148 Value *CreateNot(Constant *C) const override { 149 return ConstFolder.CreateNot(C); 150 } 151 152 Value *CreateUnOp(Instruction::UnaryOps Opc, Constant *C) const override { 153 return ConstFolder.CreateUnOp(Opc, C); 154 } 155 156 //===--------------------------------------------------------------------===// 157 // Cast/Conversion Operators 158 //===--------------------------------------------------------------------===// 159 160 Value *CreateCast(Instruction::CastOps Op, Constant *C, 161 Type *DestTy) const override { 162 if (C->getType() == DestTy) 163 return C; // avoid calling Fold 164 return ConstFolder.CreateCast(Op, C, DestTy); 165 } 166 Value *CreateIntCast(Constant *C, Type *DestTy, 167 bool isSigned) const override { 168 if (C->getType() == DestTy) 169 return C; // avoid calling Fold 170 return ConstFolder.CreateIntCast(C, DestTy, isSigned); 171 } 172 Value *CreatePointerCast(Constant *C, Type *DestTy) const override { 173 if (C->getType() == DestTy) 174 return C; // avoid calling Fold 175 return ConstFolder.CreatePointerCast(C, DestTy); 176 } 177 Value *CreateFPCast(Constant *C, Type *DestTy) const override { 178 if (C->getType() == DestTy) 179 return C; // avoid calling Fold 180 return ConstFolder.CreateFPCast(C, DestTy); 181 } 182 Value *CreateBitCast(Constant *C, Type *DestTy) const override { 183 return ConstFolder.CreateBitCast(C, DestTy); 184 } 185 Value *CreateIntToPtr(Constant *C, Type *DestTy) const override { 186 return ConstFolder.CreateIntToPtr(C, DestTy); 187 } 188 Value *CreatePtrToInt(Constant *C, Type *DestTy) const override { 189 return ConstFolder.CreatePtrToInt(C, DestTy); 190 } 191 Value *CreateZExtOrBitCast(Constant *C, Type *DestTy) const override { 192 if (C->getType() == DestTy) 193 return C; // avoid calling Fold 194 return ConstFolder.CreateZExtOrBitCast(C, DestTy); 195 } 196 Value *CreateSExtOrBitCast(Constant *C, Type *DestTy) const override { 197 if (C->getType() == DestTy) 198 return C; // avoid calling Fold 199 return ConstFolder.CreateSExtOrBitCast(C, DestTy); 200 } 201 Value *CreateTruncOrBitCast(Constant *C, Type *DestTy) const override { 202 if (C->getType() == DestTy) 203 return C; // avoid calling Fold 204 return ConstFolder.CreateTruncOrBitCast(C, DestTy); 205 } 206 207 Value *CreatePointerBitCastOrAddrSpaceCast(Constant *C, 208 Type *DestTy) const override { 209 if (C->getType() == DestTy) 210 return C; // avoid calling Fold 211 return ConstFolder.CreatePointerBitCastOrAddrSpaceCast(C, DestTy); 212 } 213 214 //===--------------------------------------------------------------------===// 215 // Compare Instructions 216 //===--------------------------------------------------------------------===// 217 218 Value *CreateFCmp(CmpInst::Predicate P, Constant *LHS, 219 Constant *RHS) const override { 220 return ConstFolder.CreateFCmp(P, LHS, RHS); 221 } 222 223 //===--------------------------------------------------------------------===// 224 // Other Instructions 225 //===--------------------------------------------------------------------===// 226 227 Value *CreateExtractElement(Constant *Vec, Constant *Idx) const override { 228 return ConstFolder.CreateExtractElement(Vec, Idx); 229 } 230 231 Value *CreateInsertElement(Constant *Vec, Constant *NewElt, 232 Constant *Idx) const override { 233 return ConstFolder.CreateInsertElement(Vec, NewElt, Idx); 234 } 235 236 Value *CreateShuffleVector(Constant *V1, Constant *V2, 237 ArrayRef<int> Mask) const override { 238 return ConstFolder.CreateShuffleVector(V1, V2, Mask); 239 } 240 241 Value *CreateExtractValue(Constant *Agg, 242 ArrayRef<unsigned> IdxList) const override { 243 return ConstFolder.CreateExtractValue(Agg, IdxList); 244 } 245 246 Value *CreateInsertValue(Constant *Agg, Constant *Val, 247 ArrayRef<unsigned> IdxList) const override { 248 return ConstFolder.CreateInsertValue(Agg, Val, IdxList); 249 } 250 }; 251 252 } // end namespace llvm 253 254 #endif // LLVM_ANALYSIS_INSTSIMPLIFYFOLDER_H 255