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
26namespace llvm {
27
28/// ConstantFolder - Create constants with minimum, target independent, folding.
29class ConstantFolder final : public IRBuilderFolder {
30 virtual void anchor();
31
32public:
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 *CreateExtractElement(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 *CreateExtractValue(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