1 //====- TargetFolder.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 TargetFolder class, a helper for IRBuilder.
10 // It provides IRBuilder with a set of methods for creating constants with
11 // target dependent folding, in addition to the same target-independent
12 // folding that the ConstantFolder class provides.  For general constant
13 // creation and folding, use ConstantExpr and the routines in
14 // llvm/Analysis/ConstantFolding.h.
15 //
16 //===----------------------------------------------------------------------===//
17 
18 #ifndef LLVM_ANALYSIS_TARGETFOLDER_H
19 #define LLVM_ANALYSIS_TARGETFOLDER_H
20 
21 #include "llvm/ADT/ArrayRef.h"
22 #include "llvm/Analysis/ConstantFolding.h"
23 #include "llvm/IR/Constants.h"
24 #include "llvm/IR/IRBuilderFolder.h"
25 
26 namespace llvm {
27 
28 class Constant;
29 class DataLayout;
30 class Type;
31 
32 /// TargetFolder - Create constants with target dependent folding.
33 class TargetFolder final : public IRBuilderFolder {
34   const DataLayout &DL;
35 
36   /// Fold - Fold the constant using target specific information.
37   Constant *Fold(Constant *C) const {
38     return ConstantFoldConstant(C, DL);
39   }
40 
41   virtual void anchor();
42 
43 public:
44   explicit TargetFolder(const DataLayout &DL) : DL(DL) {}
45 
46   //===--------------------------------------------------------------------===//
47   // Value-based folders.
48   //
49   // Return an existing value or a constant if the operation can be simplified.
50   // Otherwise return nullptr.
51   //===--------------------------------------------------------------------===//
52   Value *FoldAdd(Value *LHS, Value *RHS, bool HasNUW = false,
53                  bool HasNSW = false) const override {
54     auto *LC = dyn_cast<Constant>(LHS);
55     auto *RC = dyn_cast<Constant>(RHS);
56     if (LC && RC)
57       return Fold(ConstantExpr::getAdd(LC, RC, HasNUW, HasNSW));
58     return nullptr;
59   }
60 
61   Value *FoldAnd(Value *LHS, Value *RHS) const override {
62     auto *LC = dyn_cast<Constant>(LHS);
63     auto *RC = dyn_cast<Constant>(RHS);
64     if (LC && RC)
65       return Fold(ConstantExpr::getAnd(LC, RC));
66     return nullptr;
67   }
68 
69   Value *FoldOr(Value *LHS, Value *RHS) const override {
70     auto *LC = dyn_cast<Constant>(LHS);
71     auto *RC = dyn_cast<Constant>(RHS);
72     if (LC && RC)
73       return Fold(ConstantExpr::getOr(LC, RC));
74     return nullptr;
75   }
76 
77   Value *FoldICmp(CmpInst::Predicate P, Value *LHS, Value *RHS) const override {
78     auto *LC = dyn_cast<Constant>(LHS);
79     auto *RC = dyn_cast<Constant>(RHS);
80     if (LC && RC)
81       return ConstantExpr::getCompare(P, LC, RC);
82     return nullptr;
83   }
84 
85   Value *FoldGEP(Type *Ty, Value *Ptr, ArrayRef<Value *> IdxList,
86                  bool IsInBounds = false) const override {
87     if (auto *PC = dyn_cast<Constant>(Ptr)) {
88       // Every index must be constant.
89       if (any_of(IdxList, [](Value *V) { return !isa<Constant>(V); }))
90         return nullptr;
91       if (IsInBounds)
92         return Fold(ConstantExpr::getInBoundsGetElementPtr(Ty, PC, IdxList));
93       else
94         return Fold(ConstantExpr::getGetElementPtr(Ty, PC, IdxList));
95     }
96     return nullptr;
97   }
98 
99   Value *FoldSelect(Value *C, Value *True, Value *False) const override {
100     auto *CC = dyn_cast<Constant>(C);
101     auto *TC = dyn_cast<Constant>(True);
102     auto *FC = dyn_cast<Constant>(False);
103     if (CC && TC && FC)
104       return Fold(ConstantExpr::getSelect(CC, TC, FC));
105 
106     return nullptr;
107   }
108 
109   //===--------------------------------------------------------------------===//
110   // Binary Operators
111   //===--------------------------------------------------------------------===//
112 
113   Constant *CreateFAdd(Constant *LHS, Constant *RHS) const override {
114     return Fold(ConstantExpr::getFAdd(LHS, RHS));
115   }
116   Constant *CreateSub(Constant *LHS, Constant *RHS,
117                       bool HasNUW = false, bool HasNSW = false) const override {
118     return Fold(ConstantExpr::getSub(LHS, RHS, HasNUW, HasNSW));
119   }
120   Constant *CreateFSub(Constant *LHS, Constant *RHS) const override {
121     return Fold(ConstantExpr::getFSub(LHS, RHS));
122   }
123   Constant *CreateMul(Constant *LHS, Constant *RHS,
124                       bool HasNUW = false, bool HasNSW = false) const override {
125     return Fold(ConstantExpr::getMul(LHS, RHS, HasNUW, HasNSW));
126   }
127   Constant *CreateFMul(Constant *LHS, Constant *RHS) const override {
128     return Fold(ConstantExpr::getFMul(LHS, RHS));
129   }
130   Constant *CreateUDiv(Constant *LHS, Constant *RHS,
131                        bool isExact = false) const override {
132     return Fold(ConstantExpr::getUDiv(LHS, RHS, isExact));
133   }
134   Constant *CreateSDiv(Constant *LHS, Constant *RHS,
135                        bool isExact = false) const override {
136     return Fold(ConstantExpr::getSDiv(LHS, RHS, isExact));
137   }
138   Constant *CreateFDiv(Constant *LHS, Constant *RHS) const override {
139     return Fold(ConstantExpr::getFDiv(LHS, RHS));
140   }
141   Constant *CreateURem(Constant *LHS, Constant *RHS) const override {
142     return Fold(ConstantExpr::getURem(LHS, RHS));
143   }
144   Constant *CreateSRem(Constant *LHS, Constant *RHS) const override {
145     return Fold(ConstantExpr::getSRem(LHS, RHS));
146   }
147   Constant *CreateFRem(Constant *LHS, Constant *RHS) const override {
148     return Fold(ConstantExpr::getFRem(LHS, RHS));
149   }
150   Constant *CreateShl(Constant *LHS, Constant *RHS,
151                       bool HasNUW = false, bool HasNSW = false) const override {
152     return Fold(ConstantExpr::getShl(LHS, RHS, HasNUW, HasNSW));
153   }
154   Constant *CreateLShr(Constant *LHS, Constant *RHS,
155                        bool isExact = false) const override {
156     return Fold(ConstantExpr::getLShr(LHS, RHS, isExact));
157   }
158   Constant *CreateAShr(Constant *LHS, Constant *RHS,
159                        bool isExact = false) const override {
160     return Fold(ConstantExpr::getAShr(LHS, RHS, isExact));
161   }
162   Constant *CreateXor(Constant *LHS, Constant *RHS) const override {
163     return Fold(ConstantExpr::getXor(LHS, RHS));
164   }
165 
166   Constant *CreateBinOp(Instruction::BinaryOps Opc,
167                         Constant *LHS, Constant *RHS) const override {
168     return Fold(ConstantExpr::get(Opc, LHS, RHS));
169   }
170 
171   //===--------------------------------------------------------------------===//
172   // Unary Operators
173   //===--------------------------------------------------------------------===//
174 
175   Constant *CreateNeg(Constant *C,
176                       bool HasNUW = false, bool HasNSW = false) const override {
177     return Fold(ConstantExpr::getNeg(C, HasNUW, HasNSW));
178   }
179   Constant *CreateFNeg(Constant *C) const override {
180     return Fold(ConstantExpr::getFNeg(C));
181   }
182   Constant *CreateNot(Constant *C) const override {
183     return Fold(ConstantExpr::getNot(C));
184   }
185 
186   Constant *CreateUnOp(Instruction::UnaryOps Opc, Constant *C) const override {
187     return Fold(ConstantExpr::get(Opc, C));
188   }
189 
190   //===--------------------------------------------------------------------===//
191   // Cast/Conversion Operators
192   //===--------------------------------------------------------------------===//
193 
194   Constant *CreateCast(Instruction::CastOps Op, Constant *C,
195                        Type *DestTy) const override {
196     if (C->getType() == DestTy)
197       return C; // avoid calling Fold
198     return Fold(ConstantExpr::getCast(Op, C, DestTy));
199   }
200   Constant *CreateIntCast(Constant *C, Type *DestTy,
201                           bool isSigned) const override {
202     if (C->getType() == DestTy)
203       return C; // avoid calling Fold
204     return Fold(ConstantExpr::getIntegerCast(C, DestTy, isSigned));
205   }
206   Constant *CreatePointerCast(Constant *C, Type *DestTy) const override {
207     if (C->getType() == DestTy)
208       return C; // avoid calling Fold
209     return Fold(ConstantExpr::getPointerCast(C, DestTy));
210   }
211   Constant *CreateFPCast(Constant *C, Type *DestTy) const override {
212     if (C->getType() == DestTy)
213       return C; // avoid calling Fold
214     return Fold(ConstantExpr::getFPCast(C, DestTy));
215   }
216   Constant *CreateBitCast(Constant *C, Type *DestTy) const override {
217     return CreateCast(Instruction::BitCast, C, DestTy);
218   }
219   Constant *CreateIntToPtr(Constant *C, Type *DestTy) const override {
220     return CreateCast(Instruction::IntToPtr, C, DestTy);
221   }
222   Constant *CreatePtrToInt(Constant *C, Type *DestTy) const override {
223     return CreateCast(Instruction::PtrToInt, C, DestTy);
224   }
225   Constant *CreateZExtOrBitCast(Constant *C, Type *DestTy) const override {
226     if (C->getType() == DestTy)
227       return C; // avoid calling Fold
228     return Fold(ConstantExpr::getZExtOrBitCast(C, DestTy));
229   }
230   Constant *CreateSExtOrBitCast(Constant *C, Type *DestTy) const override {
231     if (C->getType() == DestTy)
232       return C; // avoid calling Fold
233     return Fold(ConstantExpr::getSExtOrBitCast(C, DestTy));
234   }
235   Constant *CreateTruncOrBitCast(Constant *C, Type *DestTy) const override {
236     if (C->getType() == DestTy)
237       return C; // avoid calling Fold
238     return Fold(ConstantExpr::getTruncOrBitCast(C, DestTy));
239   }
240 
241   Constant *CreatePointerBitCastOrAddrSpaceCast(Constant *C,
242                                                 Type *DestTy) const override {
243     if (C->getType() == DestTy)
244       return C; // avoid calling Fold
245     return Fold(ConstantExpr::getPointerBitCastOrAddrSpaceCast(C, DestTy));
246   }
247 
248   //===--------------------------------------------------------------------===//
249   // Compare Instructions
250   //===--------------------------------------------------------------------===//
251 
252   Constant *CreateFCmp(CmpInst::Predicate P, Constant *LHS,
253                        Constant *RHS) const override {
254     return Fold(ConstantExpr::getCompare(P, LHS, RHS));
255   }
256 
257   //===--------------------------------------------------------------------===//
258   // Other Instructions
259   //===--------------------------------------------------------------------===//
260 
261   Constant *CreateExtractElement(Constant *Vec, Constant *Idx) const override {
262     return Fold(ConstantExpr::getExtractElement(Vec, Idx));
263   }
264 
265   Constant *CreateInsertElement(Constant *Vec, Constant *NewElt,
266                                 Constant *Idx) const override {
267     return Fold(ConstantExpr::getInsertElement(Vec, NewElt, Idx));
268   }
269 
270   Constant *CreateShuffleVector(Constant *V1, Constant *V2,
271                                 ArrayRef<int> Mask) const override {
272     return Fold(ConstantExpr::getShuffleVector(V1, V2, Mask));
273   }
274 
275   Constant *CreateExtractValue(Constant *Agg,
276                                ArrayRef<unsigned> IdxList) const override {
277     return Fold(ConstantExpr::getExtractValue(Agg, IdxList));
278   }
279 
280   Constant *CreateInsertValue(Constant *Agg, Constant *Val,
281                               ArrayRef<unsigned> IdxList) const override {
282     return Fold(ConstantExpr::getInsertValue(Agg, Val, IdxList));
283   }
284 };
285 
286 }
287 
288 #endif
289