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