Skip to content

Commit 0cddbac

Browse files
committed
!fixup replace MultiUse kinds with boolean flag
1 parent 844c2c2 commit 0cddbac

File tree

9 files changed

+70
-78
lines changed

9 files changed

+70
-78
lines changed

llvm/include/llvm/Analysis/IVDescriptors.h

Lines changed: 14 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,9 @@ enum class RecurKind {
4242
And, ///< Bitwise or logical AND of integers.
4343
Xor, ///< Bitwise or logical XOR of integers.
4444
SMin, ///< Signed integer min implemented in terms of select(cmp()).
45-
SMinMultiUse, ///< Signed integer min implemented in terms of select(cmp()).
4645
SMax, ///< Signed integer max implemented in terms of select(cmp()).
47-
SMaxMultiUse, ///< Signed integer max implemented in terms of select(cmp()).
4846
UMin, ///< Unsigned integer min implemented in terms of select(cmp()).
49-
UMinMultiUse, ///< Unsigned integer min implemented in terms of select(cmp()).
5047
UMax, ///< Unsigned integer max implemented in terms of select(cmp()).
51-
UMaxMultiUse, ///< Unsigned integer max implemented in terms of select(cmp()).
5248
FAdd, ///< Sum of floats.
5349
FMul, ///< Product of floats.
5450
FMin, ///< FP min implemented in terms of select(cmp()).
@@ -99,12 +95,15 @@ class RecurrenceDescriptor {
9995
RecurKind K, FastMathFlags FMF, Instruction *ExactFP,
10096
Type *RT, bool Signed, bool Ordered,
10197
SmallPtrSetImpl<Instruction *> &CI,
102-
unsigned MinWidthCastToRecurTy)
98+
unsigned MinWidthCastToRecurTy, bool PhiMultiUse = false)
10399
: IntermediateStore(Store), StartValue(Start), LoopExitInstr(Exit),
104100
Kind(K), FMF(FMF), ExactFPMathInst(ExactFP), RecurrenceType(RT),
105-
IsSigned(Signed), IsOrdered(Ordered),
101+
IsSigned(Signed), IsOrdered(Ordered), IsPhiMultiUse(PhiMultiUse),
106102
MinWidthCastToRecurrenceType(MinWidthCastToRecurTy) {
107103
CastInsts.insert_range(CI);
104+
assert(
105+
(!PhiMultiUse || isMinMaxRecurrenceKind(K)) &&
106+
"Only min/max recurrences are allowed to have multiple uses currently");
108107
}
109108

