Line data Source code
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/ConstantFold.h"
22 : #include "llvm/IR/Constants.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 0 : 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>(LHS);
46 : auto *RC = dyn_cast<Constant>(RHS);
47 : if (LC && RC) {
48 : if (ConstantExpr::isDesirableBinOp(Opc))
49 : return ConstantExpr::get(Opc, LC, RC);
50 : return ConstantFoldBinaryInstruction(Opc, LC, 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>(LHS);
58 : auto *RC = dyn_cast<Constant>(RHS);
59 : if (LC && RC) {
60 : if (ConstantExpr::isDesirableBinOp(Opc))
61 : return ConstantExpr::get(Opc, LC, RC,
62 : IsExact ? PossiblyExactOperator::IsExact : 0);
63 : return ConstantFoldBinaryInstruction(Opc, LC, 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>(LHS);
71 : auto *RC = dyn_cast<Constant>(RHS);
72 : if (LC && RC) {
73 : if (ConstantExpr::isDesirableBinOp(Opc)) {
74 : unsigned Flags = 0;
75 : if (HasNUW)
76 : Flags |= OverflowingBinaryOperator::NoUnsignedWrap;
77 : if (HasNSW)
78 : Flags |= OverflowingBinaryOperator::NoSignedWrap;
79 : return ConstantExpr::get(Opc, LC, RC, Flags);
80 : }
81 : return ConstantFoldBinaryInstruction(Opc, LC, 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>(V))
94 : return ConstantFoldUnaryInstruction(Opc, C);
95 : return nullptr;
96 : }
97 :
98 : Value *FoldCmp(CmpInst::Predicate P, Value *LHS, Value *RHS) const override {
99 : auto *LC = dyn_cast<Constant>(LHS);
100 : auto *RC = dyn_cast<Constant>(RHS);
101 : if (LC && RC)
102 : return ConstantFoldCompareInstruction(P, LC, RC);
103 : return nullptr;
104 : }
105 :
106 : Value *FoldGEP(Type *Ty, Value *Ptr, ArrayRef<Value *> IdxList,
107 : GEPNoWrapFlags NW) const override {
108 : if (!ConstantExpr::isSupportedGetElementPtr(Ty))
109 : return nullptr;
110 :
111 : if (auto *PC = dyn_cast<Constant>(Ptr)) {
112 : // Every index must be constant.
113 : if (any_of(IdxList, [](Value *V) { return !isa<Constant>(V); }))
114 : return nullptr;
115 :
116 : return ConstantExpr::getGetElementPtr(Ty, PC, IdxList, NW);
117 : }
118 : return nullptr;
119 : }
120 :
121 : Value *FoldSelect(Value *C, Value *True, Value *False) const override {
122 : auto *CC = dyn_cast<Constant>(C);
123 : auto *TC = dyn_cast<Constant>(True);
124 : auto *FC = dyn_cast<Constant>(False);
125 : if (CC && TC && FC)
126 : return ConstantFoldSelectInstruction(CC, TC, FC);
127 : return nullptr;
128 : }
129 :
130 : Value *FoldExtractValue(Value *Agg,
131 : ArrayRef<unsigned> IdxList) const override {
132 : if (auto *CAgg = dyn_cast<Constant>(Agg))
133 : return ConstantFoldExtractValueInstruction(CAgg, IdxList);
134 : return nullptr;
135 : };
136 :
137 : Value *FoldInsertValue(Value *Agg, Value *Val,
138 : ArrayRef<unsigned> IdxList) const override {
139 : auto *CAgg = dyn_cast<Constant>(Agg);
140 : auto *CVal = dyn_cast<Constant>(Val);
141 : if (CAgg && CVal)
142 : return ConstantFoldInsertValueInstruction(CAgg, CVal, IdxList);
143 : return nullptr;
144 : }
145 :
146 : Value *FoldExtractElement(Value *Vec, Value *Idx) const override {
147 : auto *CVec = dyn_cast<Constant>(Vec);
148 : auto *CIdx = dyn_cast<Constant>(Idx);
149 : if (CVec && CIdx)
150 : return ConstantExpr::getExtractElement(CVec, CIdx);
151 : return nullptr;
152 : }
153 :
154 : Value *FoldInsertElement(Value *Vec, Value *NewElt,
155 : Value *Idx) const override {
156 : auto *CVec = dyn_cast<Constant>(Vec);
157 : auto *CNewElt = dyn_cast<Constant>(NewElt);
158 : auto *CIdx = dyn_cast<Constant>(Idx);
159 : if (CVec && CNewElt && CIdx)
160 : return ConstantExpr::getInsertElement(CVec, CNewElt, CIdx);
161 : return nullptr;
162 : }
163 :
164 : Value *FoldShuffleVector(Value *V1, Value *V2,
165 : ArrayRef<int> Mask) const override {
166 : auto *C1 = dyn_cast<Constant>(V1);
167 : auto *C2 = dyn_cast<Constant>(V2);
168 : if (C1 && C2)
169 : return ConstantExpr::getShuffleVector(C1, C2, Mask);
170 : return nullptr;
171 : }
172 :
173 : Value *FoldCast(Instruction::CastOps Op, Value *V,
174 : Type *DestTy) const override {
175 : if (auto *C = dyn_cast<Constant>(V)) {
176 : if (ConstantExpr::isDesirableCastOp(Op))
177 : return ConstantExpr::getCast(Op, C, DestTy);
178 : return ConstantFoldCastInstruction(Op, C, DestTy);
179 : }
180 : return nullptr;
181 : }
182 :
183 : Value *FoldBinaryIntrinsic(Intrinsic::ID ID, Value *LHS, Value *RHS, Type *Ty,
184 : Instruction *FMFSource) const override {
185 : // Use TargetFolder or InstSimplifyFolder instead.
186 : return nullptr;
187 : }
188 :
189 : //===--------------------------------------------------------------------===//
190 : // Cast/Conversion Operators
191 : //===--------------------------------------------------------------------===//
192 :
193 : Constant *CreatePointerCast(Constant *C, Type *DestTy) const override {
194 : return ConstantExpr::getPointerCast(C, DestTy);
195 : }
196 :
197 : Constant *CreatePointerBitCastOrAddrSpaceCast(Constant *C,
198 : Type *DestTy) const override {
199 : return ConstantExpr::getPointerBitCastOrAddrSpaceCast(C, DestTy);
200 : }
201 : };
202 :
203 : } // end namespace llvm
204 :
205 : #endif // LLVM_IR_CONSTANTFOLDER_H
|