[llvm] 9fdb3bb - [SandboxVec][VecUtils][NFC] BndlRef helper class (#223074)

via llvm-commits llvm-commits at lists.llvm.org
Mon Sep 14 11:07:28 PDT 2026


Author: vporpo
Date: 2026-09-14T11:07:22-07:00
New Revision: 9fdb3bbd29ea03834f325373efe5ee0ea9fe4061

URL: https://github.com/llvm/llvm-project/commit/9fdb3bbd29ea03834f325373efe5ee0ea9fe4061
DIFF: https://github.com/llvm/llvm-project/commit/9fdb3bbd29ea03834f325373efe5ee0ea9fe4061.diff

LOG: [SandboxVec][VecUtils][NFC] BndlRef helper class (#223074)

During debugging we need to be able to easily print a bundle of
instructions or values. Up until now we would use VecUtils::dump(Bndl).
But a much nicer API would be Bndl.dump().

To support such an API this patch is introducing BndlRef, a subclass of
ArrayRef with the additional feature of supporting print(OS) and dump()
for Value and Instruction contents.

Added: 
    

Modified: 
    llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/InstrMaps.h
    llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Passes/BundleVec.h
    llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/VecUtils.h
    llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/BundleVec.cpp
    llvm/lib/Transforms/Vectorize/SandboxVectorizer/VecUtils.cpp
    llvm/unittests/Transforms/Vectorize/SandboxVectorizer/VecUtilsTest.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/InstrMaps.h b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/InstrMaps.h
index 45b6d1405a8b3..32d63fc0452a4 100644
--- a/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/InstrMaps.h
+++ b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/InstrMaps.h
@@ -32,7 +32,7 @@ struct Action {
   unsigned Depth;
   SmallVector<Action *> Operands;
   Value *Vec = nullptr;
-  Action(const LegalityResult *LR, ArrayRef<Value *> B, ArrayRef<Value *> UB,
+  Action(const LegalityResult *LR, BndlRef<Value *> B, BndlRef<Value *> UB,
          unsigned Depth)
       : LegalityRes(LR), Bndl(B), UserBndl(UB), Depth(Depth) {}
 #ifndef NDEBUG
@@ -84,7 +84,7 @@ class InstrMaps {
     return It2->second;
   }
   /// Update the map to reflect that \p Origs got vectorized into \p Vec.
-  void registerVector(ArrayRef<Value *> Origs, Action *Vec) {
+  void registerVector(BndlRef<Value *> Origs, Action *Vec) {
     auto &OrigToLaneMap = VectorToOrigLaneMap[Vec];
     unsigned Lane = 0;
     for (Value *Orig : Origs) {

diff  --git a/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Passes/BundleVec.h b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Passes/BundleVec.h
index 62ff4a527d1f7..de9bea6d38a73 100644
--- a/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Passes/BundleVec.h
+++ b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Passes/BundleVec.h
@@ -54,7 +54,7 @@ class LLVM_ABI BundleVec final : public RegionPass {
 
   /// Creates and returns a vector instruction that replaces the instructions in
   /// \p Bndl. \p Operands are the already vectorized operands.
-  Value *createVectorInstr(ArrayRef<Value *> Bndl, ArrayRef<Value *> Operands);
+  Value *createVectorInstr(BndlRef<Value *> Bndl, BndlRef<Value *> Operands);
 
   /// Creates a shuffle instruction that shuffles \p VecOp according to \p Mask.
   /// \p UserBB is the block of the user bundle.
@@ -62,7 +62,7 @@ class LLVM_ABI BundleVec final : public RegionPass {
                        BasicBlock *UserBB);
   /// Packs all elements of \p ToPack into a vector and returns that vector. \p
   /// UserBB is the block of the user bundle.
-  Value *createPack(ArrayRef<Value *> ToPack, BasicBlock *UserBB);
+  Value *createPack(BndlRef<Value *> ToPack, BasicBlock *UserBB);
 
   /// Helper class describing how(if) to vectorize the code.
   class ActionsVector {
@@ -89,16 +89,16 @@ class LLVM_ABI BundleVec final : public RegionPass {
 
   /// Recursively try to vectorize \p Bndl. \p UserBndl identifies the
   /// users that this recursive call originates from.
-  Action *vectorizeRec(ArrayRef<Value *> Bndl, ArrayRef<Value *> UserBndl,
+  Action *vectorizeRec(BndlRef<Value *> Bndl, BndlRef<Value *> UserBndl,
                        unsigned Depth, LegalityAnalysis &Legality);
   /// If the values in \p Bndl have external users, then emit unpacks and
   /// connect them to the users. \p Vec is the vectorized form of \p Bndl.
-  void emitUnpacksForExternalUses(const ArrayRef<Value *> Bndl, Value *Vec);
+  void emitUnpacksForExternalUses(BndlRef<Value *> Bndl, Value *Vec);
   /// Generate vector instructions based on `Actions` and return the last vector
   /// created.
   Value *emitVectors();
   /// Entry point for vectorization starting from \p Seeds.
-  bool tryVectorize(ArrayRef<Value *> Seeds, LegalityAnalysis &Legality);
+  bool tryVectorize(BndlRef<Value *> Seeds, LegalityAnalysis &Legality);
 
 public:
   BundleVec(StringRef AuxArg) : RegionPass("bundle-vec") {

diff  --git a/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/VecUtils.h b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/VecUtils.h
index 80e266d1c3022..b904d497faf68 100644
--- a/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/VecUtils.h
+++ b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/VecUtils.h
@@ -453,6 +453,49 @@ class VecUtils {
 #endif // NDEBUG
 };
 
+/// An ArrayRef of Values or Instructions that we can print/dump for debugging.
+/// It is mainly used for the vectorizer's instr/value bundles.
+template <typename T> class BndlRef : public ArrayRef<T> {
+public:
+  // Inherit constructors.
+  using ArrayRef<T>::ArrayRef;
+
+#ifndef NDEBUG
+  /// Helper dump function for debugging.
+  void print(raw_ostream &OS) const {
+    for (const auto &[Idx, Val] : enumerate(*this))
+      OS << Idx << ". " << *Val << "\n";
+  }
+  LLVM_DUMP_METHOD void dump() const;
+#endif // NDEBUG
+};
+
+/// @name BndlRef Deduction guides
+/// @{
+/// Deduction guide to construct a BndlRef from a single element.
+template <typename T> BndlRef(const T &OneElt) -> BndlRef<T>;
+/// Deduction guide to construct a BndlRef from a pointer and length
+template <typename T> BndlRef(const T *data, size_t length) -> BndlRef<T>;
+/// Deduction guide to construct a BndlRef from a range
+template <typename T> BndlRef(const T *data, const T *end) -> BndlRef<T>;
+/// Deduction guide to construct a BndlRef from a SmallVector
+template <typename T> BndlRef(const SmallVectorImpl<T> &Vec) -> BndlRef<T>;
+/// Deduction guide to construct a BndlRef from a SmallVector
+template <typename T, unsigned N>
+BndlRef(const SmallVector<T, N> &Vec) -> BndlRef<T>;
+/// Deduction guide to construct a BndlRef from a std::vector
+template <typename T> BndlRef(const std::vector<T> &Vec) -> BndlRef<T>;
+/// Deduction guide to construct a BndlRef from a std::array
+template <typename T, std::size_t N>
+BndlRef(const std::array<T, N> &Vec) -> BndlRef<T>;
+/// Deduction guide to construct a BndlRef from an BndlRef (const)
+template <typename T> BndlRef(const BndlRef<T> &Vec) -> BndlRef<T>;
+/// Deduction guide to construct a BndlRef from an BndlRef
+template <typename T> BndlRef(BndlRef<T> &Vec) -> BndlRef<T>;
+/// Deduction guide to construct a BndlRef from a C array.
+template <typename T, size_t N> BndlRef(const T (&Arr)[N]) -> BndlRef<T>;
+/// @}
+
 } // namespace sandboxir
 
 } // namespace llvm

diff  --git a/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/BundleVec.cpp b/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/BundleVec.cpp
index 5f4ca6fe12686..80dd30896b00b 100644
--- a/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/BundleVec.cpp
+++ b/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/BundleVec.cpp
@@ -41,7 +41,7 @@ static cl::opt<unsigned long>
 
 namespace sandboxir {
 
-static BundleTy getOperand(ArrayRef<Value *> Bndl, unsigned OpIdx) {
+static BundleTy getOperand(BndlRef<Value *> Bndl, unsigned OpIdx) {
   BundleTy Operands;
   for (Value *BndlV : Bndl) {
     auto *BndlI = cast<Instruction>(BndlV);
@@ -50,10 +50,10 @@ static BundleTy getOperand(ArrayRef<Value *> Bndl, unsigned OpIdx) {
   return Operands;
 }
 
-Value *BundleVec::createVectorInstr(ArrayRef<Value *> Bndl,
-                                    ArrayRef<Value *> Operands) {
-  auto CreateVectorInstr = [](ArrayRef<Value *> Bndl,
-                              ArrayRef<Value *> Operands) -> Value * {
+Value *BundleVec::createVectorInstr(BndlRef<Value *> Bndl,
+                                    BndlRef<Value *> Operands) {
+  auto CreateVectorInstr = [](BndlRef<Value *> Bndl,
+                              BndlRef<Value *> Operands) -> Value * {
     assert(all_of(Bndl, [](auto *V) { return isa<Instruction>(V); }) &&
            "Expect Instructions!");
     auto &Ctx = Bndl[0]->getContext();
@@ -169,7 +169,7 @@ Value *BundleVec::createShuffle(Value *VecOp, const ShuffleMask &Mask,
                                    VecOp->getContext(), "VShuf");
 }
 
-Value *BundleVec::createPack(ArrayRef<Value *> ToPack, BasicBlock *UserBB) {
+Value *BundleVec::createPack(BndlRef<Value *> ToPack, BasicBlock *UserBB) {
   BasicBlock::iterator WhereIt =
       VecUtils::getInsertPointAfterInstrs(ToPack, UserBB);
 
@@ -221,8 +221,8 @@ Value *BundleVec::createPack(ArrayRef<Value *> ToPack, BasicBlock *UserBB) {
   return LastInsert;
 }
 
-Action *BundleVec::vectorizeRec(ArrayRef<Value *> Bndl,
-                                ArrayRef<Value *> UserBndl, unsigned Depth,
+Action *BundleVec::vectorizeRec(BndlRef<Value *> Bndl,
+                                BndlRef<Value *> UserBndl, unsigned Depth,
                                 LegalityAnalysis &Legality) {
   bool StopForDebug =
       DebugBndlCnt++ >= StopBundle && StopBundle != StopBundleDisabled;
@@ -239,8 +239,8 @@ Action *BundleVec::vectorizeRec(ArrayRef<Value *> Bndl,
     if (LegalityRes.getSubclassID() != LegalityResultID::Widen)
       return nullptr;
 
-    auto ActionPtr = std::make_unique<Action>(&LegalityRes, Bndl,
-                                              ArrayRef<Value *>(), Depth);
+    auto ActionPtr =
+        std::make_unique<Action>(&LegalityRes, Bndl, BndlRef<Value *>(), Depth);
     Action *Action = ActionPtr.get();
     IMaps->registerVector(Bndl, Action);
     Actions.push_back(std::move(ActionPtr));
@@ -309,8 +309,7 @@ void BundleVec::ActionsVector::print(raw_ostream &OS) const {
 void BundleVec::ActionsVector::dump() const { print(dbgs()); }
 #endif // NDEBUG
 
-void BundleVec::emitUnpacksForExternalUses(const ArrayRef<Value *> Bndl,
-                                           Value *Vec) {
+void BundleVec::emitUnpacksForExternalUses(BndlRef<Value *> Bndl, Value *Vec) {
   // Find where we should emit the unpacks.
   BasicBlock::iterator WhereIt;
   if (auto *VecI = dyn_cast<Instruction>(Vec)) {
@@ -350,8 +349,8 @@ void BundleVec::emitUnpacksForExternalUses(const ArrayRef<Value *> Bndl,
 Value *BundleVec::emitVectors() {
   Value *NewVec = nullptr;
   for (const auto &ActionPtr : Actions) {
-    ArrayRef<Value *> Bndl = ActionPtr->Bndl;
-    ArrayRef<Value *> UserBndl = ActionPtr->UserBndl;
+    BndlRef<Value *> Bndl = ActionPtr->Bndl;
+    BndlRef<Value *> UserBndl = ActionPtr->UserBndl;
     const LegalityResult &LegalityRes = *ActionPtr->LegalityRes;
     unsigned Depth = ActionPtr->Depth;
     auto *UserBB = !UserBndl.empty()
@@ -512,7 +511,7 @@ Value *BundleVec::emitVectors() {
   return NewVec;
 }
 
-bool BundleVec::tryVectorize(ArrayRef<Value *> Bndl,
+bool BundleVec::tryVectorize(BndlRef<Value *> Bndl,
                              LegalityAnalysis &Legality) {
   Change = false;
   if (LLVM_UNLIKELY(InvocationCnt++ >= StopAt && StopAt != StopAtDisabled))

diff  --git a/llvm/lib/Transforms/Vectorize/SandboxVectorizer/VecUtils.cpp b/llvm/lib/Transforms/Vectorize/SandboxVectorizer/VecUtils.cpp
index abf3d79966d8f..e5caeb68764d6 100644
--- a/llvm/lib/Transforms/Vectorize/SandboxVectorizer/VecUtils.cpp
+++ b/llvm/lib/Transforms/Vectorize/SandboxVectorizer/VecUtils.cpp
@@ -159,6 +159,15 @@ template <typename T> static void dumpImpl(ArrayRef<T *> Bndl) {
 }
 void VecUtils::dump(ArrayRef<Value *> Bndl) { dumpImpl(Bndl); }
 void VecUtils::dump(ArrayRef<Instruction *> Bndl) { dumpImpl(Bndl); }
+
+template <typename T> void BndlRef<T>::dump() const {
+  print(dbgs());
+  dbgs() << "\n";
+}
+// Explicit instantiation for commonly used types.
+template class BndlRef<Instruction *>;
+template class BndlRef<Value *>;
+
 #endif // NDEBUG
 
 } // namespace llvm::sandboxir

diff  --git a/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/VecUtilsTest.cpp b/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/VecUtilsTest.cpp
index b4f40a1eee201..a2d6b2cba3ac0 100644
--- a/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/VecUtilsTest.cpp
+++ b/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/VecUtilsTest.cpp
@@ -1299,3 +1299,38 @@ define void @vectorized_seed_user(ptr %p) {
       sandboxir::VecUtils::getNextUserBundles({Ld0, Ld1}, IMaps, Claimed)
           .empty());
 }
+
+TEST_F(VecUtilsTest, BndlRef) {
+  parseIR(R"IR(
+define void @vectorized_seed_user(i8 %v0, i8 %v1) {
+entry:
+  %add0 = add i8 %v0, 0
+  %add1 = add i8 %v1, 1
+  ret void
+}
+)IR");
+  sandboxir::Context Ctx(C);
+  auto *F = Ctx.createFunction(M->getFunction("vectorized_seed_user"));
+  auto &BB = getBasicBlockByName(*F, "entry");
+  auto It = BB.begin();
+  auto *Ld0 = cast<sandboxir::Instruction>(&*It++);
+  auto *Ld1 = cast<sandboxir::Instruction>(&*It++);
+  std::string Str;
+  raw_string_ostream SS(Str);
+
+  SmallVector<sandboxir::Value *> ValuesVec(
+      {static_cast<sandboxir::Value *>(Ld0),
+       static_cast<sandboxir::Value *>(Ld1)});
+  sandboxir::BndlRef ValuesBndl(ValuesVec);
+  Str.clear();
+  ValuesBndl.print(SS);
+  EXPECT_THAT(Str, testing::MatchesRegex("0. *%add0 = add i8 %v0, 0 .*\n"
+                                         "1. *%add1 = add i8 %v1, 1 .*\n"));
+
+  SmallVector<sandboxir::Instruction *> InstrsVec({Ld0, Ld1});
+  sandboxir::BndlRef InstrsBndl(InstrsVec);
+  Str.clear();
+  ValuesBndl.print(SS);
+  EXPECT_THAT(Str, testing::MatchesRegex("0. *%add0 = add i8 %v0, 0 .*\n"
+                                         "1. *%add1 = add i8 %v1, 1 .*\n"));
+}


        


More information about the llvm-commits mailing list