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