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