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/ConstantFold.h" |
23 | #include "llvm/IR/IRBuilderFolder.h" |
24 | #include "llvm/IR/Instruction.h" |
25 | #include "llvm/IR/Operator.h" |
26 | |
27 | namespace llvm { |
28 | |
29 | /// ConstantFolder - Create constants with minimum, target independent, folding. |
30 | class ConstantFolder final : public IRBuilderFolder { |
31 | virtual void anchor(); |
32 | |
33 | public: |
34 | explicit ConstantFolder() = default; |
35 | |
36 | //===--------------------------------------------------------------------===// |
37 | // Value-based folders. |
38 | // |
39 | // Return an existing value or a constant if the operation can be simplified. |
40 | // Otherwise return nullptr. |
41 | //===--------------------------------------------------------------------===// |
42 | |
43 | Value *FoldBinOp(Instruction::BinaryOps Opc, Value *LHS, |
44 | Value *RHS) const override { |
45 | auto *LC = dyn_cast<Constant>(Val: LHS); |
46 | auto *RC = dyn_cast<Constant>(Val: RHS); |
47 | if (LC && RC) { |
48 | if (ConstantExpr::isDesirableBinOp(Opcode: Opc)) |
49 | return ConstantExpr::get(Opcode: Opc, C1: LC, C2: RC); |
50 | return ConstantFoldBinaryInstruction(Opcode: Opc, V1: LC, V2: RC); |
51 | } |
52 | return nullptr; |
53 | } |
54 | |
55 | Value *FoldExactBinOp(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, |
56 | bool IsExact) const override { |
57 | auto *LC = dyn_cast<Constant>(Val: LHS); |
58 | auto *RC = dyn_cast<Constant>(Val: RHS); |
59 | if (LC && RC) { |
60 | if (ConstantExpr::isDesirableBinOp(Opcode: Opc)) |
61 | return ConstantExpr::get(Opcode: Opc, C1: LC, C2: RC, |
62 | Flags: IsExact ? PossiblyExactOperator::IsExact : 0); |
63 | return ConstantFoldBinaryInstruction(Opcode: Opc, V1: LC, V2: RC); |
64 | } |
65 | return nullptr; |
66 | } |
67 | |
68 | Value *FoldNoWrapBinOp(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, |
69 | bool HasNUW, bool HasNSW) const override { |
70 | auto *LC = dyn_cast<Constant>(Val: LHS); |
71 | auto *RC = dyn_cast<Constant>(Val: RHS); |
72 | if (LC && RC) { |
73 | if (ConstantExpr::isDesirableBinOp(Opcode: Opc)) { |
74 | unsigned Flags = 0; |
75 | if (HasNUW) |
76 | Flags |= OverflowingBinaryOperator::NoUnsignedWrap; |
77 | if (HasNSW) |
78 | Flags |= OverflowingBinaryOperator::NoSignedWrap; |
79 | return ConstantExpr::get(Opcode: Opc, C1: LC, C2: RC, Flags); |
80 | } |
81 | return ConstantFoldBinaryInstruction(Opcode: Opc, V1: LC, V2: RC); |
82 | } |
83 | return nullptr; |
84 | } |
85 | |
86 | Value *FoldBinOpFMF(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, |
87 | FastMathFlags FMF) const override { |
88 | return FoldBinOp(Opc, LHS, RHS); |
89 | } |
90 | |
91 | Value *FoldUnOpFMF(Instruction::UnaryOps Opc, Value *V, |
92 | FastMathFlags FMF) const override { |
93 | if (Constant *C = dyn_cast<Constant>(Val: V)) |
94 | return ConstantFoldUnaryInstruction(Opcode: Opc, V: C); |
95 | return nullptr; |
96 | } |
97 | |
98 | Value *FoldICmp(CmpInst::Predicate P, Value *LHS, Value *RHS) const override { |
99 | auto *LC = dyn_cast<Constant>(Val: LHS); |
100 | auto *RC = dyn_cast<Constant>(Val: RHS); |
101 | if (LC && RC) |
102 | return ConstantExpr::getCompare(pred: P, C1: LC, C2: RC); |
103 | return nullptr; |
104 | } |
105 | |
106 | Value *FoldGEP(Type *Ty, Value *Ptr, ArrayRef<Value *> IdxList, |
107 | bool IsInBounds = false) const override { |
108 | if (!ConstantExpr::isSupportedGetElementPtr(SrcElemTy: Ty)) |
109 | return nullptr; |
110 | |
111 | if (auto *PC = dyn_cast<Constant>(Val: Ptr)) { |
112 | // Every index must be constant. |
113 | if (any_of(Range&: IdxList, P: [](Value *V) { return !isa<Constant>(Val: V); })) |
114 | return nullptr; |
115 | |
116 | if (IsInBounds) |
117 | return ConstantExpr::getInBoundsGetElementPtr(Ty, C: PC, IdxList); |
118 | else |
119 | return ConstantExpr::getGetElementPtr(Ty, C: PC, IdxList); |
120 | } |
121 | return nullptr; |
122 | } |
123 | |
124 | Value *FoldSelect(Value *C, Value *True, Value *False) const override { |
125 | auto *CC = dyn_cast<Constant>(Val: C); |
126 | auto *TC = dyn_cast<Constant>(Val: True); |
127 | auto *FC = dyn_cast<Constant>(Val: False); |
128 | if (CC && TC && FC) |
129 | return ConstantFoldSelectInstruction(Cond: CC, V1: TC, V2: FC); |
130 | return nullptr; |
131 | } |
132 | |
133 | Value *(Value *Agg, |
134 | ArrayRef<unsigned> IdxList) const override { |
135 | if (auto *CAgg = dyn_cast<Constant>(Val: Agg)) |
136 | return ConstantFoldExtractValueInstruction(Agg: CAgg, Idxs: IdxList); |
137 | return nullptr; |
138 | }; |
139 | |
140 | Value *FoldInsertValue(Value *Agg, Value *Val, |
141 | ArrayRef<unsigned> IdxList) const override { |
142 | auto *CAgg = dyn_cast<Constant>(Val: Agg); |
143 | auto *CVal = dyn_cast<Constant>(Val); |
144 | if (CAgg && CVal) |
145 | return ConstantFoldInsertValueInstruction(Agg: CAgg, Val: CVal, Idxs: IdxList); |
146 | return nullptr; |
147 | } |
148 | |
149 | Value *(Value *Vec, Value *Idx) const override { |
150 | auto *CVec = dyn_cast<Constant>(Val: Vec); |
151 | auto *CIdx = dyn_cast<Constant>(Val: Idx); |
152 | if (CVec && CIdx) |
153 | return ConstantExpr::getExtractElement(Vec: CVec, Idx: CIdx); |
154 | return nullptr; |
155 | } |
156 | |
157 | Value *FoldInsertElement(Value *Vec, Value *NewElt, |
158 | Value *Idx) const override { |
159 | auto *CVec = dyn_cast<Constant>(Val: Vec); |
160 | auto *CNewElt = dyn_cast<Constant>(Val: NewElt); |
161 | auto *CIdx = dyn_cast<Constant>(Val: Idx); |
162 | if (CVec && CNewElt && CIdx) |
163 | return ConstantExpr::getInsertElement(Vec: CVec, Elt: CNewElt, Idx: CIdx); |
164 | return nullptr; |
165 | } |
166 | |
167 | Value *FoldShuffleVector(Value *V1, Value *V2, |
168 | ArrayRef<int> Mask) const override { |
169 | auto *C1 = dyn_cast<Constant>(Val: V1); |
170 | auto *C2 = dyn_cast<Constant>(Val: V2); |
171 | if (C1 && C2) |
172 | return ConstantExpr::getShuffleVector(V1: C1, V2: C2, Mask); |
173 | return nullptr; |
174 | } |
175 | |
176 | Value *FoldCast(Instruction::CastOps Op, Value *V, |
177 | Type *DestTy) const override { |
178 | if (auto *C = dyn_cast<Constant>(Val: V)) { |
179 | if (ConstantExpr::isDesirableCastOp(Opcode: Op)) |
180 | return ConstantExpr::getCast(ops: Op, C, Ty: DestTy); |
181 | return ConstantFoldCastInstruction(opcode: Op, V: C, DestTy); |
182 | } |
183 | return nullptr; |
184 | } |
185 | |
186 | //===--------------------------------------------------------------------===// |
187 | // Cast/Conversion Operators |
188 | //===--------------------------------------------------------------------===// |
189 | |
190 | Constant *CreatePointerCast(Constant *C, Type *DestTy) const override { |
191 | return ConstantExpr::getPointerCast(C, Ty: DestTy); |
192 | } |
193 | |
194 | Constant *CreatePointerBitCastOrAddrSpaceCast(Constant *C, |
195 | Type *DestTy) const override { |
196 | return ConstantExpr::getPointerBitCastOrAddrSpaceCast(C, Ty: DestTy); |
197 | } |
198 | |
199 | //===--------------------------------------------------------------------===// |
200 | // Compare Instructions |
201 | //===--------------------------------------------------------------------===// |
202 | |
203 | Constant *CreateFCmp(CmpInst::Predicate P, Constant *LHS, |
204 | Constant *RHS) const override { |
205 | return ConstantExpr::getCompare(pred: P, C1: LHS, C2: RHS); |
206 | } |
207 | }; |
208 | |
209 | } // end namespace llvm |
210 | |
211 | #endif // LLVM_IR_CONSTANTFOLDER_H |
212 | |