[llvm] [VPlan] Introduce VPValue::user_empty (NFC) (PR #203518)
Ramkumar Ramachandra via llvm-commits
llvm-commits at lists.llvm.org
Wed Jun 24 03:37:51 PDT 2026
https://github.com/artagnon updated https://github.com/llvm/llvm-project/pull/203518
>From 0b430179c9659e671175c62705498dab2e96b044 Mon Sep 17 00:00:00 2001
From: Ramkumar Ramachandra <artagnon at tenstorrent.com>
Date: Fri, 12 Jun 2026 13:28:12 +0100
Subject: [PATCH 1/2] [VPlan] Introduce VPValue::has[No]Users (NFC)
---
llvm/lib/Transforms/Vectorize/VPlan.cpp | 18 +++++++--------
llvm/lib/Transforms/Vectorize/VPlan.h | 2 +-
.../Transforms/Vectorize/VPlanAnalysis.cpp | 4 ++--
.../Vectorize/VPlanConstruction.cpp | 2 +-
.../Transforms/Vectorize/VPlanTransforms.cpp | 23 +++++++++----------
llvm/lib/Transforms/Vectorize/VPlanUnroll.cpp | 2 +-
llvm/lib/Transforms/Vectorize/VPlanValue.h | 6 +++--
7 files changed, 29 insertions(+), 28 deletions(-)
diff --git a/llvm/lib/Transforms/Vectorize/VPlan.cpp b/llvm/lib/Transforms/Vectorize/VPlan.cpp
index 83333aae39cf9..d5fc0778ce574 100644
--- a/llvm/lib/Transforms/Vectorize/VPlan.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlan.cpp
@@ -832,7 +832,7 @@ void VPRegionBlock::dissolveToCFGLoop() {
auto *Header = cast<VPBasicBlock>(getEntry());
auto *ExitingLatch = cast<VPBasicBlock>(getExiting());
auto *CanIV = getCanonicalIV();
- if (CanIV->getNumUsers() > 0) {
+ if (CanIV->hasUsers()) {
VPlan &Plan = *getPlan();
auto *Zero = Plan.getZero(CanIV->getType());
DebugLoc DL = CanIV->getDebugLoc();
@@ -1085,25 +1085,25 @@ bool VPlan::isOuterLoop() const {
void VPlan::printLiveIns(raw_ostream &O) const {
VPSlotTracker SlotTracker(this);
- if (VF.getNumUsers() > 0) {
+ if (VF.hasUsers()) {
O << "\nLive-in ";
VF.printAsOperand(O, SlotTracker);
O << " = VF";
}
- if (UF.getNumUsers() > 0) {
+ if (UF.hasUsers()) {
O << "\nLive-in ";
UF.printAsOperand(O, SlotTracker);
O << " = UF";
}
- if (VFxUF.getNumUsers() > 0) {
+ if (VFxUF.hasUsers()) {
O << "\nLive-in ";
VFxUF.printAsOperand(O, SlotTracker);
O << " = VF * UF";
}
- if (VectorTripCount.getNumUsers() > 0) {
+ if (VectorTripCount.hasUsers()) {
O << "\nLive-in ";
VectorTripCount.printAsOperand(O, SlotTracker);
O << " = vector-trip-count";
@@ -1116,7 +1116,7 @@ void VPlan::printLiveIns(raw_ostream &O) const {
}
O << "\n";
- if (TripCount && TripCount->getNumUsers() > 0) {
+ if (TripCount && TripCount->hasUsers()) {
if (isa<VPIRValue>(TripCount))
O << "Live-in ";
TripCount->printAsOperand(O, SlotTracker);
@@ -1563,11 +1563,11 @@ void VPSlotTracker::assignName(const VPValue *V) {
}
void VPSlotTracker::assignNames(const VPlan &Plan) {
- if (Plan.VF.getNumUsers() > 0)
+ if (Plan.VF.hasUsers())
assignName(&Plan.VF);
- if (Plan.UF.getNumUsers() > 0)
+ if (Plan.UF.hasUsers())
assignName(&Plan.UF);
- if (Plan.VFxUF.getNumUsers() > 0)
+ if (Plan.VFxUF.hasUsers())
assignName(&Plan.VFxUF);
assignName(&Plan.VectorTripCount);
if (Plan.BackedgeTakenCount)
diff --git a/llvm/lib/Transforms/Vectorize/VPlan.h b/llvm/lib/Transforms/Vectorize/VPlan.h
index 26c528a323969..7275b4ca7bc05 100644
--- a/llvm/lib/Transforms/Vectorize/VPlan.h
+++ b/llvm/lib/Transforms/Vectorize/VPlan.h
@@ -4936,7 +4936,7 @@ class VPlan {
/// Resets the trip count for the VPlan. The caller must make sure all uses of
/// the original trip count have been replaced.
void resetTripCount(VPValue *NewTripCount) {
- assert(TripCount && NewTripCount && TripCount->getNumUsers() == 0 &&
+ assert(TripCount && NewTripCount && TripCount->hasNoUsers() &&
"TripCount must be set when resetting");
TripCount = NewTripCount;
}
diff --git a/llvm/lib/Transforms/Vectorize/VPlanAnalysis.cpp b/llvm/lib/Transforms/Vectorize/VPlanAnalysis.cpp
index 54f6c602f77d2..d42b0622f835d 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanAnalysis.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanAnalysis.cpp
@@ -124,7 +124,7 @@ SmallVector<VPRegisterUsage, 8> llvm::calculateRegisterUsageForPlan(
// the loop (not including non-recipe values such as arguments and
// constants).
SmallSetVector<VPValue *, 8> LoopInvariants;
- if (Plan.getVectorTripCount().getNumUsers() > 0)
+ if (Plan.getVectorTripCount().hasUsers())
LoopInvariants.insert(&Plan.getVectorTripCount());
// We scan the loop in a topological order in order and assign a number to
@@ -198,7 +198,7 @@ SmallVector<VPRegisterUsage, 8> llvm::calculateRegisterUsageForPlan(
VPValue *CanIV = LoopRegion->getCanonicalIV();
// Note: canonical IVs are retained even if they have no users.
- if (CanIV->getNumUsers() != 0)
+ if (CanIV->hasUsers())
OpenIntervals.insert(CanIV);
// We scan the instructions linearly and record each time that a new interval
diff --git a/llvm/lib/Transforms/Vectorize/VPlanConstruction.cpp b/llvm/lib/Transforms/Vectorize/VPlanConstruction.cpp
index bb967d3f3daf0..619fea8c10b4d 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanConstruction.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanConstruction.cpp
@@ -1767,7 +1767,7 @@ bool VPlanTransforms::handleMaxMinNumReductions(VPlan &Plan) {
continue;
if (auto *DerivedIV = dyn_cast<VPDerivedIVRecipe>(VecV)) {
VPValue *DIVTC = DerivedIV->getOperand(1);
- if (DerivedIV->getNumUsers() == 1 && IsTC(DIVTC)) {
+ if (DerivedIV->hasOneUse() && IsTC(DIVTC)) {
auto *NewSel = MiddleBuilder.createSelect(
AnyNaNLane, LoopRegion->getCanonicalIV(), DIVTC);
DerivedIV->moveAfter(&*MiddleBuilder.getInsertPoint());
diff --git a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
index adcfe30ff9561..35786f019d697 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
@@ -492,7 +492,7 @@ static bool mergeReplicateRegionsIntoSuccessors(VPlan &Plan) {
});
// Remove phi recipes that are unused after merging the regions.
- if (Phi1ToMove.getVPSingleValue()->getNumUsers() == 0) {
+ if (Phi1ToMove.getVPSingleValue()->hasNoUsers()) {
Phi1ToMove.eraseFromParent();
continue;
}
@@ -548,7 +548,7 @@ static VPRegionBlock *createReplicateRegion(VPReplicateRecipe *PredRecipe,
VPBlockUtils::insertTwoBlocksAfter(Pred, Exiting, Entry);
VPBlockUtils::connectBlocks(Pred, Exiting);
- if (PredRecipe->getNumUsers() != 0) {
+ if (PredRecipe->hasUsers()) {
auto *PHIRecipe = new VPPredInstPHIRecipe(RecipeWithoutMask,
RecipeWithoutMask->getDebugLoc());
Exiting->appendRecipe(PHIRecipe);
@@ -802,8 +802,7 @@ static bool isDeadRecipe(VPRecipeBase &R) {
return false;
// Recipe is dead if no user keeps the recipe alive.
- return all_of(R.definedValues(),
- [](VPValue *V) { return V->getNumUsers() == 0; });
+ return all_of(R.definedValues(), [](VPValue *V) { return V->hasNoUsers(); });
}
void VPlanTransforms::removeDeadRecipes(VPlan &Plan) {
@@ -894,7 +893,7 @@ static void legalizeAndOptimizeInductions(VPlan &Plan) {
auto *RepR = dyn_cast<VPReplicateRecipe>(U);
// Skip recipes that shouldn't be narrowed.
if (!Def || !isa<VPReplicateRecipe, VPWidenRecipe>(Def) ||
- Def->getNumUsers() == 0 || !Def->getUnderlyingValue() ||
+ Def->hasNoUsers() || !Def->getUnderlyingValue() ||
(RepR && (RepR->isSingleScalar() || RepR->isPredicated())))
continue;
@@ -2063,7 +2062,7 @@ static void simplifyBlends(VPlan &Plan) {
// TODO: Find the most expensive mask that can be deadcoded, or a mask
// that's used by multiple blends where it can be removed from them all.
VPValue *Mask = Blend->getMask(I);
- if (Mask->getNumUsers() == 1 && !match(Mask, m_False())) {
+ if (Mask->hasOneUse() && !match(Mask, m_False())) {
StartIndex = I;
break;
}
@@ -2099,7 +2098,7 @@ static void simplifyBlends(VPlan &Plan) {
NewBlend->setOperand(0, Inc1);
NewBlend->setOperand(1, Inc0);
NewBlend->setOperand(2, NewMask);
- if (OldMask->getNumUsers() == 0)
+ if (OldMask->hasNoUsers())
cast<VPInstruction>(OldMask)->eraseFromParent();
}
}
@@ -5322,7 +5321,7 @@ void VPlanTransforms::materializeConstantVectorTripCount(
assert(Plan.hasUF(BestUF) && "BestUF is not available in Plan");
VPValue *TC = Plan.getTripCount();
- if (TC->getNumUsers() == 0)
+ if (TC->hasNoUsers())
return;
// Skip cases for which the trip count may be non-trivial to materialize.
@@ -5351,7 +5350,7 @@ void VPlanTransforms::materializeConstantVectorTripCount(
void VPlanTransforms::materializeBackedgeTakenCount(VPlan &Plan,
VPBasicBlock *VectorPH) {
VPValue *BTC = Plan.getOrCreateBackedgeTakenCount();
- if (BTC->getNumUsers() == 0)
+ if (BTC->hasNoUsers())
return;
VPBuilder Builder(VectorPH, VectorPH->begin());
@@ -5460,7 +5459,7 @@ void VPlanTransforms::materializeVectorTripCount(
VPSymbolicValue &VectorTC = Plan.getVectorTripCount();
// There's nothing to do if there are no users of the vector trip count or its
// IR value has already been set.
- if (VectorTC.getNumUsers() == 0 || VectorTC.getUnderlyingValue())
+ if (VectorTC.hasNoUsers() || VectorTC.getUnderlyingValue())
return;
VPValue *TC = Plan.getTripCount();
@@ -5540,7 +5539,7 @@ void VPlanTransforms::materializeFactors(VPlan &Plan, VPBasicBlock *VectorPH,
VPValue &VFxUF = Plan.getVFxUF();
// If there are no users of the runtime VF, compute VFxUF by constant folding
// the multiplication of VF and UF.
- if (VF.getNumUsers() == 0) {
+ if (VF.hasNoUsers()) {
VPValue *RuntimeVFxUF =
Builder.createElementCount(TCTy, VFEC * Plan.getConcreteUF());
VFxUF.replaceAllUsesWith(RuntimeVFxUF);
@@ -5695,7 +5694,7 @@ void VPlanTransforms::expandSCEVsToVPInstructions(VPlan &Plan,
// late expansion.
for (VPRecipeBase &R : make_early_inc_range(*Entry)) {
auto *ExpSCEV = dyn_cast<VPExpandSCEVRecipe>(&R);
- if (!ExpSCEV || ExpSCEV->getNumUsers() == 0)
+ if (!ExpSCEV || ExpSCEV->hasNoUsers())
continue;
Builder.setInsertPoint(ExpSCEV);
VPValue *Expanded = Expander.tryToExpand(ExpSCEV->getSCEV());
diff --git a/llvm/lib/Transforms/Vectorize/VPlanUnroll.cpp b/llvm/lib/Transforms/Vectorize/VPlanUnroll.cpp
index ae4beb5b71874..a9a91e4ad61f8 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanUnroll.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanUnroll.cpp
@@ -946,7 +946,7 @@ void VPlanTransforms::replicateByVF(VPlan &Plan, ElementCount VF) {
auto *DefR = cast<VPSingleDefRecipe>(&R);
VPBuilder Builder(DefR);
- if (DefR->getNumUsers() == 0) {
+ if (DefR->hasNoUsers()) {
// Create single-scalar version of DefR for all lanes.
for (unsigned I = 0; I != VF.getKnownMinValue(); ++I)
cloneForLane(Plan, Builder, IdxTy, DefR, VPLane(I), Def2LaneDefs);
diff --git a/llvm/lib/Transforms/Vectorize/VPlanValue.h b/llvm/lib/Transforms/Vectorize/VPlanValue.h
index 8356bcb08634f..0722ef4d83a28 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanValue.h
+++ b/llvm/lib/Transforms/Vectorize/VPlanValue.h
@@ -161,7 +161,7 @@ class LLVM_ABI_FOR_TEST VPValue {
/// Returns true if the value has more than one unique user.
bool hasMoreThanOneUniqueUser() const {
- if (getNumUsers() == 0)
+ if (hasNoUsers())
return false;
// Check if all users match the first user.
@@ -171,6 +171,8 @@ class LLVM_ABI_FOR_TEST VPValue {
return Current != user_end();
}
+ bool hasNoUsers() const { return Users.empty(); }
+ bool hasUsers() const { return !hasNoUsers(); }
bool hasOneUse() const { return getNumUsers() == 1; }
/// Return the single user of this value, or nullptr if there is not exactly
@@ -523,7 +525,7 @@ class VPDef {
for (VPRecipeValue *D : to_vector(DefinedValues)) {
assert(D->isDefinedBy(this) &&
"all defined VPValues should point to the containing VPDef");
- assert(D->getNumUsers() == 0 &&
+ assert(D->hasNoUsers() &&
"all defined VPValues should have no more users");
delete D;
}
>From 87e0d240a43317daf8d1520e8122516e0a72d80b Mon Sep 17 00:00:00 2001
From: Ramkumar Ramachandra <artagnon at tenstorrent.com>
Date: Wed, 24 Jun 2026 11:17:46 +0100
Subject: [PATCH 2/2] [VPlan] Switch to user_empty()
---
llvm/lib/Transforms/Vectorize/VPlan.cpp | 20 +++++-----
llvm/lib/Transforms/Vectorize/VPlan.h | 2 +-
.../Transforms/Vectorize/VPlanAnalysis.cpp | 4 +-
.../Transforms/Vectorize/VPlanTransforms.cpp | 20 +++++-----
llvm/lib/Transforms/Vectorize/VPlanUnroll.cpp | 2 +-
llvm/lib/Transforms/Vectorize/VPlanValue.h | 11 +++--
.../Transforms/Vectorize/VPlanTest.cpp | 40 +++++++++----------
7 files changed, 49 insertions(+), 50 deletions(-)
diff --git a/llvm/lib/Transforms/Vectorize/VPlan.cpp b/llvm/lib/Transforms/Vectorize/VPlan.cpp
index d5fc0778ce574..5f29f329baf8c 100644
--- a/llvm/lib/Transforms/Vectorize/VPlan.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlan.cpp
@@ -832,7 +832,7 @@ void VPRegionBlock::dissolveToCFGLoop() {
auto *Header = cast<VPBasicBlock>(getEntry());
auto *ExitingLatch = cast<VPBasicBlock>(getExiting());
auto *CanIV = getCanonicalIV();
- if (CanIV->hasUsers()) {
+ if (!CanIV->user_empty()) {
VPlan &Plan = *getPlan();
auto *Zero = Plan.getZero(CanIV->getType());
DebugLoc DL = CanIV->getDebugLoc();
@@ -1085,38 +1085,38 @@ bool VPlan::isOuterLoop() const {
void VPlan::printLiveIns(raw_ostream &O) const {
VPSlotTracker SlotTracker(this);
- if (VF.hasUsers()) {
+ if (!VF.user_empty()) {
O << "\nLive-in ";
VF.printAsOperand(O, SlotTracker);
O << " = VF";
}
- if (UF.hasUsers()) {
+ if (!UF.user_empty()) {
O << "\nLive-in ";
UF.printAsOperand(O, SlotTracker);
O << " = UF";
}
- if (VFxUF.hasUsers()) {
+ if (!VFxUF.user_empty()) {
O << "\nLive-in ";
VFxUF.printAsOperand(O, SlotTracker);
O << " = VF * UF";
}
- if (VectorTripCount.hasUsers()) {
+ if (!VectorTripCount.user_empty()) {
O << "\nLive-in ";
VectorTripCount.printAsOperand(O, SlotTracker);
O << " = vector-trip-count";
}
- if (BackedgeTakenCount && BackedgeTakenCount->getNumUsers()) {
+ if (BackedgeTakenCount && !BackedgeTakenCount->user_empty()) {
O << "\nLive-in ";
BackedgeTakenCount->printAsOperand(O, SlotTracker);
O << " = backedge-taken count";
}
O << "\n";
- if (TripCount && TripCount->hasUsers()) {
+ if (TripCount && !TripCount->user_empty()) {
if (isa<VPIRValue>(TripCount))
O << "Live-in ";
TripCount->printAsOperand(O, SlotTracker);
@@ -1563,11 +1563,11 @@ void VPSlotTracker::assignName(const VPValue *V) {
}
void VPSlotTracker::assignNames(const VPlan &Plan) {
- if (Plan.VF.hasUsers())
+ if (!Plan.VF.user_empty())
assignName(&Plan.VF);
- if (Plan.UF.hasUsers())
+ if (!Plan.UF.user_empty())
assignName(&Plan.UF);
- if (Plan.VFxUF.hasUsers())
+ if (!Plan.VFxUF.user_empty())
assignName(&Plan.VFxUF);
assignName(&Plan.VectorTripCount);
if (Plan.BackedgeTakenCount)
diff --git a/llvm/lib/Transforms/Vectorize/VPlan.h b/llvm/lib/Transforms/Vectorize/VPlan.h
index 7275b4ca7bc05..f73118ac31797 100644
--- a/llvm/lib/Transforms/Vectorize/VPlan.h
+++ b/llvm/lib/Transforms/Vectorize/VPlan.h
@@ -4936,7 +4936,7 @@ class VPlan {
/// Resets the trip count for the VPlan. The caller must make sure all uses of
/// the original trip count have been replaced.
void resetTripCount(VPValue *NewTripCount) {
- assert(TripCount && NewTripCount && TripCount->hasNoUsers() &&
+ assert(TripCount && NewTripCount && TripCount->user_empty() &&
"TripCount must be set when resetting");
TripCount = NewTripCount;
}
diff --git a/llvm/lib/Transforms/Vectorize/VPlanAnalysis.cpp b/llvm/lib/Transforms/Vectorize/VPlanAnalysis.cpp
index d42b0622f835d..77a33339eb5f9 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanAnalysis.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanAnalysis.cpp
@@ -124,7 +124,7 @@ SmallVector<VPRegisterUsage, 8> llvm::calculateRegisterUsageForPlan(
// the loop (not including non-recipe values such as arguments and
// constants).
SmallSetVector<VPValue *, 8> LoopInvariants;
- if (Plan.getVectorTripCount().hasUsers())
+ if (!Plan.getVectorTripCount().user_empty())
LoopInvariants.insert(&Plan.getVectorTripCount());
// We scan the loop in a topological order in order and assign a number to
@@ -198,7 +198,7 @@ SmallVector<VPRegisterUsage, 8> llvm::calculateRegisterUsageForPlan(
VPValue *CanIV = LoopRegion->getCanonicalIV();
// Note: canonical IVs are retained even if they have no users.
- if (CanIV->hasUsers())
+ if (!CanIV->user_empty())
OpenIntervals.insert(CanIV);
// We scan the instructions linearly and record each time that a new interval
diff --git a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
index 35786f019d697..0c7ede5f81593 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
@@ -492,7 +492,7 @@ static bool mergeReplicateRegionsIntoSuccessors(VPlan &Plan) {
});
// Remove phi recipes that are unused after merging the regions.
- if (Phi1ToMove.getVPSingleValue()->hasNoUsers()) {
+ if (Phi1ToMove.getVPSingleValue()->user_empty()) {
Phi1ToMove.eraseFromParent();
continue;
}
@@ -548,7 +548,7 @@ static VPRegionBlock *createReplicateRegion(VPReplicateRecipe *PredRecipe,
VPBlockUtils::insertTwoBlocksAfter(Pred, Exiting, Entry);
VPBlockUtils::connectBlocks(Pred, Exiting);
- if (PredRecipe->hasUsers()) {
+ if (!PredRecipe->user_empty()) {
auto *PHIRecipe = new VPPredInstPHIRecipe(RecipeWithoutMask,
RecipeWithoutMask->getDebugLoc());
Exiting->appendRecipe(PHIRecipe);
@@ -802,7 +802,7 @@ static bool isDeadRecipe(VPRecipeBase &R) {
return false;
// Recipe is dead if no user keeps the recipe alive.
- return all_of(R.definedValues(), [](VPValue *V) { return V->hasNoUsers(); });
+ return all_of(R.definedValues(), [](VPValue *V) { return V->user_empty(); });
}
void VPlanTransforms::removeDeadRecipes(VPlan &Plan) {
@@ -893,7 +893,7 @@ static void legalizeAndOptimizeInductions(VPlan &Plan) {
auto *RepR = dyn_cast<VPReplicateRecipe>(U);
// Skip recipes that shouldn't be narrowed.
if (!Def || !isa<VPReplicateRecipe, VPWidenRecipe>(Def) ||
- Def->hasNoUsers() || !Def->getUnderlyingValue() ||
+ Def->user_empty() || !Def->getUnderlyingValue() ||
(RepR && (RepR->isSingleScalar() || RepR->isPredicated())))
continue;
@@ -2098,7 +2098,7 @@ static void simplifyBlends(VPlan &Plan) {
NewBlend->setOperand(0, Inc1);
NewBlend->setOperand(1, Inc0);
NewBlend->setOperand(2, NewMask);
- if (OldMask->hasNoUsers())
+ if (OldMask->user_empty())
cast<VPInstruction>(OldMask)->eraseFromParent();
}
}
@@ -5321,7 +5321,7 @@ void VPlanTransforms::materializeConstantVectorTripCount(
assert(Plan.hasUF(BestUF) && "BestUF is not available in Plan");
VPValue *TC = Plan.getTripCount();
- if (TC->hasNoUsers())
+ if (TC->user_empty())
return;
// Skip cases for which the trip count may be non-trivial to materialize.
@@ -5350,7 +5350,7 @@ void VPlanTransforms::materializeConstantVectorTripCount(
void VPlanTransforms::materializeBackedgeTakenCount(VPlan &Plan,
VPBasicBlock *VectorPH) {
VPValue *BTC = Plan.getOrCreateBackedgeTakenCount();
- if (BTC->hasNoUsers())
+ if (BTC->user_empty())
return;
VPBuilder Builder(VectorPH, VectorPH->begin());
@@ -5459,7 +5459,7 @@ void VPlanTransforms::materializeVectorTripCount(
VPSymbolicValue &VectorTC = Plan.getVectorTripCount();
// There's nothing to do if there are no users of the vector trip count or its
// IR value has already been set.
- if (VectorTC.hasNoUsers() || VectorTC.getUnderlyingValue())
+ if (VectorTC.user_empty() || VectorTC.getUnderlyingValue())
return;
VPValue *TC = Plan.getTripCount();
@@ -5539,7 +5539,7 @@ void VPlanTransforms::materializeFactors(VPlan &Plan, VPBasicBlock *VectorPH,
VPValue &VFxUF = Plan.getVFxUF();
// If there are no users of the runtime VF, compute VFxUF by constant folding
// the multiplication of VF and UF.
- if (VF.hasNoUsers()) {
+ if (VF.user_empty()) {
VPValue *RuntimeVFxUF =
Builder.createElementCount(TCTy, VFEC * Plan.getConcreteUF());
VFxUF.replaceAllUsesWith(RuntimeVFxUF);
@@ -5694,7 +5694,7 @@ void VPlanTransforms::expandSCEVsToVPInstructions(VPlan &Plan,
// late expansion.
for (VPRecipeBase &R : make_early_inc_range(*Entry)) {
auto *ExpSCEV = dyn_cast<VPExpandSCEVRecipe>(&R);
- if (!ExpSCEV || ExpSCEV->hasNoUsers())
+ if (!ExpSCEV || ExpSCEV->user_empty())
continue;
Builder.setInsertPoint(ExpSCEV);
VPValue *Expanded = Expander.tryToExpand(ExpSCEV->getSCEV());
diff --git a/llvm/lib/Transforms/Vectorize/VPlanUnroll.cpp b/llvm/lib/Transforms/Vectorize/VPlanUnroll.cpp
index a9a91e4ad61f8..bcd17a54a3e31 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanUnroll.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanUnroll.cpp
@@ -946,7 +946,7 @@ void VPlanTransforms::replicateByVF(VPlan &Plan, ElementCount VF) {
auto *DefR = cast<VPSingleDefRecipe>(&R);
VPBuilder Builder(DefR);
- if (DefR->hasNoUsers()) {
+ if (DefR->user_empty()) {
// Create single-scalar version of DefR for all lanes.
for (unsigned I = 0; I != VF.getKnownMinValue(); ++I)
cloneForLane(Plan, Builder, IdxTy, DefR, VPLane(I), Def2LaneDefs);
diff --git a/llvm/lib/Transforms/Vectorize/VPlanValue.h b/llvm/lib/Transforms/Vectorize/VPlanValue.h
index 0722ef4d83a28..a7aa0523ad5d0 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanValue.h
+++ b/llvm/lib/Transforms/Vectorize/VPlanValue.h
@@ -92,7 +92,7 @@ class LLVM_ABI_FOR_TEST VPValue {
VPValue &operator=(const VPValue &) = delete;
virtual ~VPValue() {
- assert(Users.empty() && "trying to delete a VPValue with remaining users");
+ assert(user_empty() && "trying to delete a VPValue with remaining users");
}
/// \return an ID for the concrete type of this object.
@@ -113,7 +113,7 @@ class LLVM_ABI_FOR_TEST VPValue {
void assertNotMaterialized() const;
unsigned getNumUsers() const {
- if (Users.empty())
+ if (user_empty())
return 0;
assertNotMaterialized();
return Users.size();
@@ -158,10 +158,11 @@ class LLVM_ABI_FOR_TEST VPValue {
const_user_range users() const {
return const_user_range(user_begin(), user_end());
}
+ bool user_empty() const { return Users.empty(); } // NOLINT
/// Returns true if the value has more than one unique user.
bool hasMoreThanOneUniqueUser() const {
- if (hasNoUsers())
+ if (user_empty())
return false;
// Check if all users match the first user.
@@ -171,8 +172,6 @@ class LLVM_ABI_FOR_TEST VPValue {
return Current != user_end();
}
- bool hasNoUsers() const { return Users.empty(); }
- bool hasUsers() const { return !hasNoUsers(); }
bool hasOneUse() const { return getNumUsers() == 1; }
/// Return the single user of this value, or nullptr if there is not exactly
@@ -525,7 +524,7 @@ class VPDef {
for (VPRecipeValue *D : to_vector(DefinedValues)) {
assert(D->isDefinedBy(this) &&
"all defined VPValues should point to the containing VPDef");
- assert(D->hasNoUsers() &&
+ assert(D->user_empty() &&
"all defined VPValues should have no more users");
delete D;
}
diff --git a/llvm/unittests/Transforms/Vectorize/VPlanTest.cpp b/llvm/unittests/Transforms/Vectorize/VPlanTest.cpp
index 723977595938f..2deb7c6c864b0 100644
--- a/llvm/unittests/Transforms/Vectorize/VPlanTest.cpp
+++ b/llvm/unittests/Transforms/Vectorize/VPlanTest.cpp
@@ -197,24 +197,24 @@ TEST_F(VPInstructionTest, setOperand) {
VPInstruction *I1 =
new VPInstruction(Instruction::Add, {VPV1, VPV2},
VPIRFlags::getDefaultFlags(Instruction::Add));
- EXPECT_EQ(1u, VPV1->getNumUsers());
+ EXPECT_TRUE(VPV1->hasOneUse());
EXPECT_EQ(I1, *VPV1->user_begin());
- EXPECT_EQ(1u, VPV2->getNumUsers());
+ EXPECT_TRUE(VPV2->hasOneUse());
EXPECT_EQ(I1, *VPV2->user_begin());
// Replace operand 0 (VPV1) with VPV3.
VPValue *VPV3 = getPlan().getOrAddLiveIn(ConstantInt::get(Int32, 3));
I1->setOperand(0, VPV3);
- EXPECT_EQ(0u, VPV1->getNumUsers());
- EXPECT_EQ(1u, VPV2->getNumUsers());
+ EXPECT_TRUE(VPV1->user_empty());
+ EXPECT_TRUE(VPV2->hasOneUse());
EXPECT_EQ(I1, *VPV2->user_begin());
- EXPECT_EQ(1u, VPV3->getNumUsers());
+ EXPECT_TRUE(VPV3->hasOneUse());
EXPECT_EQ(I1, *VPV3->user_begin());
// Replace operand 1 (VPV2) with VPV3.
I1->setOperand(1, VPV3);
- EXPECT_EQ(0u, VPV1->getNumUsers());
- EXPECT_EQ(0u, VPV2->getNumUsers());
+ EXPECT_TRUE(VPV1->user_empty());
+ EXPECT_TRUE(VPV2->user_empty());
EXPECT_EQ(2u, VPV3->getNumUsers());
EXPECT_EQ(I1, *VPV3->user_begin());
EXPECT_EQ(I1, *std::next(VPV3->user_begin()));
@@ -222,13 +222,13 @@ TEST_F(VPInstructionTest, setOperand) {
// Replace operand 0 (VPV3) with VPV4.
VPValue *VPV4 = getPlan().getOrAddLiveIn(ConstantInt::get(Int32, 4));
I1->setOperand(0, VPV4);
- EXPECT_EQ(1u, VPV3->getNumUsers());
+ EXPECT_TRUE(VPV3->hasOneUse());
EXPECT_EQ(I1, *VPV3->user_begin());
EXPECT_EQ(I1, *VPV4->user_begin());
// Replace operand 1 (VPV3) with VPV4.
I1->setOperand(1, VPV4);
- EXPECT_EQ(0u, VPV3->getNumUsers());
+ EXPECT_TRUE(VPV3->user_empty());
EXPECT_EQ(I1, *VPV4->user_begin());
EXPECT_EQ(I1, *std::next(VPV4->user_begin()));
@@ -248,18 +248,18 @@ TEST_F(VPInstructionTest, replaceAllUsesWith) {
VPV1->replaceAllUsesWith(VPV3);
EXPECT_EQ(VPV3, I1->getOperand(0));
EXPECT_EQ(VPV2, I1->getOperand(1));
- EXPECT_EQ(0u, VPV1->getNumUsers());
- EXPECT_EQ(1u, VPV2->getNumUsers());
+ EXPECT_TRUE(VPV1->user_empty());
+ EXPECT_TRUE(VPV2->hasOneUse());
EXPECT_EQ(I1, *VPV2->user_begin());
- EXPECT_EQ(1u, VPV3->getNumUsers());
+ EXPECT_TRUE(VPV3->hasOneUse());
EXPECT_EQ(I1, *VPV3->user_begin());
// Replace all uses of VPV2 with VPV3.
VPV2->replaceAllUsesWith(VPV3);
EXPECT_EQ(VPV3, I1->getOperand(0));
EXPECT_EQ(VPV3, I1->getOperand(1));
- EXPECT_EQ(0u, VPV1->getNumUsers());
- EXPECT_EQ(0u, VPV2->getNumUsers());
+ EXPECT_TRUE(VPV1->user_empty());
+ EXPECT_TRUE(VPV2->user_empty());
EXPECT_EQ(2u, VPV3->getNumUsers());
EXPECT_EQ(I1, *VPV3->user_begin());
@@ -269,8 +269,8 @@ TEST_F(VPInstructionTest, replaceAllUsesWith) {
EXPECT_EQ(VPV1, I1->getOperand(1));
EXPECT_EQ(2u, VPV1->getNumUsers());
EXPECT_EQ(I1, *VPV1->user_begin());
- EXPECT_EQ(0u, VPV2->getNumUsers());
- EXPECT_EQ(0u, VPV3->getNumUsers());
+ EXPECT_TRUE(VPV2->user_empty());
+ EXPECT_TRUE(VPV3->user_empty());
VPInstruction *I2 =
new VPInstruction(Instruction::Add, {VPV1, VPV2},
@@ -291,15 +291,15 @@ TEST_F(VPInstructionTest, releaseOperandsAtDeletion) {
new VPInstruction(Instruction::Add, {VPV1, VPV2},
VPIRFlags::getDefaultFlags(Instruction::Add));
- EXPECT_EQ(1u, VPV1->getNumUsers());
+ EXPECT_TRUE(VPV1->hasOneUse());
EXPECT_EQ(I1, *VPV1->user_begin());
- EXPECT_EQ(1u, VPV2->getNumUsers());
+ EXPECT_TRUE(VPV2->hasOneUse());
EXPECT_EQ(I1, *VPV2->user_begin());
delete I1;
- EXPECT_EQ(0u, VPV1->getNumUsers());
- EXPECT_EQ(0u, VPV2->getNumUsers());
+ EXPECT_TRUE(VPV1->user_empty());
+ EXPECT_TRUE(VPV2->user_empty());
}
using VPBasicBlockTest = VPlanTestBase;
More information about the llvm-commits
mailing list