Skip to content

Conversation

@Mel-Chen
Copy link
Contributor

@Mel-Chen Mel-Chen commented Dec 5, 2025

SmallVector Users may contain duplicate users, so relying on hasOneUse() does not guarantee a single unique user. This patch introduces hasOneUser() to check for exactly only one user, and updates getSingleUser() and VPWidenCastRecipe::computeCost() to use it.

@llvmbot
Copy link
Member

llvmbot commented Dec 5, 2025

@llvm/pr-subscribers-vectorizers

@llvm/pr-subscribers-llvm-transforms

Author: Mel Chen (Mel-Chen)

Changes

SmallVector Users may contain duplicate users, so relying on hasOneUse() does not guarantee a single unique user. This patch introduces hasOneUser() to check for exactly only one user, and updates getSingleUser() and VPWidenCastRecipe::computeCost() to use it.


Full diff: https://github.com/llvm/llvm-project/pull/170826.diff

2 Files Affected:

  • (modified) llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp (+2-3)
  • (modified) llvm/lib/Transforms/Vectorize/VPlanValue.h (+12-2)
diff --git a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
index 1b1308c78c76e..17adcafd18044 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
@@ -2259,9 +2259,8 @@ InstructionCost VPWidenCastRecipe::computeCost(ElementCount VF,
   VPValue *Operand = getOperand(0);
   TTI::CastContextHint CCH = TTI::CastContextHint::None;
   // For Trunc/FPTrunc, get the context from the only user.
-  if ((Opcode == Instruction::Trunc || Opcode == Instruction::FPTrunc) &&
-      !hasMoreThanOneUniqueUser() && getNumUsers() > 0) {
-    if (auto *StoreRecipe = dyn_cast<VPRecipeBase>(*user_begin()))
+  if (Opcode == Instruction::Trunc || Opcode == Instruction::FPTrunc) {
+    if (auto *StoreRecipe = dyn_cast_or_null<VPRecipeBase>(getSingleUser()))
       CCH = ComputeCCH(StoreRecipe);
   }
   // For Z/Sext, get the context from the operand.
diff --git a/llvm/lib/Transforms/Vectorize/VPlanValue.h b/llvm/lib/Transforms/Vectorize/VPlanValue.h
index b9f5847ec731c..db48fe5ed73bf 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanValue.h
+++ b/llvm/lib/Transforms/Vectorize/VPlanValue.h
@@ -150,11 +150,21 @@ class LLVM_ABI_FOR_TEST VPValue {
 
   bool hasOneUse() const { return getNumUsers() == 1; }
 
+  /// Returns true if the value has exactly one unique user, ignoring multiple
+  /// uses by the same user.
+  bool hasOneUser() const {
+    if (getNumUsers() == 0)
+      return false;
+    if (hasOneUse())
+      return true;
+    return std::equal(std::next(user_begin()), user_end(), user_begin());
+  }
+
   /// Return the single user of this value, or nullptr if there is not exactly
   /// one user.
-  VPUser *getSingleUser() { return hasOneUse() ? *user_begin() : nullptr; }
+  VPUser *getSingleUser() { return hasOneUser() ? *user_begin() : nullptr; }
   const VPUser *getSingleUser() const {
-    return hasOneUse() ? *user_begin() : nullptr;
+    return hasOneUser() ? *user_begin() : nullptr;
   }
 
   void replaceAllUsesWith(VPValue *New);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants