Skip to content

Commit 5fe981e

Browse files
committed
[VPlan] Remove getNumUsers(), replace with targeted helpers.
Most users of getNumUsers() only care about 3 case: * no users * one (unique) user * or more than one (unique) user Instead of providing getNumUsers, provide helpers that accurately check for the 3 cases above, handling duplicates.
1 parent 8ae3aea commit 5fe981e

File tree

11 files changed

+63
-70
lines changed

11 files changed

+63
-70
lines changed

llvm/lib/Transforms/Vectorize/LoopVectorize.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4174,7 +4174,7 @@ VectorizationFactor LoopVectorizationPlanner::selectVectorizationFactor() {
41744174
// divisors.
41754175
case Instruction::Select: {
41764176
VPValue *VPV = VPI->getVPSingleValue();
4177-
if (VPV->getNumUsers() == 1) {
4177+
if (VPV->hasOneUser()) {
41784178
if (auto *WR = dyn_cast<VPWidenRecipe>(*VPV->user_begin())) {
41794179
switch (WR->getOpcode()) {
41804180
case Instruction::UDiv:

llvm/lib/Transforms/Vectorize/VPlan.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1066,25 +1066,25 @@ const VPRegionBlock *VPlan::getVectorLoopRegion() const {
10661066
void VPlan::printLiveIns(raw_ostream &O) const {
10671067
VPSlotTracker SlotTracker(this);
10681068

1069-
if (VF.getNumUsers() > 0) {
1069+
if (VF.hasUsers()) {
10701070
O << "\nLive-in ";
10711071
VF.printAsOperand(O, SlotTracker);
10721072
O << " = VF";
10731073
}
10741074

1075-
if (VFxUF.getNumUsers() > 0) {
1075+
if (VFxUF.hasUsers()) {
10761076
O << "\nLive-in ";
10771077
VFxUF.printAsOperand(O, SlotTracker);
10781078
O << " = VF * UF";
10791079
}
10801080

1081-
if (VectorTripCount.getNumUsers() > 0) {
1081+
if (VectorTripCount.hasUsers()) {
10821082
O << "\nLive-in ";
10831083
VectorTripCount.printAsOperand(O, SlotTracker);
10841084
O << " = vector-trip-count";
10851085
}
10861086

1087-
if (BackedgeTakenCount && BackedgeTakenCount->getNumUsers()) {
1087+
if (BackedgeTakenCount && BackedgeTakenCount->hasUsers()) {
10881088
O << "\nLive-in ";
10891089
BackedgeTakenCount->printAsOperand(O, SlotTracker);
10901090
O << " = backedge-taken count";
@@ -1502,9 +1502,9 @@ void VPSlotTracker::assignName(const VPValue *V) {
15021502
}
15031503

15041504
void VPSlotTracker::assignNames(const VPlan &Plan) {
1505-
if (Plan.VF.getNumUsers() > 0)
1505+
if (Plan.VF.hasUsers())
15061506
assignName(&Plan.VF);
1507-
if (Plan.VFxUF.getNumUsers() > 0)
1507+
if (Plan.VFxUF.hasUsers())
15081508
assignName(&Plan.VFxUF);
15091509
assignName(&Plan.VectorTripCount);
15101510
if (Plan.BackedgeTakenCount)

llvm/lib/Transforms/Vectorize/VPlan.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4218,7 +4218,7 @@ class VPlan {
42184218
/// Resets the trip count for the VPlan. The caller must make sure all uses of
42194219
/// the original trip count have been replaced.
42204220
void resetTripCount(VPValue *NewTripCount) {
4221-
assert(TripCount && NewTripCount && TripCount->getNumUsers() == 0 &&
4221+
assert(TripCount && NewTripCount && TripCount->hasNoUsers() &&
42224222
"TripCount must be set when resetting");
42234223
TripCount = NewTripCount;
42244224
}

llvm/lib/Transforms/Vectorize/VPlanConstruction.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -888,7 +888,7 @@ bool VPlanTransforms::handleMaxMinNumReductions(VPlan &Plan) {
888888
if (VecV == RdxResult)
889889
continue;
890890
if (auto *DerivedIV = dyn_cast<VPDerivedIVRecipe>(VecV)) {
891-
if (DerivedIV->getNumUsers() == 1 &&
891+
if (DerivedIV->hasOneUser() &&
892892
DerivedIV->getOperand(1) == &Plan.getVectorTripCount()) {
893893
auto *NewSel = Builder.createSelect(AnyNaN, Plan.getCanonicalIV(),
894894
&Plan.getVectorTripCount());

llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2285,7 +2285,7 @@ InstructionCost VPWidenCastRecipe::computeCost(ElementCount VF,
22852285
TTI::CastContextHint CCH = TTI::CastContextHint::None;
22862286
// For Trunc/FPTrunc, get the context from the only user.
22872287
if ((Opcode == Instruction::Trunc || Opcode == Instruction::FPTrunc) &&
2288-
!hasMoreThanOneUniqueUser() && getNumUsers() > 0) {
2288+
hasOneUser()) {
22892289
if (auto *StoreRecipe = dyn_cast<VPRecipeBase>(*user_begin()))
22902290
CCH = ComputeCCH(StoreRecipe);
22912291
}

llvm/lib/Transforms/Vectorize/VPlanSLP.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,8 +156,7 @@ bool VPlanSlp::areVectorizable(ArrayRef<VPValue *> Operands) const {
156156
return false;
157157
}
158158

159-
if (any_of(Operands,
160-
[](VPValue *Op) { return Op->hasMoreThanOneUniqueUser(); })) {
159+
if (any_of(Operands, [](VPValue *Op) { return !Op->hasNoOrOneUser(); })) {
161160
LLVM_DEBUG(dbgs() << "VPSLP: Some operands have multiple users.\n");
162161
return false;
163162
}

llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,7 @@ static bool mergeReplicateRegionsIntoSuccessors(VPlan &Plan) {
316316
});
317317

318318
// Remove phi recipes that are unused after merging the regions.
319-
if (Phi1ToMove.getVPSingleValue()->getNumUsers() == 0) {
319+
if (Phi1ToMove.getVPSingleValue()->hasNoUsers()) {
320320
Phi1ToMove.eraseFromParent();
321321
continue;
322322
}
@@ -363,7 +363,7 @@ static VPRegionBlock *createReplicateRegion(VPReplicateRecipe *PredRecipe,
363363
Plan.createVPBasicBlock(Twine(RegionName) + ".if", RecipeWithoutMask);
364364

365365
VPPredInstPHIRecipe *PHIRecipe = nullptr;
366-
if (PredRecipe->getNumUsers() != 0) {
366+
if (!PredRecipe->hasNoUsers()) {
367367
PHIRecipe = new VPPredInstPHIRecipe(RecipeWithoutMask,
368368
RecipeWithoutMask->getDebugLoc());
369369
PredRecipe->replaceAllUsesWith(PHIRecipe);
@@ -546,8 +546,7 @@ static bool isDeadRecipe(VPRecipeBase &R) {
546546
return false;
547547

548548
// Recipe is dead if no user keeps the recipe alive.
549-
return all_of(R.definedValues(),
550-
[](VPValue *V) { return V->getNumUsers() == 0; });
549+
return all_of(R.definedValues(), [](VPValue *V) { return V->hasNoUsers(); });
551550
}
552551

553552
void VPlanTransforms::removeDeadRecipes(VPlan &Plan) {
@@ -563,11 +562,11 @@ void VPlanTransforms::removeDeadRecipes(VPlan &Plan) {
563562

564563
// Check if R is a dead VPPhi <-> update cycle and remove it.
565564
auto *PhiR = dyn_cast<VPPhi>(&R);
566-
if (!PhiR || PhiR->getNumOperands() != 2 || PhiR->getNumUsers() != 1)
565+
if (!PhiR || PhiR->getNumOperands() != 2 || !PhiR->hasOneUser())
567566
continue;
568567
VPValue *Incoming = PhiR->getOperand(1);
569568
if (*PhiR->user_begin() != Incoming->getDefiningRecipe() ||
570-
Incoming->getNumUsers() != 1)
569+
!Incoming->hasOneUser())
571570
continue;
572571
PhiR->replaceAllUsesWith(PhiR->getOperand(0));
573572
PhiR->eraseFromParent();
@@ -658,7 +657,7 @@ static void legalizeAndOptimizeInductions(VPlan &Plan) {
658657
auto *RepR = dyn_cast<VPReplicateRecipe>(U);
659658
// Skip recipes that shouldn't be narrowed.
660659
if (!Def || !isa<VPReplicateRecipe, VPWidenRecipe>(Def) ||
661-
Def->getNumUsers() == 0 || !Def->getUnderlyingValue() ||
660+
Def->hasNoUsers() || !Def->getUnderlyingValue() ||
662661
(RepR && (RepR->isSingleScalar() || RepR->isPredicated())))
663662
continue;
664663

@@ -1103,8 +1102,8 @@ static void simplifyRecipe(VPRecipeBase &R, VPTypeAnalysis &TypeInfo) {
11031102
m_LogicalAnd(m_Deferred(X), m_VPValue(Z)))) &&
11041103
// Simplify only if one of the operands has one use to avoid creating an
11051104
// extra recipe.
1106-
(!Def->getOperand(0)->hasMoreThanOneUniqueUser() ||
1107-
!Def->getOperand(1)->hasMoreThanOneUniqueUser()))
1105+
(Def->getOperand(0)->hasNoOrOneUser() ||
1106+
Def->getOperand(1)->hasNoOrOneUser()))
11081107
return Def->replaceAllUsesWith(
11091108
Builder.createLogicalAnd(X, Builder.createOr(Y, Z)));
11101109

@@ -1130,7 +1129,7 @@ static void simplifyRecipe(VPRecipeBase &R, VPTypeAnalysis &TypeInfo) {
11301129
// further.
11311130
if (match(Def, m_LogicalAnd(m_LogicalAnd(m_VPValue(X), m_VPValue(Y)),
11321131
m_VPValue(Z))) &&
1133-
X->hasMoreThanOneUniqueUser())
1132+
!X->hasNoOrOneUser())
11341133
return Def->replaceAllUsesWith(
11351134
Builder.createLogicalAnd(X, Builder.createLogicalAnd(Y, Z)));
11361135

@@ -1383,7 +1382,7 @@ static void simplifyBlends(VPlan &Plan) {
13831382
// TODO: Find the most expensive mask that can be deadcoded, or a mask
13841383
// that's used by multiple blends where it can be removed from them all.
13851384
VPValue *Mask = Blend->getMask(I);
1386-
if (Mask->getNumUsers() == 1 && !match(Mask, m_False())) {
1385+
if (Mask->hasOneUser() && !match(Mask, m_False())) {
13871386
StartIndex = I;
13881387
break;
13891388
}
@@ -1419,7 +1418,7 @@ static void simplifyBlends(VPlan &Plan) {
14191418
NewBlend->setOperand(0, Inc1);
14201419
NewBlend->setOperand(1, Inc0);
14211420
NewBlend->setOperand(2, NewMask);
1422-
if (OldMask->getNumUsers() == 0)
1421+
if (OldMask->hasNoUsers())
14231422
cast<VPInstruction>(OldMask)->eraseFromParent();
14241423
}
14251424
}
@@ -1466,8 +1465,7 @@ static bool optimizeVectorInductionWidthForTCAndVFUF(VPlan &Plan,
14661465
// Currently only handle canonical IVs as it is trivial to replace the start
14671466
// and stop values, and we currently only perform the optimization when the
14681467
// IV has a single use.
1469-
if (!WideIV || !WideIV->isCanonical() ||
1470-
WideIV->hasMoreThanOneUniqueUser() ||
1468+
if (!WideIV || !WideIV->isCanonical() || !WideIV->hasNoOrOneUser() ||
14711469
NewIVTy == WideIV->getScalarType())
14721470
continue;
14731471

@@ -2611,7 +2609,7 @@ static void transformRecipestoEVLRecipes(VPlan &Plan, VPValue &EVL) {
26112609
ToErase.push_back(CurRecipe);
26122610
}
26132611
// Remove dead EVL mask.
2614-
if (EVLMask->getNumUsers() == 0)
2612+
if (EVLMask->hasNoUsers())
26152613
ToErase.push_back(EVLMask->getDefiningRecipe());
26162614

26172615
for (VPRecipeBase *R : reverse(ToErase)) {
@@ -3590,7 +3588,7 @@ void VPlanTransforms::materializeBroadcasts(VPlan &Plan) {
35903588
#endif
35913589

35923590
SmallVector<VPValue *> VPValues;
3593-
if (Plan.getOrCreateBackedgeTakenCount()->getNumUsers() > 0)
3591+
if (Plan.getOrCreateBackedgeTakenCount()->hasUsers())
35943592
VPValues.push_back(Plan.getOrCreateBackedgeTakenCount());
35953593
append_range(VPValues, Plan.getLiveIns());
35963594
for (VPRecipeBase &R : *Plan.getEntry())
@@ -3659,7 +3657,7 @@ void VPlanTransforms::materializeConstantVectorTripCount(
36593657
void VPlanTransforms::materializeBackedgeTakenCount(VPlan &Plan,
36603658
VPBasicBlock *VectorPH) {
36613659
VPValue *BTC = Plan.getOrCreateBackedgeTakenCount();
3662-
if (BTC->getNumUsers() == 0)
3660+
if (BTC->hasNoUsers())
36633661
return;
36643662

36653663
VPBuilder Builder(VectorPH, VectorPH->begin());
@@ -3725,7 +3723,7 @@ void VPlanTransforms::materializeVectorTripCount(VPlan &Plan,
37253723
assert(VectorTC.isLiveIn() && "vector-trip-count must be a live-in");
37263724
// There's nothing to do if there are no users of the vector trip count or its
37273725
// IR value has already been set.
3728-
if (VectorTC.getNumUsers() == 0 || VectorTC.getLiveInIRValue())
3726+
if (VectorTC.hasNoUsers() || VectorTC.getLiveInIRValue())
37293727
return;
37303728

37313729
VPValue *TC = Plan.getTripCount();
@@ -3790,7 +3788,7 @@ void VPlanTransforms::materializeVFAndVFxUF(VPlan &Plan, VPBasicBlock *VectorPH,
37903788

37913789
// If there are no users of the runtime VF, compute VFxUF by constant folding
37923790
// the multiplication of VF and UF.
3793-
if (VF.getNumUsers() == 0) {
3791+
if (VF.hasNoUsers()) {
37943792
VPValue *RuntimeVFxUF =
37953793
Builder.createElementCount(TCTy, VFEC * Plan.getUF());
37963794
VFxUF.replaceAllUsesWith(RuntimeVFxUF);

llvm/lib/Transforms/Vectorize/VPlanUnroll.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -535,7 +535,7 @@ void VPlanTransforms::replicateByVF(VPlan &Plan, ElementCount VF) {
535535
continue;
536536

537537
VPBuilder Builder(RepR);
538-
if (RepR->getNumUsers() == 0) {
538+
if (RepR->hasNoUsers()) {
539539
if (isa<StoreInst>(RepR->getUnderlyingInstr()) &&
540540
vputils::isSingleScalar(RepR->getOperand(1))) {
541541
// Stores to invariant addresses need to store the last lane only.

llvm/lib/Transforms/Vectorize/VPlanValue.h

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ class LLVM_ABI_FOR_TEST VPValue {
5656

5757
SmallVector<VPUser *, 1> Users;
5858

59+
unsigned getNumUsers() const { return Users.size(); }
60+
5961
protected:
6062
// Hold the underlying Value, if any, attached to this VPValue.
6163
Value *UnderlyingVal;
@@ -110,7 +112,6 @@ class LLVM_ABI_FOR_TEST VPValue {
110112
void dump() const;
111113
#endif
112114

113-
unsigned getNumUsers() const { return Users.size(); }
114115
void addUser(VPUser &User) { Users.push_back(&User); }
115116

116117
/// Remove a single \p User from the list of users.
@@ -136,17 +137,12 @@ class LLVM_ABI_FOR_TEST VPValue {
136137
return const_user_range(user_begin(), user_end());
137138
}
138139

140+
bool hasUsers() const { return !Users.empty(); }
141+
bool hasNoUsers() const { return !hasUsers(); }
142+
bool hasOneUser() const { return !hasNoUsers() && all_equal(Users); }
143+
139144
/// Returns true if the value has more than one unique user.
140-
bool hasMoreThanOneUniqueUser() const {
141-
if (getNumUsers() == 0)
142-
return false;
143-
144-
// Check if all users match the first user.
145-
auto Current = std::next(user_begin());
146-
while (Current != user_end() && *user_begin() == *Current)
147-
Current++;
148-
return Current != user_end();
149-
}
145+
bool hasNoOrOneUser() const { return hasNoUsers() || hasOneUser(); }
150146

151147
void replaceAllUsesWith(VPValue *New);
152148

llvm/lib/Transforms/Vectorize/VPlanVerifier.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -198,8 +198,8 @@ bool VPlanVerifier::verifyEVLRecipe(const VPInstruction &EVL) const {
198198
}
199199
// EVLIVIncrement is only used by EVLIV & BranchOnCount.
200200
// Having more than two users is unexpected.
201-
if ((I->getNumUsers() != 1) &&
202-
(I->getNumUsers() != 2 || none_of(I->users(), [&I](VPUser *U) {
201+
if ((size(I->users()) != 1) &&
202+
(size(I->users()) != 2 || none_of(I->users(), [&I](VPUser *U) {
203203
using namespace llvm::VPlanPatternMatch;
204204
return match(U, m_BranchOnCount(m_Specific(I), m_VPValue()));
205205
}))) {

0 commit comments

Comments
 (0)