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