Skip to content

Commit 2f96400

Browse files
committed
VPlan: implement VPlan-level constant-folding
Introduce VPlanConstantFolder, a variation of ConstantFolder for VPlan, and use it in VPBuilder to constant-fold when all the underlying IR values passed into the API are constants.
1 parent 2b4a4f0 commit 2f96400

File tree

6 files changed

+286
-67
lines changed

6 files changed

+286
-67
lines changed

llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
#define LLVM_TRANSFORMS_VECTORIZE_LOOPVECTORIZATIONPLANNER_H
2626

2727
#include "VPlan.h"
28-
#include "llvm/ADT/SmallSet.h"
28+
#include "VPlanConstantFolder.h"
2929
#include "llvm/Support/InstructionCost.h"
3030

3131
namespace llvm {
@@ -46,6 +46,7 @@ struct VFRange;
4646
class VPBuilder {
4747
VPBasicBlock *BB = nullptr;
4848
VPBasicBlock::iterator InsertPt = VPBasicBlock::iterator();
49+
VPConstantFolder Folder;
4950

5051
/// Insert \p VPI in BB at InsertPt if BB is set.
5152
template <typename T> T *tryInsertInstruction(T *R) {
@@ -66,6 +67,11 @@ class VPBuilder {
6667
return createInstruction(Opcode, ArrayRef<VPValue *>(Operands), DL, Name);
6768
}
6869

70+
VPValue *getOrAddLiveIn(Value *V) {
71+
assert(BB && "Expected insertion point to be set");
72+
return BB->getPlan()->getOrAddLiveIn(V);
73+
}
74+
6975
public:
7076
VPBuilder() = default;
7177
VPBuilder(VPBasicBlock *InsertBB) { setInsertPoint(InsertBB); }
@@ -180,31 +186,45 @@ class VPBuilder {
180186

181187
VPValue *createNot(VPValue *Operand, DebugLoc DL = {},
182188
const Twine &Name = "") {
189+
if (auto *V = Folder.foldNot(Operand))
190+
if (BB)
191+
return getOrAddLiveIn(V);
183192
return createInstruction(VPInstruction::Not, {Operand}, DL, Name);
184193
}
185194

186195
VPValue *createAnd(VPValue *LHS, VPValue *RHS, DebugLoc DL = {},
187196
const Twine &Name = "") {
197+
if (auto *V = Folder.foldAnd(LHS, RHS))
198+
if (BB)
199+
return getOrAddLiveIn(V);
188200
return createInstruction(Instruction::BinaryOps::And, {LHS, RHS}, DL, Name);
189201
}
190202

191203
VPValue *createOr(VPValue *LHS, VPValue *RHS, DebugLoc DL = {},
192204
const Twine &Name = "") {
193-
205+
if (auto *V = Folder.foldOr(LHS, RHS))
206+
if (BB)
207+
return getOrAddLiveIn(V);
194208
return tryInsertInstruction(new VPInstruction(
195209
Instruction::BinaryOps::Or, {LHS, RHS},
196210
VPRecipeWithIRFlags::DisjointFlagsTy(false), DL, Name));
197211
}
198212

199213
VPValue *createLogicalAnd(VPValue *LHS, VPValue *RHS, DebugLoc DL = {},
200214
const Twine &Name = "") {
215+
if (auto *V = Folder.foldLogicalAnd(LHS, RHS))
216+
if (BB)
217+
return getOrAddLiveIn(V);
201218
return tryInsertInstruction(
202219
new VPInstruction(VPInstruction::LogicalAnd, {LHS, RHS}, DL, Name));
203220
}
204221

205222
VPValue *createSelect(VPValue *Cond, VPValue *TrueVal, VPValue *FalseVal,
206223
DebugLoc DL = {}, const Twine &Name = "",
207224
std::optional<FastMathFlags> FMFs = std::nullopt) {
225+
if (auto *V = Folder.foldSelect(Cond, TrueVal, FalseVal))
226+
if (BB)
227+
return getOrAddLiveIn(V);
208228
auto *Select =
209229
FMFs ? new VPInstruction(Instruction::Select, {Cond, TrueVal, FalseVal},
210230
*FMFs, DL, Name)
@@ -220,17 +240,26 @@ class VPBuilder {
220240
DebugLoc DL = {}, const Twine &Name = "") {
221241
assert(Pred >= CmpInst::FIRST_ICMP_PREDICATE &&
222242
Pred <= CmpInst::LAST_ICMP_PREDICATE && "invalid predicate");
243+
if (auto *V = Folder.foldCmp(Pred, A, B))
244+
if (BB)
245+
return getOrAddLiveIn(V);
223246
return tryInsertInstruction(
224247
new VPInstruction(Instruction::ICmp, Pred, A, B, DL, Name));
225248
}
226249

227-
VPInstruction *createPtrAdd(VPValue *Ptr, VPValue *Offset, DebugLoc DL = {},
228-
const Twine &Name = "") {
250+
VPValue *createPtrAdd(VPValue *Ptr, VPValue *Offset, DebugLoc DL = {},
251+
const Twine &Name = "") {
252+
if (auto *V = Folder.foldPtrAdd(Ptr, Offset, GEPNoWrapFlags::none()))
253+
if (BB)
254+
return getOrAddLiveIn(V);
229255
return tryInsertInstruction(
230256
new VPInstruction(Ptr, Offset, GEPNoWrapFlags::none(), DL, Name));
231257
}
232258
VPValue *createInBoundsPtrAdd(VPValue *Ptr, VPValue *Offset, DebugLoc DL = {},
233259
const Twine &Name = "") {
260+
if (auto *V = Folder.foldPtrAdd(Ptr, Offset, GEPNoWrapFlags::inBounds()))
261+
if (BB)
262+
return getOrAddLiveIn(V);
234263
return tryInsertInstruction(
235264
new VPInstruction(Ptr, Offset, GEPNoWrapFlags::inBounds(), DL, Name));
236265
}
@@ -246,14 +275,20 @@ class VPBuilder {
246275
new VPDerivedIVRecipe(Kind, FPBinOp, Start, Current, Step, Name));
247276
}
248277

249-
VPScalarCastRecipe *createScalarCast(Instruction::CastOps Opcode, VPValue *Op,
250-
Type *ResultTy, DebugLoc DL) {
278+
VPValue *createScalarCast(Instruction::CastOps Opcode, VPValue *Op,
279+
Type *ResultTy, DebugLoc DL) {
280+
if (auto *V = Folder.foldCast(Opcode, Op, ResultTy))
281+
if (BB)
282+
return getOrAddLiveIn(V);
251283
return tryInsertInstruction(
252284
new VPScalarCastRecipe(Opcode, Op, ResultTy, DL));
253285
}
254286

255-
VPWidenCastRecipe *createWidenCast(Instruction::CastOps Opcode, VPValue *Op,
256-
Type *ResultTy) {
287+
VPValue *createWidenCast(Instruction::CastOps Opcode, VPValue *Op,
288+
Type *ResultTy) {
289+
if (auto *V = Folder.foldCast(Opcode, Op, ResultTy))
290+
if (BB)
291+
return getOrAddLiveIn(V);
257292
return tryInsertInstruction(new VPWidenCastRecipe(Opcode, Op, ResultTy));
258293
}
259294

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
//===- VPlanConstantFolder.h - ConstantFolder for VPlan -------------------===//
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+
#include "VPlanValue.h"
10+
#include "llvm/IR/ConstantFolder.h"
11+
12+
#ifndef LLVM_TRANSFORMS_VECTORIZE_VPLANCONSTANTFOLDER_H
13+
#define LLVM_TRANSFORMS_VECTORIZE_VPLANCONSTANTFOLDER_H
14+
15+
namespace llvm {
16+
class VPConstantFolder {
17+
private:
18+
ConstantFolder Folder;
19+
20+
Constant *getIRConstant(VPValue *V) const {
21+
if (!V->isLiveIn())
22+
return nullptr;
23+
return dyn_cast_if_present<Constant>(V->getLiveInIRValue());
24+
}
25+
26+
Value *foldBinOp(Instruction::BinaryOps Opcode, VPValue *LHS,
27+
VPValue *RHS) const {
28+
auto *LC = getIRConstant(LHS);
29+
auto *RC = getIRConstant(RHS);
30+
if (LC && RC)
31+
return Folder.FoldBinOp(Opcode, LC, RC);
32+
return nullptr;
33+
}
34+
35+
public:
36+
Value *foldAnd(VPValue *LHS, VPValue *RHS) const {
37+
return foldBinOp(Instruction::BinaryOps::And, LHS, RHS);
38+
}
39+
40+
Value *foldOr(VPValue *LHS, VPValue *RHS) const {
41+
return foldBinOp(Instruction::BinaryOps::Or, LHS, RHS);
42+
}
43+
44+
Value *foldNot(VPValue *Op) const {
45+
auto *C = getIRConstant(Op);
46+
if (C)
47+
return Folder.FoldBinOp(Instruction::BinaryOps::Xor, C,
48+
Constant::getAllOnesValue(C->getType()));
49+
return nullptr;
50+
}
51+
52+
Value *foldLogicalAnd(VPValue *LHS, VPValue *RHS) const {
53+
auto *LC = getIRConstant(LHS);
54+
auto *RC = getIRConstant(RHS);
55+
if (LC && RC)
56+
return Folder.FoldSelect(LC, RC,
57+
ConstantInt::getNullValue(RC->getType()));
58+
return nullptr;
59+
}
60+
61+
Value *foldSelect(VPValue *Cond, VPValue *TrueVal, VPValue *FalseVal) const {
62+
auto *CC = getIRConstant(Cond);
63+
auto *TV = getIRConstant(TrueVal);
64+
auto *FV = getIRConstant(FalseVal);
65+
if (CC && TV && FV)
66+
return Folder.FoldSelect(CC, TV, FV);
67+
return nullptr;
68+
}
69+
70+
Value *foldCmp(CmpInst::Predicate Pred, VPValue *LHS, VPValue *RHS) const {
71+
auto *LC = getIRConstant(LHS);
72+
auto *RC = getIRConstant(RHS);
73+
if (LC && RC)
74+
return Folder.FoldCmp(Pred, LC, RC);
75+
return nullptr;
76+
}
77+
78+
Value *foldPtrAdd(VPValue *Base, VPValue *Offset, GEPNoWrapFlags NW) const {
79+
auto *BC = getIRConstant(Base);
80+
auto *OC = getIRConstant(Offset);
81+
if (BC && OC) {
82+
auto &Ctx = BC->getType()->getContext();
83+
return Folder.FoldGEP(Type::getInt8Ty(Ctx), BC, OC, NW);
84+
}
85+
return nullptr;
86+
}
87+
88+
Value *foldCast(Instruction::CastOps Opcode, VPValue *Op,
89+
Type *DestTy) const {
90+
auto *C = getIRConstant(Op);
91+
if (C)
92+
return Folder.FoldCast(Opcode, C, DestTy);
93+
return nullptr;
94+
}
95+
};
96+
} // namespace llvm
97+
98+
#endif

llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -533,8 +533,8 @@ createScalarIVSteps(VPlan &Plan, InductionDescriptor::InductionKind Kind,
533533
VPBuilder &Builder) {
534534
VPBasicBlock *HeaderVPBB = Plan.getVectorLoopRegion()->getEntryBasicBlock();
535535
VPCanonicalIVPHIRecipe *CanonicalIV = Plan.getCanonicalIV();
536-
VPSingleDefRecipe *BaseIV = Builder.createDerivedIV(
537-
Kind, FPBinOp, StartV, CanonicalIV, Step, "offset.idx");
536+
VPValue *BaseIV = Builder.createDerivedIV(Kind, FPBinOp, StartV, CanonicalIV,
537+
Step, "offset.idx");
538538

539539
// Truncate base induction if needed.
540540
Type *CanonicalIVType = CanonicalIV->getScalarType();

0 commit comments

Comments
 (0)