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

source code of llvm/include/llvm/Analysis/TargetFolder.h