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