Skip to content

Commit 958b973

Browse files
committed
VPlan: use Worklist in simplifyRecipes
Since simplifyRecipe creates new recipes in some cases, use a Worklist in its caller to capture newly-created recipes, and add it to the Worklist, as a candidate for further simplification. This patch thoroughly rewrites simplifyRecipe to simplify matched patterns, eraseFromParent when applicable, and simplify the logic.
1 parent 641e2ec commit 958b973

File tree

7 files changed

+144
-108
lines changed

7 files changed

+144
-108
lines changed

llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -161,33 +161,34 @@ class VPBuilder {
161161
return tryInsertInstruction(
162162
new VPInstruction(Opcode, Operands, WrapFlags, DL, Name));
163163
}
164-
VPValue *createNot(VPValue *Operand, DebugLoc DL = {},
165-
const Twine &Name = "") {
164+
VPInstruction *createNot(VPValue *Operand, DebugLoc DL = {},
165+
const Twine &Name = "") {
166166
return createInstruction(VPInstruction::Not, {Operand}, DL, Name);
167167
}
168168

169-
VPValue *createAnd(VPValue *LHS, VPValue *RHS, DebugLoc DL = {},
170-
const Twine &Name = "") {
169+
VPInstruction *createAnd(VPValue *LHS, VPValue *RHS, DebugLoc DL = {},
170+
const Twine &Name = "") {
171171
return createInstruction(Instruction::BinaryOps::And, {LHS, RHS}, DL, Name);
172172
}
173173

174-
VPValue *createOr(VPValue *LHS, VPValue *RHS, DebugLoc DL = {},
175-
const Twine &Name = "") {
174+
VPInstruction *createOr(VPValue *LHS, VPValue *RHS, DebugLoc DL = {},
175+
const Twine &Name = "") {
176176

177177
return tryInsertInstruction(new VPInstruction(
178178
Instruction::BinaryOps::Or, {LHS, RHS},
179179
VPRecipeWithIRFlags::DisjointFlagsTy(false), DL, Name));
180180
}
181181

182-
VPValue *createLogicalAnd(VPValue *LHS, VPValue *RHS, DebugLoc DL = {},
183-
const Twine &Name = "") {
182+
VPInstruction *createLogicalAnd(VPValue *LHS, VPValue *RHS, DebugLoc DL = {},
183+
const Twine &Name = "") {
184184
return tryInsertInstruction(
185185
new VPInstruction(VPInstruction::LogicalAnd, {LHS, RHS}, DL, Name));
186186
}
187187

188-
VPValue *createSelect(VPValue *Cond, VPValue *TrueVal, VPValue *FalseVal,
189-
DebugLoc DL = {}, const Twine &Name = "",
190-
std::optional<FastMathFlags> FMFs = std::nullopt) {
188+
VPInstruction *
189+
createSelect(VPValue *Cond, VPValue *TrueVal, VPValue *FalseVal,
190+
DebugLoc DL = {}, const Twine &Name = "",
191+
std::optional<FastMathFlags> FMFs = std::nullopt) {
191192
auto *Select =
192193
FMFs ? new VPInstruction(Instruction::Select, {Cond, TrueVal, FalseVal},
193194
*FMFs, DL, Name)
@@ -199,8 +200,8 @@ class VPBuilder {
199200
/// Create a new ICmp VPInstruction with predicate \p Pred and operands \p A
200201
/// and \p B.
201202
/// TODO: add createFCmp when needed.
202-
VPValue *createICmp(CmpInst::Predicate Pred, VPValue *A, VPValue *B,
203-
DebugLoc DL = {}, const Twine &Name = "");
203+
VPInstruction *createICmp(CmpInst::Predicate Pred, VPValue *A, VPValue *B,
204+
DebugLoc DL = {}, const Twine &Name = "");
204205

205206
//===--------------------------------------------------------------------===//
206207
// RAII helpers.

llvm/lib/Transforms/Vectorize/LoopVectorize.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6903,8 +6903,9 @@ void LoopVectorizationCostModel::collectInLoopReductions() {
69036903
}
69046904
}
69056905

6906-
VPValue *VPBuilder::createICmp(CmpInst::Predicate Pred, VPValue *A, VPValue *B,
6907-
DebugLoc DL, const Twine &Name) {
6906+
VPInstruction *VPBuilder::createICmp(CmpInst::Predicate Pred, VPValue *A,
6907+
VPValue *B, DebugLoc DL,
6908+
const Twine &Name) {
69086909
assert(Pred >= CmpInst::FIRST_ICMP_PREDICATE &&
69096910
Pred <= CmpInst::LAST_ICMP_PREDICATE && "invalid predicate");
69106911
return tryInsertInstruction(

llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,9 @@ template <unsigned BitWidth = 0> struct specific_intval {
7575
if (!CI)
7676
return false;
7777

78-
assert((BitWidth == 0 || CI->getBitWidth() == BitWidth) &&
79-
"Trying the match constant with unexpected bitwidth.");
78+
if (BitWidth != 0 && CI->getBitWidth() != BitWidth)
79+
return false;
80+
8081
return APInt::isSameValue(CI->getValue(), Val);
8182
}
8283
};
@@ -87,6 +88,8 @@ inline specific_intval<0> m_SpecificInt(uint64_t V) {
8788

8889
inline specific_intval<1> m_False() { return specific_intval<1>(APInt(64, 0)); }
8990

91+
inline specific_intval<1> m_True() { return specific_intval<1>(APInt(64, 1)); }
92+
9093
/// Matching combinators
9194
template <typename LTy, typename RTy> struct match_combine_or {
9295
LTy L;

llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp

Lines changed: 78 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "llvm/Analysis/VectorUtils.h"
2525
#include "llvm/IR/Intrinsics.h"
2626
#include "llvm/IR/PatternMatch.h"
27+
#include <deque>
2728

2829
using namespace llvm;
2930

@@ -892,9 +893,10 @@ void VPlanTransforms::clearReductionWrapFlags(VPlan &Plan) {
892893
}
893894
}
894895

895-
/// Try to simplify recipe \p R. Returns any new recipes introduced during
896-
/// simplification, as a candidate for further simplification.
897-
static VPRecipeBase *simplifyRecipe(VPRecipeBase &R, VPTypeAnalysis &TypeInfo) {
896+
/// Try to simplify recipe \p R. Returns any new recipes introduced during
897+
/// simplification, as candidates for further simplification.
898+
static SmallVector<VPRecipeBase *>
899+
simplifyRecipe(VPRecipeBase &R, VPTypeAnalysis &TypeInfo, VPlan &Plan) {
898900
using namespace llvm::VPlanPatternMatch;
899901

900902
if (auto *Blend = dyn_cast<VPBlendRecipe>(&R)) {
@@ -909,11 +911,11 @@ static VPRecipeBase *simplifyRecipe(VPRecipeBase &R, VPTypeAnalysis &TypeInfo) {
909911
if (UniqueValues.size() == 1) {
910912
Blend->replaceAllUsesWith(*UniqueValues.begin());
911913
Blend->eraseFromParent();
912-
return nullptr;
914+
return {};
913915
}
914916

915917
if (Blend->isNormalized())
916-
return nullptr;
918+
return {};
917919

918920
// Normalize the blend so its first incomming value is used as the initial
919921
// value with the others blended into it.
@@ -937,7 +939,7 @@ static VPRecipeBase *simplifyRecipe(VPRecipeBase &R, VPTypeAnalysis &TypeInfo) {
937939
Blend->replaceAllUsesWith(NewBlend);
938940
Blend->eraseFromParent();
939941
recursivelyDeleteDeadRecipes(DeadMask);
940-
return nullptr;
942+
return {};
941943
}
942944

943945
VPValue *A;
@@ -986,25 +988,74 @@ static VPRecipeBase *simplifyRecipe(VPRecipeBase &R, VPTypeAnalysis &TypeInfo) {
986988
assert(TypeInfo.inferScalarType(VPV) == TypeInfo2.inferScalarType(VPV));
987989
}
988990
#endif
989-
return VPC;
991+
if (VPC)
992+
return {VPC};
993+
return {};
994+
}
995+
996+
VPValue *X, *X1, *Y, *Z;
997+
LLVMContext &Ctx = TypeInfo.getContext();
998+
999+
// (X || !X) -> true.
1000+
if (match(&R, m_c_BinaryOr(m_VPValue(X), m_Not(m_VPValue(X1)))) && X == X1) {
1001+
VPValue *VPV = Plan.getOrAddLiveIn(ConstantInt::getTrue(Ctx));
1002+
R.getVPSingleValue()->replaceAllUsesWith(VPV);
1003+
return {};
1004+
}
1005+
1006+
// (X || true) -> true.
1007+
if (match(&R, m_c_BinaryOr(m_VPValue(X), m_True()))) {
1008+
VPValue *VPV = Plan.getOrAddLiveIn(ConstantInt::getTrue(Ctx));
1009+
R.getVPSingleValue()->replaceAllUsesWith(VPV);
1010+
return {};
9901011
}
9911012

992-
// Simplify (X && Y) || (X && !Y) -> X.
993-
// TODO: Split up into simpler, modular combines: (X && Y) || (X && Z) into X
994-
// && (Y || Z) and (X || !X) into true. This requires queuing newly created
995-
// recipes to be visited during simplification.
996-
VPValue *X, *Y, *X1, *Y1;
997-
if (match(&R,
998-
m_c_BinaryOr(m_LogicalAnd(m_VPValue(X), m_VPValue(Y)),
999-
m_LogicalAnd(m_VPValue(X1), m_Not(m_VPValue(Y1))))) &&
1000-
X == X1 && Y == Y1) {
1013+
// (X || false) -> X.
1014+
if (match(&R, m_c_BinaryOr(m_VPValue(X), m_False()))) {
10011015
R.getVPSingleValue()->replaceAllUsesWith(X);
1002-
return nullptr;
1016+
return {};
10031017
}
10041018

1005-
if (match(&R, m_c_Mul(m_VPValue(A), m_SpecificInt(1))))
1006-
R.getVPSingleValue()->replaceAllUsesWith(A);
1007-
return nullptr;
1019+
// (X && !X) -> false.
1020+
if (match(&R, m_LogicalAnd(m_VPValue(X), m_Not(m_VPValue(X1)))) && X == X1) {
1021+
VPValue *VPV = Plan.getOrAddLiveIn(ConstantInt::getFalse(Ctx));
1022+
R.getVPSingleValue()->replaceAllUsesWith(VPV);
1023+
return {};
1024+
}
1025+
1026+
// (X && true) -> X.
1027+
if (match(&R, m_LogicalAnd(m_VPValue(X), m_True()))) {
1028+
R.getVPSingleValue()->replaceAllUsesWith(X);
1029+
return {};
1030+
}
1031+
1032+
// (X && false) -> false.
1033+
if (match(&R, m_LogicalAnd(m_VPValue(X), m_False()))) {
1034+
VPValue *VPV = Plan.getOrAddLiveIn(ConstantInt::getFalse(Ctx));
1035+
R.getVPSingleValue()->replaceAllUsesWith(VPV);
1036+
return {};
1037+
}
1038+
1039+
// (X * 1) -> X.
1040+
if (match(&R, m_c_Mul(m_VPValue(X), m_SpecificInt(1)))) {
1041+
R.getVPSingleValue()->replaceAllUsesWith(X);
1042+
return {};
1043+
}
1044+
1045+
// (X && Y) || (X && Z) -> X && (Y || Z).
1046+
if (match(&R, m_BinaryOr(m_LogicalAnd(m_VPValue(X), m_VPValue(Y)),
1047+
m_LogicalAnd(m_VPValue(X1), m_VPValue(Z)))) &&
1048+
X == X1) {
1049+
VPBuilder Builder(&R);
1050+
VPInstruction *YorZ = Builder.createOr(Y, Z, R.getDebugLoc());
1051+
VPInstruction *VPI = Builder.createLogicalAnd(X, YorZ, R.getDebugLoc());
1052+
R.getVPSingleValue()->replaceAllUsesWith(VPI);
1053+
// Order of simplification matters: simplify sub-recipes before root
1054+
// recipes.
1055+
return {YorZ, VPI};
1056+
}
1057+
1058+
return {};
10081059
}
10091060

10101061
/// Try to simplify the recipes in \p Plan.
@@ -1013,10 +1064,14 @@ static void simplifyRecipes(VPlan &Plan, LLVMContext &Ctx) {
10131064
Plan.getEntry());
10141065
VPTypeAnalysis TypeInfo(Plan.getCanonicalIV()->getScalarType(), Ctx);
10151066
for (VPBasicBlock *VPBB : VPBlockUtils::blocksOnly<VPBasicBlock>(RPOT)) {
1067+
std::deque<VPRecipeBase *> Worklist;
10161068
for (auto &R : make_early_inc_range(*VPBB)) {
1017-
VPRecipeBase *NewR = simplifyRecipe(R, TypeInfo);
1018-
while (NewR)
1019-
NewR = simplifyRecipe(*NewR, TypeInfo);
1069+
Worklist.emplace_front(&R);
1070+
while (!Worklist.empty()) {
1071+
VPRecipeBase *R = Worklist.front();
1072+
Worklist.pop_front();
1073+
append_range(Worklist, simplifyRecipe(*R, TypeInfo, Plan));
1074+
}
10201075
}
10211076
}
10221077
}

0 commit comments

Comments
 (0)