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 //===--------------------------------------------------------------------===// 76 // Binary Operators 77 //===--------------------------------------------------------------------===// 78 79 Value *CreateFAdd(Constant *LHS, Constant *RHS) const override { 80 return ConstFolder.CreateFAdd(LHS, RHS); 81 } 82 Value *CreateSub(Constant *LHS, Constant *RHS, bool HasNUW = false, 83 bool HasNSW = false) const override { 84 return ConstFolder.CreateSub(LHS, RHS, HasNUW, HasNSW); 85 } 86 Value *CreateFSub(Constant *LHS, Constant *RHS) const override { 87 return ConstFolder.CreateFSub(LHS, RHS); 88 } 89 Value *CreateMul(Constant *LHS, Constant *RHS, bool HasNUW = false, 90 bool HasNSW = false) const override { 91 return ConstFolder.CreateMul(LHS, RHS, HasNUW, HasNSW); 92 } 93 Value *CreateFMul(Constant *LHS, Constant *RHS) const override { 94 return ConstFolder.CreateFMul(LHS, RHS); 95 } 96 Value *CreateUDiv(Constant *LHS, Constant *RHS, 97 bool isExact = false) const override { 98 return ConstFolder.CreateUDiv(LHS, RHS, isExact); 99 } 100 Value *CreateSDiv(Constant *LHS, Constant *RHS, 101 bool isExact = false) const override { 102 return ConstFolder.CreateSDiv(LHS, RHS, isExact); 103 } 104 Value *CreateFDiv(Constant *LHS, Constant *RHS) const override { 105 return ConstFolder.CreateFDiv(LHS, RHS); 106 } 107 Value *CreateURem(Constant *LHS, Constant *RHS) const override { 108 return ConstFolder.CreateURem(LHS, RHS); 109 } 110 Value *CreateSRem(Constant *LHS, Constant *RHS) const override { 111 return ConstFolder.CreateSRem(LHS, RHS); 112 } 113 Value *CreateFRem(Constant *LHS, Constant *RHS) const override { 114 return ConstFolder.CreateFRem(LHS, RHS); 115 } 116 Value *CreateShl(Constant *LHS, Constant *RHS, bool HasNUW = false, 117 bool HasNSW = false) const override { 118 return ConstFolder.CreateShl(LHS, RHS, HasNUW, HasNSW); 119 } 120 Value *CreateLShr(Constant *LHS, Constant *RHS, 121 bool isExact = false) const override { 122 return ConstFolder.CreateLShr(LHS, RHS, isExact); 123 } 124 Value *CreateAShr(Constant *LHS, Constant *RHS, 125 bool isExact = false) const override { 126 return ConstFolder.CreateAShr(LHS, RHS, isExact); 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