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   // Binary Operators
42   //===--------------------------------------------------------------------===//
43 
44   Instruction *CreateAdd(Constant *LHS, Constant *RHS,
45                          bool HasNUW = false,
46                          bool HasNSW = false) const override {
47     BinaryOperator *BO = BinaryOperator::CreateAdd(LHS, RHS);
48     if (HasNUW) BO->setHasNoUnsignedWrap();
49     if (HasNSW) BO->setHasNoSignedWrap();
50     return BO;
51   }
52 
CreateFAdd(Constant * LHS,Constant * RHS)53   Instruction *CreateFAdd(Constant *LHS, Constant *RHS) const override {
54     return BinaryOperator::CreateFAdd(LHS, RHS);
55   }
56 
57   Instruction *CreateSub(Constant *LHS, Constant *RHS,
58                          bool HasNUW = false,
59                          bool HasNSW = false) const override {
60     BinaryOperator *BO = BinaryOperator::CreateSub(LHS, RHS);
61     if (HasNUW) BO->setHasNoUnsignedWrap();
62     if (HasNSW) BO->setHasNoSignedWrap();
63     return BO;
64   }
65 
CreateFSub(Constant * LHS,Constant * RHS)66   Instruction *CreateFSub(Constant *LHS, Constant *RHS) const override {
67     return BinaryOperator::CreateFSub(LHS, RHS);
68   }
69 
70   Instruction *CreateMul(Constant *LHS, Constant *RHS,
71                          bool HasNUW = false,
72                          bool HasNSW = false) const override {
73     BinaryOperator *BO = BinaryOperator::CreateMul(LHS, RHS);
74     if (HasNUW) BO->setHasNoUnsignedWrap();
75     if (HasNSW) BO->setHasNoSignedWrap();
76     return BO;
77   }
78 
CreateFMul(Constant * LHS,Constant * RHS)79   Instruction *CreateFMul(Constant *LHS, Constant *RHS) const override {
80     return BinaryOperator::CreateFMul(LHS, RHS);
81   }
82 
83   Instruction *CreateUDiv(Constant *LHS, Constant *RHS,
84                           bool isExact = false) const override {
85     if (!isExact)
86       return BinaryOperator::CreateUDiv(LHS, RHS);
87     return BinaryOperator::CreateExactUDiv(LHS, RHS);
88   }
89 
90   Instruction *CreateSDiv(Constant *LHS, Constant *RHS,
91                           bool isExact = false) const override {
92     if (!isExact)
93       return BinaryOperator::CreateSDiv(LHS, RHS);
94     return BinaryOperator::CreateExactSDiv(LHS, RHS);
95   }
96 
CreateFDiv(Constant * LHS,Constant * RHS)97   Instruction *CreateFDiv(Constant *LHS, Constant *RHS) const override {
98     return BinaryOperator::CreateFDiv(LHS, RHS);
99   }
100 
CreateURem(Constant * LHS,Constant * RHS)101   Instruction *CreateURem(Constant *LHS, Constant *RHS) const override {
102     return BinaryOperator::CreateURem(LHS, RHS);
103   }
104 
CreateSRem(Constant * LHS,Constant * RHS)105   Instruction *CreateSRem(Constant *LHS, Constant *RHS) const override {
106     return BinaryOperator::CreateSRem(LHS, RHS);
107   }
108 
CreateFRem(Constant * LHS,Constant * RHS)109   Instruction *CreateFRem(Constant *LHS, Constant *RHS) const override {
110     return BinaryOperator::CreateFRem(LHS, RHS);
111   }
112 
113   Instruction *CreateShl(Constant *LHS, Constant *RHS, bool HasNUW = false,
114                          bool HasNSW = false) const override {
115     BinaryOperator *BO = BinaryOperator::CreateShl(LHS, RHS);
116     if (HasNUW) BO->setHasNoUnsignedWrap();
117     if (HasNSW) BO->setHasNoSignedWrap();
118     return BO;
119   }
120 
121   Instruction *CreateLShr(Constant *LHS, Constant *RHS,
122                           bool isExact = false) const override {
123     if (!isExact)
124       return BinaryOperator::CreateLShr(LHS, RHS);
125     return BinaryOperator::CreateExactLShr(LHS, RHS);
126   }
127 
128   Instruction *CreateAShr(Constant *LHS, Constant *RHS,
129                           bool isExact = false) const override {
130     if (!isExact)
131       return BinaryOperator::CreateAShr(LHS, RHS);
132     return BinaryOperator::CreateExactAShr(LHS, RHS);
133   }
134 
CreateAnd(Constant * LHS,Constant * RHS)135   Instruction *CreateAnd(Constant *LHS, Constant *RHS) const override {
136     return BinaryOperator::CreateAnd(LHS, RHS);
137   }
138 
CreateOr(Constant * LHS,Constant * RHS)139   Instruction *CreateOr(Constant *LHS, Constant *RHS) const override {
140     return BinaryOperator::CreateOr(LHS, RHS);
141   }
142 
CreateXor(Constant * LHS,Constant * RHS)143   Instruction *CreateXor(Constant *LHS, Constant *RHS) const override {
144     return BinaryOperator::CreateXor(LHS, RHS);
145   }
146 
CreateBinOp(Instruction::BinaryOps Opc,Constant * LHS,Constant * RHS)147   Instruction *CreateBinOp(Instruction::BinaryOps Opc,
148                            Constant *LHS, Constant *RHS) const override {
149     return BinaryOperator::Create(Opc, LHS, RHS);
150   }
151 
152   //===--------------------------------------------------------------------===//
153   // Unary Operators
154   //===--------------------------------------------------------------------===//
155 
156   Instruction *CreateNeg(Constant *C,
157                          bool HasNUW = false,
158                          bool HasNSW = false) const override {
159     BinaryOperator *BO = BinaryOperator::CreateNeg(C);
160     if (HasNUW) BO->setHasNoUnsignedWrap();
161     if (HasNSW) BO->setHasNoSignedWrap();
162     return BO;
163   }
164 
CreateFNeg(Constant * C)165   Instruction *CreateFNeg(Constant *C) const override {
166     return UnaryOperator::CreateFNeg(C);
167   }
168 
CreateNot(Constant * C)169   Instruction *CreateNot(Constant *C) const override {
170     return BinaryOperator::CreateNot(C);
171   }
172 
CreateUnOp(Instruction::UnaryOps Opc,Constant * C)173   Instruction *CreateUnOp(Instruction::UnaryOps Opc,
174                           Constant *C) const override {
175     return UnaryOperator::Create(Opc, C);
176   }
177 
178   //===--------------------------------------------------------------------===//
179   // Memory Instructions
180   //===--------------------------------------------------------------------===//
181 
CreateGetElementPtr(Type * Ty,Constant * C,ArrayRef<Constant * > IdxList)182   Constant *CreateGetElementPtr(Type *Ty, Constant *C,
183                                 ArrayRef<Constant *> IdxList) const override {
184     return ConstantExpr::getGetElementPtr(Ty, C, IdxList);
185   }
186 
CreateGetElementPtr(Type * Ty,Constant * C,Constant * Idx)187   Constant *CreateGetElementPtr(Type *Ty, Constant *C,
188                                 Constant *Idx) const override {
189     // This form of the function only exists to avoid ambiguous overload
190     // warnings about whether to convert Idx to ArrayRef<Constant *> or
191     // ArrayRef<Value *>.
192     return ConstantExpr::getGetElementPtr(Ty, C, Idx);
193   }
194 
CreateGetElementPtr(Type * Ty,Constant * C,ArrayRef<Value * > IdxList)195   Instruction *CreateGetElementPtr(Type *Ty, Constant *C,
196                                    ArrayRef<Value *> IdxList) const override {
197     return GetElementPtrInst::Create(Ty, C, IdxList);
198   }
199 
CreateInBoundsGetElementPtr(Type * Ty,Constant * C,ArrayRef<Constant * > IdxList)200   Constant *CreateInBoundsGetElementPtr(
201       Type *Ty, Constant *C, ArrayRef<Constant *> IdxList) const override {
202     return ConstantExpr::getInBoundsGetElementPtr(Ty, C, IdxList);
203   }
204 
CreateInBoundsGetElementPtr(Type * Ty,Constant * C,Constant * Idx)205   Constant *CreateInBoundsGetElementPtr(Type *Ty, Constant *C,
206                                         Constant *Idx) const override {
207     // This form of the function only exists to avoid ambiguous overload
208     // warnings about whether to convert Idx to ArrayRef<Constant *> or
209     // ArrayRef<Value *>.
210     return ConstantExpr::getInBoundsGetElementPtr(Ty, C, Idx);
211   }
212 
CreateInBoundsGetElementPtr(Type * Ty,Constant * C,ArrayRef<Value * > IdxList)213   Instruction *CreateInBoundsGetElementPtr(
214       Type *Ty, Constant *C, ArrayRef<Value *> IdxList) const override {
215     return GetElementPtrInst::CreateInBounds(Ty, C, IdxList);
216   }
217 
218   //===--------------------------------------------------------------------===//
219   // Cast/Conversion Operators
220   //===--------------------------------------------------------------------===//
221 
CreateCast(Instruction::CastOps Op,Constant * C,Type * DestTy)222   Instruction *CreateCast(Instruction::CastOps Op, Constant *C,
223                           Type *DestTy) const override {
224     return CastInst::Create(Op, C, DestTy);
225   }
226 
CreatePointerCast(Constant * C,Type * DestTy)227   Instruction *CreatePointerCast(Constant *C, Type *DestTy) const override {
228     return CastInst::CreatePointerCast(C, DestTy);
229   }
230 
CreatePointerBitCastOrAddrSpaceCast(Constant * C,Type * DestTy)231   Instruction *CreatePointerBitCastOrAddrSpaceCast(
232       Constant *C, Type *DestTy) const override {
233     return CastInst::CreatePointerBitCastOrAddrSpaceCast(C, DestTy);
234   }
235 
CreateIntCast(Constant * C,Type * DestTy,bool isSigned)236   Instruction *CreateIntCast(Constant *C, Type *DestTy,
237                              bool isSigned) const override {
238     return CastInst::CreateIntegerCast(C, DestTy, isSigned);
239   }
240 
CreateFPCast(Constant * C,Type * DestTy)241   Instruction *CreateFPCast(Constant *C, Type *DestTy) const override {
242     return CastInst::CreateFPCast(C, DestTy);
243   }
244 
CreateBitCast(Constant * C,Type * DestTy)245   Instruction *CreateBitCast(Constant *C, Type *DestTy) const override {
246     return CreateCast(Instruction::BitCast, C, DestTy);
247   }
248 
CreateIntToPtr(Constant * C,Type * DestTy)249   Instruction *CreateIntToPtr(Constant *C, Type *DestTy) const override {
250     return CreateCast(Instruction::IntToPtr, C, DestTy);
251   }
252 
CreatePtrToInt(Constant * C,Type * DestTy)253   Instruction *CreatePtrToInt(Constant *C, Type *DestTy) const override {
254     return CreateCast(Instruction::PtrToInt, C, DestTy);
255   }
256 
CreateZExtOrBitCast(Constant * C,Type * DestTy)257   Instruction *CreateZExtOrBitCast(Constant *C, Type *DestTy) const override {
258     return CastInst::CreateZExtOrBitCast(C, DestTy);
259   }
260 
CreateSExtOrBitCast(Constant * C,Type * DestTy)261   Instruction *CreateSExtOrBitCast(Constant *C, Type *DestTy) const override {
262     return CastInst::CreateSExtOrBitCast(C, DestTy);
263   }
264 
CreateTruncOrBitCast(Constant * C,Type * DestTy)265   Instruction *CreateTruncOrBitCast(Constant *C, Type *DestTy) const override {
266     return CastInst::CreateTruncOrBitCast(C, DestTy);
267   }
268 
269   //===--------------------------------------------------------------------===//
270   // Compare Instructions
271   //===--------------------------------------------------------------------===//
272 
CreateICmp(CmpInst::Predicate P,Constant * LHS,Constant * RHS)273   Instruction *CreateICmp(CmpInst::Predicate P,
274                           Constant *LHS, Constant *RHS) const override {
275     return new ICmpInst(P, LHS, RHS);
276   }
277 
CreateFCmp(CmpInst::Predicate P,Constant * LHS,Constant * RHS)278   Instruction *CreateFCmp(CmpInst::Predicate P,
279                           Constant *LHS, Constant *RHS) const override {
280     return new FCmpInst(P, LHS, RHS);
281   }
282 
283   //===--------------------------------------------------------------------===//
284   // Other Instructions
285   //===--------------------------------------------------------------------===//
286 
CreateSelect(Constant * C,Constant * True,Constant * False)287   Instruction *CreateSelect(Constant *C,
288                             Constant *True, Constant *False) const override {
289     return SelectInst::Create(C, True, False);
290   }
291 
CreateExtractElement(Constant * Vec,Constant * Idx)292   Instruction *CreateExtractElement(Constant *Vec,
293                                     Constant *Idx) const override {
294     return ExtractElementInst::Create(Vec, Idx);
295   }
296 
CreateInsertElement(Constant * Vec,Constant * NewElt,Constant * Idx)297   Instruction *CreateInsertElement(Constant *Vec, Constant *NewElt,
298                                    Constant *Idx) const override {
299     return InsertElementInst::Create(Vec, NewElt, Idx);
300   }
301 
CreateShuffleVector(Constant * V1,Constant * V2,ArrayRef<int> Mask)302   Instruction *CreateShuffleVector(Constant *V1, Constant *V2,
303                                    ArrayRef<int> Mask) const override {
304     return new ShuffleVectorInst(V1, V2, Mask);
305   }
306 
CreateExtractValue(Constant * Agg,ArrayRef<unsigned> IdxList)307   Instruction *CreateExtractValue(Constant *Agg,
308                                   ArrayRef<unsigned> IdxList) const override {
309     return ExtractValueInst::Create(Agg, IdxList);
310   }
311 
CreateInsertValue(Constant * Agg,Constant * Val,ArrayRef<unsigned> IdxList)312   Instruction *CreateInsertValue(Constant *Agg, Constant *Val,
313                                  ArrayRef<unsigned> IdxList) const override {
314     return InsertValueInst::Create(Agg, Val, IdxList);
315   }
316 };
317 
318 } // end namespace llvm
319 
320 #endif // LLVM_IR_NOFOLDER_H
321