110109
/// This POD struct holds information about a potential recurrence operation.
@@ -251,26 +250,8 @@ class RecurrenceDescriptor {
251250

252251
/// Returns true if the recurrence kind is an integer min/max kind.
253252
static bool isIntMinMaxRecurrenceKind(RecurKind Kind) {
254-
return Kind == RecurKind::UMin || Kind == RecurKind::UMinMultiUse ||
255-
Kind == RecurKind::UMax || Kind == RecurKind::UMaxMultiUse ||
256-
Kind == RecurKind::SMin || Kind == RecurKind::SMinMultiUse ||
257-
Kind == RecurKind::SMax || Kind == RecurKind::SMaxMultiUse;
258-
}
259-
260-
static RecurKind convertFromMultiUseKind(RecurKind Kind) {
261-
switch (Kind) {
262-
case RecurKind::UMaxMultiUse:
263-
return RecurKind::UMax;
264-
case RecurKind::UMinMultiUse:
265-
return RecurKind::UMin;
266-
case RecurKind::SMinMultiUse:
267-
return RecurKind::SMin;
268-
case RecurKind::SMaxMultiUse:
269-
return RecurKind::SMax;
270-
default:
271-
return Kind;
272-
}
273-
llvm_unreachable("all cases must be handled above");
253+
return Kind == RecurKind::UMin || Kind == RecurKind::UMax ||
254+
Kind == RecurKind::SMin || Kind == RecurKind::SMax;
274255
}
275256

276257
/// Returns true if the recurrence kind is a floating-point minnum/maxnum
@@ -361,6 +342,10 @@ class RecurrenceDescriptor {
361342
/// Expose an ordered FP reduction to the instance users.
362343
bool isOrdered() const { return IsOrdered; }
363344

345+
/// Returns true if the reduction PHI has multiple in-loop users. This is
346+
/// relevant for min/max reductions that are part of a FindLastIV pattern.
347+
bool isPhiMultiUse() const { return IsPhiMultiUse; }
348+
364349
/// Attempts to find a chain of operations from Phi to LoopExitInst that can
365350
/// be treated as a set of reductions instructions for in-loop reductions.
366351
LLVM_ABI SmallVector<Instruction *, 4> getReductionOpChain(PHINode *Phi,
@@ -398,6 +383,9 @@ class RecurrenceDescriptor {
398383
// Currently only a non-reassociative FAdd can be considered in-order,
399384
// if it is also the only FAdd in the PHI's use chain.
400385
bool IsOrdered = false;
386+
// True if the reduction PHI has multiple in-loop users. This is relevant
387+
// for min/max reductions that are part of a FindLastIV pattern.
388+
bool IsPhiMultiUse = false;
401389
// Instructions used for type-promoting the recurrence.
402390
SmallPtrSet<Instruction *, 8> CastInsts;
403391
// The minimum width used by the recurrence.

llvm/lib/Analysis/IVDescriptors.cpp

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -227,25 +227,24 @@ getMultiUseMinMax(PHINode *Phi, RecurKind Kind, Loop *TheLoop) {
227227

228228
Value *A, *B;
229229
if (match(Inc, m_OneUse(m_UMin(m_Value(A), m_Value(B)))))
230-
RK = RecurKind::UMinMultiUse;
230+
RK = RecurKind::UMin;
231231
else if (match(Inc, m_OneUse(m_UMax(m_Value(A), m_Value(B)))))
232-
RK = RecurKind::UMaxMultiUse;
232+
RK = RecurKind::UMax;
233233
else if (match(Inc, m_OneUse(m_SMax(m_Value(A), m_Value(B)))))
234-
RK = RecurKind::SMaxMultiUse;
234+
RK = RecurKind::SMax;
235235
else if (match(Inc, m_OneUse(m_SMin(m_Value(A), m_Value(B)))))
236-
RK = RecurKind::SMinMultiUse;
236+
RK = RecurKind::SMin;
237237
else
238238
return std::nullopt;
239239

240-
if (RecurrenceDescriptor::convertFromMultiUseKind(RK) != Kind || A == B ||
241-
(A != Phi && B != Phi))
240+
if (A == B || (A != Phi && B != Phi))
242241
return std::nullopt;
243242

244243
SmallPtrSet<Instruction *, 4> CastInsts;
245244
Value *RdxStart = Phi->getIncomingValueForBlock(TheLoop->getLoopPreheader());
246245
RecurrenceDescriptor RD(RdxStart, nullptr, nullptr, RK, FastMathFlags(),
247-
nullptr, Phi->getType(), false, false, CastInsts,
248-
-1U);
246+
nullptr, Phi->getType(), false, false, CastInsts, -1U,
247+
true);
249248
return {RD};
250249
}
251250

llvm/lib/Transforms/Utils/LoopUnroll.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1217,7 +1217,9 @@ llvm::canParallelizeReductionWhenUnrolling(PHINode &Phi, Loop *L,
12171217
RecurrenceDescriptor RdxDesc;
12181218
if (!RecurrenceDescriptor::isReductionPHI(&Phi, L, RdxDesc,
12191219
/*DemandedBits=*/nullptr,
1220-
/*AC=*/nullptr, /*DT=*/nullptr, SE))
1220+
/*AC=*/nullptr, /*DT=*/nullptr,
1221+
SE) ||
1222+
RdxDesc.isPhiMultiUse())
12211223
return std::nullopt;
12221224
RecurKind RK = RdxDesc.getRecurrenceKind();
12231225
// Skip unsupported reductions.

llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -878,6 +878,11 @@ bool LoopVectorizationLegality::canVectorizeInstr(Instruction &I) {
878878
Requirements->addExactFPMathInst(RedDes.getExactFPMathInst());
879879
AllowedExit.insert(RedDes.getLoopExitInstr());
880880
Reductions[Phi] = RedDes;
881+
assert((!RedDes.isPhiMultiUse() ||
882+
RecurrenceDescriptor::isMinMaxRecurrenceKind(
883+
RedDes.getRecurrenceKind())) &&
884+
"Only min/max recurrences are allowed to have multiple uses "
885+
"currently");
881886
return true;
882887
}
883888

llvm/lib/Transforms/Vectorize/LoopVectorize.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6515,6 +6515,11 @@ void LoopVectorizationCostModel::collectInLoopReductions() {
65156515
PHINode *Phi = Reduction.first;
65166516
const RecurrenceDescriptor &RdxDesc = Reduction.second;
65176517

6518+
// Multi-use reductions (e.g., used in FindLastIV patterns) are handled
6519+
// separately and should not be considered for in-loop reductions.
6520+
if (RdxDesc.isPhiMultiUse())
6521+
continue;
6522+
65186523
// We don't collect reductions that are type promoted (yet).
65196524
if (RdxDesc.getRecurrenceType() != Phi->getType())
65206525
continue;
@@ -8072,7 +8077,8 @@ VPRecipeBase *VPRecipeBuilder::tryToCreateWidenRecipe(VPSingleDefRecipe *R,
80728077
getScalingForReduction(RdxDesc.getLoopExitInstr()).value_or(1);
80738078
PhiRecipe = new VPReductionPHIRecipe(
80748079
Phi, RdxDesc.getRecurrenceKind(), *StartV, CM.isInLoopReduction(Phi),
8075-
CM.useOrderedReductions(RdxDesc), ScaleFactor);
8080+
CM.useOrderedReductions(RdxDesc), ScaleFactor,
8081+
RdxDesc.isPhiMultiUse());
80768082
} else if (Legal->isFixedOrderRecurrence(Phi)) {
80778083
// TODO: Currently fixed-order recurrences are modeled as chains of
80788084
// first-order recurrences. If there are no users of the intermediate
@@ -8429,8 +8435,8 @@ VPlanPtr LoopVectorizationPlanner::tryToBuildVPlanWithVPRecipes(
84298435
// Adjust the recipes for any inloop reductions.
84308436
adjustRecipesForReductions(Plan, RecipeBuilder, Range.Start);
84318437

8432-
// Try to convert remaining VPWidenPHIRecipes to reduction recipes.
8433-
if (!VPlanTransforms::runPass(VPlanTransforms::legalizeUnclassifiedPhis,
8438+
// Try to legalize reductions with multiple in-loop uses.
8439+
if (!VPlanTransforms::runPass(VPlanTransforms::legalizeMultiUseReductions,
84348440
*Plan))
84358441
return nullptr;
84368442
// Apply mandatory transformation to handle FP maxnum/minnum reduction with

llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25091,10 +25091,6 @@ class HorizontalReduction {
2509125091
case RecurKind::FMinNum:
2509225092
case RecurKind::FMaximumNum:
2509325093
case RecurKind::FMinimumNum:
25094-
case RecurKind::UMaxMultiUse:
25095-
case RecurKind::UMinMultiUse:
25096-
case RecurKind::SMinMultiUse:
25097-
case RecurKind::SMaxMultiUse:
2509825094
case RecurKind::None:
2509925095
llvm_unreachable("Unexpected reduction kind for repeated scalar.");
2510025096
}
@@ -25236,10 +25232,6 @@ class HorizontalReduction {
2523625232
case RecurKind::FMinNum:
2523725233
case RecurKind::FMaximumNum:
2523825234
case RecurKind::FMinimumNum:
25239-
case RecurKind::UMaxMultiUse:
25240-
case RecurKind::UMinMultiUse:
25241-
case RecurKind::SMinMultiUse:
25242-
case RecurKind::SMaxMultiUse:
2524325235
case RecurKind::None:
2524425236
llvm_unreachable("Unexpected reduction kind for repeated scalar.");
2524525237
}
@@ -25346,10 +25338,6 @@ class HorizontalReduction {
2534625338
case RecurKind::FMinNum:
2534725339
case RecurKind::FMaximumNum:
2534825340
case RecurKind::FMinimumNum:
25349-
case RecurKind::UMaxMultiUse:
25350-
case RecurKind::UMinMultiUse:
25351-
case RecurKind::SMinMultiUse:
25352-
case RecurKind::SMaxMultiUse:
2535325341
case RecurKind::None:
2535425342
llvm_unreachable("Unexpected reduction kind for reused scalars.");
2535525343
}

llvm/lib/Transforms/Vectorize/VPlan.h

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2346,6 +2346,10 @@ class VPReductionPHIRecipe : public VPHeaderPHIRecipe,
23462346
/// The phi is part of an ordered reduction. Requires IsInLoop to be true.
23472347
bool IsOrdered;
23482348

2349+
/// The phi is part of a multi-use reduction (e.g., used in FindLastIV
2350+
/// patterns).
2351+
bool IsPhiMultiUse;
2352+
23492353
/// When expanding the reduction PHI, the plan's VF element count is divided
23502354
/// by this factor to form the reduction phi's VF.
23512355
unsigned VFScaleFactor = 1;
@@ -2354,9 +2358,10 @@ class VPReductionPHIRecipe : public VPHeaderPHIRecipe,
23542358
/// Create a new VPReductionPHIRecipe for the reduction \p Phi.
23552359
VPReductionPHIRecipe(PHINode *Phi, RecurKind Kind, VPValue &Start,
23562360
bool IsInLoop = false, bool IsOrdered = false,
2357-
unsigned VFScaleFactor = 1)
2361+
unsigned VFScaleFactor = 1, bool IsPhiMultiUse = false)
23582362
: VPHeaderPHIRecipe(VPDef::VPReductionPHISC, Phi, &Start), Kind(Kind),
2359-
IsInLoop(IsInLoop), IsOrdered(IsOrdered), VFScaleFactor(VFScaleFactor) {
2363+
IsInLoop(IsInLoop), IsOrdered(IsOrdered), IsPhiMultiUse(IsPhiMultiUse),
2364+
VFScaleFactor(VFScaleFactor) {
23602365
assert((!IsOrdered || IsInLoop) && "IsOrdered requires IsInLoop");
23612366
}
23622367

@@ -2365,7 +2370,7 @@ class VPReductionPHIRecipe : public VPHeaderPHIRecipe,
23652370
VPReductionPHIRecipe *clone() override {
23662371
auto *R = new VPReductionPHIRecipe(
23672372
dyn_cast_or_null<PHINode>(getUnderlyingValue()), getRecurrenceKind(),
2368-
*getOperand(0), IsInLoop, IsOrdered, VFScaleFactor);
2373+
*getOperand(0), IsInLoop, IsOrdered, VFScaleFactor, IsPhiMultiUse);
23692374
R->addOperand(getBackedgeValue());
23702375
return R;
23712376
}
@@ -2398,6 +2403,9 @@ class VPReductionPHIRecipe : public VPHeaderPHIRecipe,
23982403
/// Returns true, if the phi is part of an in-loop reduction.
23992404
bool isInLoop() const { return IsInLoop; }
24002405

2406+
/// Returns true, if the phi is part of a multi-use reduction.
2407+
bool isPhiMultiUse() const { return IsPhiMultiUse; }
2408+
24012409
/// Returns true if the recipe only uses the first lane of operand \p Op.
24022410
bool onlyFirstLaneUsed(const VPValue *Op) const override {
24032411
assert(is_contained(operands(), Op) &&

llvm/lib/Transforms/Vectorize/VPlanConstruction.cpp

Lines changed: 17 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -950,23 +950,25 @@ bool VPlanTransforms::handleMaxMinNumReductions(VPlan &Plan) {
950950
return true;
951951
}
952952

953-
bool VPlanTransforms::legalizeUnclassifiedPhis(VPlan &Plan) {
954-
using namespace VPlanPatternMatch;
953+
bool VPlanTransforms::legalizeMultiUseReductions(VPlan &Plan) {
955954
for (auto &PhiR : make_early_inc_range(
956955
Plan.getVectorLoopRegion()->getEntryBasicBlock()->phis())) {
957956
auto *MinMaxPhiR = dyn_cast<VPReductionPHIRecipe>(&PhiR);
958-
if (!MinMaxPhiR || !RecurrenceDescriptor::isIntMinMaxRecurrenceKind(
959-
MinMaxPhiR->getRecurrenceKind()))
957+
if (!MinMaxPhiR)
960958
continue;
961959

962-
RecurKind RdxKind = RecurrenceDescriptor::convertFromMultiUseKind(
963-
MinMaxPhiR->getRecurrenceKind());
964-
if (RdxKind == MinMaxPhiR->getRecurrenceKind())
960+
RecurKind RdxKind = MinMaxPhiR->getRecurrenceKind();
961+
// TODO: check for multi-uses in VPlan directly.
962+
if (!RecurrenceDescriptor::isIntMinMaxRecurrenceKind(RdxKind) ||
963+
!MinMaxPhiR->isPhiMultiUse())
965964
continue;
966965

967966
// One user of MinMaxPhiR is MinMaxOp, the other users must be a compare
968967
// that's part of a FindLastIV chain.
969-
auto *MinMaxOp = cast<VPRecipeWithIRFlags>(MinMaxPhiR->getBackedgeValue());
968+
auto *MinMaxOp =
969+
dyn_cast<VPRecipeWithIRFlags>(MinMaxPhiR->getBackedgeValue());
970+
if (!MinMaxOp)
971+
return false;
970972
auto MinMaxUsers = to_vector(MinMaxPhiR->users());
971973
auto *Cmp = dyn_cast<VPRecipeWithIRFlags>(
972974
MinMaxUsers[0] == MinMaxOp ? MinMaxUsers[1] : MinMaxUsers[0]);
@@ -1019,28 +1021,22 @@ bool VPlanTransforms::legalizeUnclassifiedPhis(VPlan &Plan) {
10191021
assert(!FindIVPhiR->isInLoop() && !FindIVPhiR->isOrdered() &&
10201022
"cannot handle inloop/ordered reductions yet");
10211023

1022-
auto NewPhiR = new VPReductionPHIRecipe(
1023-
cast<PHINode>(MinMaxPhiR->getUnderlyingInstr()), RdxKind,
1024-
*MinMaxPhiR->getOperand(0), false, false, 1);
1025-
NewPhiR->insertBefore(MinMaxPhiR);
1026-
MinMaxPhiR->replaceAllUsesWith(NewPhiR);
1027-
NewPhiR->addOperand(MinMaxPhiR->getOperand(1));
1028-
MinMaxPhiR->eraseFromParent();
1029-
10301024
// The reduction using MinMaxPhiR needs adjusting to compute the correct
10311025
// result:
10321026
// 1. We need to find the last IV for which the condition based on the
10331027
// min/max recurrence is true,
10341028
// 2. Compare the partial min/max reduction result to its final value and,
10351029
// 3. Select the lanes of the partial FindLastIV reductions which
10361030
// correspond to the lanes matching the min/max reduction result.
1037-
VPInstruction *FindIVResult = cast<VPInstruction>(
1031+
VPInstruction *FindIVResult = dyn_cast<VPInstruction>(
10381032
*(Sel->user_begin() + (*Sel->user_begin() == FindIVPhiR ? 1 : 0)));
1033+
if (!FindIVResult)
1034+
return false;
10391035
VPBuilder B(FindIVResult);
1040-
VPInstruction *MinMaxResult =
1041-
B.createNaryOp(VPInstruction::ComputeReductionResult,
1042-
{NewPhiR, NewPhiR->getBackedgeValue()}, VPIRFlags(), {});
1043-
NewPhiR->getBackedgeValue()->replaceUsesWithIf(
1036+
VPInstruction *MinMaxResult = B.createNaryOp(
1037+
VPInstruction::ComputeReductionResult,
1038+
{MinMaxPhiR, MinMaxPhiR->getBackedgeValue()}, VPIRFlags(), {});
1039+
MinMaxPhiR->getBackedgeValue()->replaceUsesWithIf(
10441040
MinMaxResult, [](VPUser &U, unsigned) { return isa<VPPhi>(&U); });
10451041
auto *FinalMinMaxCmp = B.createICmp(
10461042
CmpInst::ICMP_EQ, MinMaxResult->getOperand(1), MinMaxResult);

llvm/lib/Transforms/Vectorize/VPlanTransforms.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -143,10 +143,10 @@ struct VPlanTransforms {
143143
GetIntOrFpInductionDescriptor,
144144
const TargetLibraryInfo &TLI);
145145

146-
/// Try to legalize unclassified phis by converting VPWidenPHIRecipes to
147-
/// min-max reductions used by FindLastIV reductions if possible. Returns
148-
/// false if the VPlan contains VPWidenPHIRecipes that cannot be legalized.
149-
static bool legalizeUnclassifiedPhis(VPlan &Plan);
146+
/// Try to legalize reductions with multiple in-loop uses. Currently only
147+
/// min/max reductions used by FindLastIV reductions are supported. Otherwise
148+
/// return false.
149+
static bool legalizeMultiUseReductions(VPlan &Plan);
150150

151151
/// Try to have all users of fixed-order recurrences appear after the recipe
152152
/// defining their previous value, by either sinking users or hoisting recipes

0 commit comments

Comments
 (0)