1 //===- NoFolder.h - Constant 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 NoFolder class, a helper for IRBuilder.  It provides
10 // IRBuilder with a set of methods for creating unfolded constants.  This is
11 // useful for learners trying to understand how LLVM IR works, and who don't
12 // want details to be hidden by the constant folder.  For general constant
13 // creation and folding, use ConstantExpr and the routines in
14 // llvm/Analysis/ConstantFolding.h.
15 //
16 // Note: since it is not actually possible to create unfolded constants, this
17 // class returns instructions rather than constants.
18 //
19 //===----------------------------------------------------------------------===//
20 
21 #ifndef LLVM_IR_NOFOLDER_H
22 #define LLVM_IR_NOFOLDER_H
23 
24 #include "llvm/ADT/ArrayRef.h"
25 #include "llvm/IR/Constants.h"
26 #include "llvm/IR/InstrTypes.h"
27 #include "llvm/IR/Instruction.h"
28 #include "llvm/IR/Instructions.h"
29 #include "llvm/IR/IRBuilderFolder.h"
30 
31 namespace llvm {
32 
33 /// NoFolder - Create "constants" (actually, instructions) with no folding.
34 class NoFolder final : public IRBuilderFolder {
35   virtual void anchor();
36 
37 public:
38   explicit NoFolder() = default;
39 
40   //===--------------------------------------------------------------------===//
41   // Value-based folders.
42   //
43   // Return an existing value or a constant if the operation can be simplified.
44   // Otherwise return nullptr.
45   //===--------------------------------------------------------------------===//
46   Value *FoldAdd(Value *LHS, Value *RHS, bool HasNUW = false,
47                  bool HasNSW = false) const override {
48     return nullptr;
49   }
50 
51   Value *FoldAnd(Value *LHS, Value *RHS) const override { return nullptr; }
52 
53   Value *FoldOr(Value *LHS, Value *RHS) const override { return nullptr; }
54 
55   Value *FoldICmp(CmpInst::Predicate P, Value *LHS, Value *RHS) const override {
56     return nullptr;
57   }
58 
59   Value *FoldGEP(Type *Ty, Value *Ptr, ArrayRef<Value *> IdxList,
60                  bool IsInBounds = false) const override {
61     return nullptr;
62   }
63 
64   Value *FoldSelect(Value *C, Value *True, Value *False) const override {
65     return nullptr;
66   }
67 
68   //===--------------------------------------------------------------------===//
69   // Binary Operators
70   //===--------------------------------------------------------------------===//
71 
72   Instruction *CreateFAdd(Constant *LHS, Constant *RHS) const override {
73     return BinaryOperator::CreateFAdd(LHS, RHS);
74   }
75 
76   Instruction *CreateSub(Constant *LHS, Constant *RHS,
77                          bool HasNUW = false,
78                          bool HasNSW = false) const override {
79     BinaryOperator *BO = BinaryOperator::CreateSub(LHS, RHS);
80     if (HasNUW) BO->setHasNoUnsignedWrap();
81     if (HasNSW) BO->setHasNoSignedWrap();
82     return BO;
83   }
84 
85   Instruction *CreateFSub(Constant *LHS, Constant *RHS) const override {
86     return BinaryOperator::CreateFSub(LHS, RHS);
87   }
88 
89   Instruction *CreateMul(Constant *LHS, Constant *RHS,
90                          bool HasNUW = false,
91                          bool HasNSW = false) const override {
92     BinaryOperator *BO = BinaryOperator::CreateMul(LHS, RHS);
93     if (HasNUW) BO->setHasNoUnsignedWrap();
94     if (HasNSW) BO->setHasNoSignedWrap();
95     return BO;
96   }
97 
98   Instruction *CreateFMul(Constant *LHS, Constant *RHS) const override {
99     return BinaryOperator::CreateFMul(LHS, RHS);
100   }
101 
102   Instruction *CreateUDiv(Constant *LHS, Constant *RHS,
103                           bool isExact = false) const override {
104     if (!isExact)
105       return BinaryOperator::CreateUDiv(LHS, RHS);
106     return BinaryOperator::CreateExactUDiv(LHS, RHS);
107   }
108 
109   Instruction *CreateSDiv(Constant *LHS, Constant *RHS,
110                           bool isExact = false) const override {
111     if (!isExact)
112       return BinaryOperator::CreateSDiv(LHS, RHS);
113     return BinaryOperator::CreateExactSDiv(LHS, RHS);
114   }
115 
116   Instruction *CreateFDiv(Constant *LHS, Constant *RHS) const override {
117     return BinaryOperator::CreateFDiv(LHS, RHS);
118   }
119 
120   Instruction *CreateURem(Constant *LHS, Constant *RHS) const override {
121     return BinaryOperator::CreateURem(LHS, RHS);
122   }
123 
124   Instruction *CreateSRem(Constant *LHS, Constant *RHS) const override {
125     return BinaryOperator::CreateSRem(LHS, RHS);
126   }
127 
128   Instruction *CreateFRem(Constant *LHS, Constant *RHS) const override {
129     return BinaryOperator::CreateFRem(LHS, RHS);
130   }
131 
132   Instruction *CreateShl(Constant *LHS, Constant *RHS, bool HasNUW = false,
133                          bool HasNSW = false) const override {
134     BinaryOperator *BO = BinaryOperator::CreateShl(LHS, RHS);
135     if (HasNUW) BO->setHasNoUnsignedWrap();
136     if (HasNSW) BO->setHasNoSignedWrap();
137     return BO;
138   }
139 
140   Instruction *CreateLShr(Constant *LHS, Constant *RHS,
141                           bool isExact = false) const override {
142     if (!isExact)
143       return BinaryOperator::CreateLShr(LHS, RHS);
144     return BinaryOperator::CreateExactLShr(LHS, RHS);
145   }
146 
147   Instruction *CreateAShr(Constant *LHS, Constant *RHS,
148                           bool isExact = false) const override {
149     if (!isExact)
150       return BinaryOperator::CreateAShr(LHS, RHS);
151     return BinaryOperator::CreateExactAShr(LHS, RHS);
152   }
153 
154   Instruction *CreateXor(Constant *LHS, Constant *RHS) const override {
155     return BinaryOperator::CreateXor(LHS, RHS);
156   }
157 
158   Instruction *CreateBinOp(Instruction::BinaryOps Opc,
159                            Constant *LHS, Constant *RHS) const override {
160     return BinaryOperator::Create(Opc, LHS, RHS);
161   }
162 
163   //===--------------------------------------------------------------------===//
164   // Unary Operators
165   //===--------------------------------------------------------------------===//
166 
167   Instruction *CreateNeg(Constant *C,
168                          bool HasNUW = false,
169                          bool HasNSW = false) const override {
170     BinaryOperator *BO = BinaryOperator::CreateNeg(C);
171     if (HasNUW) BO->setHasNoUnsignedWrap();
172     if (HasNSW) BO->setHasNoSignedWrap();
173     return BO;
174   }
175 
176   Instruction *CreateFNeg(Constant *C) const override {
177     return UnaryOperator::CreateFNeg(C);
178   }
179 
180   Instruction *CreateNot(Constant *C) const override {
181     return BinaryOperator::CreateNot(C);
182   }
183 
184   Instruction *CreateUnOp(Instruction::UnaryOps Opc,
185                           Constant *C) const override {
186     return UnaryOperator::Create(Opc, C);
187   }
188 
189   //===--------------------------------------------------------------------===//
190   // Cast/Conversion Operators
191   //===--------------------------------------------------------------------===//
192 
193   Instruction *CreateCast(Instruction::CastOps Op, Constant *C,
194                           Type *DestTy) const override {
195     return CastInst::Create(Op, C, DestTy);
196   }
197 
198   Instruction *CreatePointerCast(Constant *C, Type *DestTy) const override {
199     return CastInst::CreatePointerCast(C, DestTy);
200   }
201 
202   Instruction *CreatePointerBitCastOrAddrSpaceCast(
203       Constant *C, Type *DestTy) const override {
204     return CastInst::CreatePointerBitCastOrAddrSpaceCast(C, DestTy);
205   }
206 
207   Instruction *CreateIntCast(Constant *C, Type *DestTy,
208                              bool isSigned) const override {
209     return CastInst::CreateIntegerCast(C, DestTy, isSigned);
210   }
211 
212   Instruction *CreateFPCast(Constant *C, Type *DestTy) const override {
213     return CastInst::CreateFPCast(C, DestTy);
214   }
215 
216   Instruction *CreateBitCast(Constant *C, Type *DestTy) const override {
217     return CreateCast(Instruction::BitCast, C, DestTy);
218   }
219 
220   Instruction *CreateIntToPtr(Constant *C, Type *DestTy) const override {
221     return CreateCast(Instruction::IntToPtr, C, DestTy);
222   }
223 
224   Instruction *CreatePtrToInt(Constant *C, Type *DestTy) const override {
225     return CreateCast(Instruction::PtrToInt, C, DestTy);
226   }
227 
228   Instruction *CreateZExtOrBitCast(Constant *C, Type *DestTy) const override {
229     return CastInst::CreateZExtOrBitCast(C, DestTy);
230   }
231 
232   Instruction *CreateSExtOrBitCast(Constant *C, Type *DestTy) const override {
233     return CastInst::CreateSExtOrBitCast(C, DestTy);
234   }
235 
236   Instruction *CreateTruncOrBitCast(Constant *C, Type *DestTy) const override {
237     return CastInst::CreateTruncOrBitCast(C, DestTy);
238   }
239 
240   //===--------------------------------------------------------------------===//
241   // Compare Instructions
242   //===--------------------------------------------------------------------===//
243 
244   Instruction *CreateFCmp(CmpInst::Predicate P,
245                           Constant *LHS, Constant *RHS) const override {
246     return new FCmpInst(P, LHS, RHS);
247   }
248 
249   //===--------------------------------------------------------------------===//
250   // Other Instructions
251   //===--------------------------------------------------------------------===//
252 
253   Instruction *CreateExtractElement(Constant *Vec,
254                                     Constant *Idx) const override {
255     return ExtractElementInst::Create(Vec, Idx);
256   }
257 
258   Instruction *CreateInsertElement(Constant *Vec, Constant *NewElt,
259                                    Constant *Idx) const override {
260     return InsertElementInst::Create(Vec, NewElt, Idx);
261   }
262 
263   Instruction *CreateShuffleVector(Constant *V1, Constant *V2,
264                                    ArrayRef<int> Mask) const override {
265     return new ShuffleVectorInst(V1, V2, Mask);
266   }
267 
268   Instruction *CreateExtractValue(Constant *Agg,
269                                   ArrayRef<unsigned> IdxList) const override {
270     return ExtractValueInst::Create(Agg, IdxList);
271   }
272 
273   Instruction *CreateInsertValue(Constant *Agg, Constant *Val,
274                                  ArrayRef<unsigned> IdxList) const override {
275     return InsertValueInst::Create(Agg, Val, IdxList);
276   }
277 };
278 
279 } // end namespace llvm
280 
281 #endif // LLVM_IR_NOFOLDER_H
282