[llvm] [SandboxVec] SandboxVectorizerIR Boilerplate (PR #189515)

via llvm-commits llvm-commits at lists.llvm.org
Tue Mar 31 13:57:34 PDT 2026


https://github.com/vporpo updated https://github.com/llvm/llvm-project/pull/189515

>From bb249297dfc8621c900e99581388fdf7885f84a0 Mon Sep 17 00:00:00 2001
From: Vasileios Porpodas <vasileios.porpodas at amd.com>
Date: Fri, 27 Mar 2026 00:35:25 +0000
Subject: [PATCH 1/2] [SandboxVec] SandboxVectorizerIR Boilerplate

This patch introduces a new specialization of SandboxIR named SandboxVectorizerIR
that contains the new Pack instruction (though it is just a placeholder for now).
It also implements the necessary boilerplate in SandboxIR to support adding such
specializations.

Each specialization requires its own *Values.def file defining its new instructions.
The new .def file also needs to be added to ValuesDefFilesList.def which
allows SandboxIR to include entries from all specializations and populate
structures like the Opcode enum, ClassID and others.

Given that we need to include both .def files in several places, I had to (i) change the
.def file to undefine its locally defined macros so that they won't get redefined in the
next #include .def, and (ii) add the DEF_DISABLE_AUTO_UNDEF option to disable undefining
the macros at the end because otherwise the user-specified DEF_ macros would be undefined
by the time we reach the second .def file.
---
 llvm/include/llvm/SandboxIR/Context.h         | 15 +++-
 llvm/include/llvm/SandboxIR/Instruction.h     | 22 +++++-
 llvm/include/llvm/SandboxIR/Use.h             |  6 +-
 llvm/include/llvm/SandboxIR/Value.h           | 25 ++++++-
 llvm/include/llvm/SandboxIR/Values.def        | 75 ++++++++++++++++---
 .../llvm/SandboxIR/ValuesDefFilesList.def     | 21 ++++++
 .../SandboxVectorizer/SandboxVectorizerIR.h   | 62 +++++++++++++++
 .../SandboxVectorizerIRValues.def             | 52 +++++++++++++
 llvm/lib/SandboxIR/Context.cpp                |  4 +-
 llvm/lib/SandboxIR/Instruction.cpp            | 12 ---
 llvm/lib/Transforms/Vectorize/CMakeLists.txt  |  1 +
 .../Vectorize/SandboxVectorizer/Legality.cpp  |  1 +
 .../SandboxVectorizer/SandboxVectorizerIR.cpp | 48 ++++++++++++
 llvm/unittests/SandboxIR/SandboxIRTest.cpp    |  1 +
 .../SandboxVectorizer/CMakeLists.txt          |  1 +
 .../SandboxVectorizerIRTest.cpp               | 57 ++++++++++++++
 16 files changed, 370 insertions(+), 33 deletions(-)
 create mode 100644 llvm/include/llvm/SandboxIR/ValuesDefFilesList.def
 create mode 100644 llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizerIR.h
 create mode 100644 llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizerIRValues.def
 create mode 100644 llvm/lib/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizerIR.cpp
 create mode 100644 llvm/unittests/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizerIRTest.cpp

diff --git a/llvm/include/llvm/SandboxIR/Context.h b/llvm/include/llvm/SandboxIR/Context.h
index 0c936b138e7c5..d37465860f615 100644
--- a/llvm/include/llvm/SandboxIR/Context.h
+++ b/llvm/include/llvm/SandboxIR/Context.h
@@ -30,8 +30,19 @@ class Region;
 class Value;
 class Use;
 
+enum class SandboxIRSpecialization {
+#define DEF_SPECIALIZATION(NAME) NAME,
+#include "llvm/SandboxIR/ValuesDefFilesList.def"
+};
+
 class Context {
+  SandboxIRSpecialization Specialization = SandboxIRSpecialization::Base;
+
 public:
+  SandboxIRSpecialization getSpecialization() const { return Specialization; }
+  void assertSpecialization(SandboxIRSpecialization S) const {
+    assert(Specialization == S && "Unexpected SandboxIR Specialization!");
+  }
   // A EraseInstrCallback receives the instruction about to be erased.
   using EraseInstrCallback = std::function<void(Instruction *)>;
   // A CreateInstrCallback receives the instruction about to be created.
@@ -239,7 +250,9 @@ class Context {
   friend FCmpInst; // For createFCmpInst()
 
 public:
-  LLVM_ABI Context(LLVMContext &LLVMCtx);
+  LLVM_ABI
+  Context(LLVMContext &LLVMCtx, SandboxIRSpecialization Specialization =
+                                    SandboxIRSpecialization::Base);
   LLVM_ABI ~Context();
   /// Clears function-level state.
   LLVM_ABI void clear();
diff --git a/llvm/include/llvm/SandboxIR/Instruction.h b/llvm/include/llvm/SandboxIR/Instruction.h
index 5d056359c0542..62178e4afc88d 100644
--- a/llvm/include/llvm/SandboxIR/Instruction.h
+++ b/llvm/include/llvm/SandboxIR/Instruction.h
@@ -46,7 +46,11 @@ class Instruction : public User {
 #define OP(OPC) OPC,
 #define OPCODES(...) __VA_ARGS__
 #define DEF_INSTR(ID, OPC, CLASS) OPC
-#include "llvm/SandboxIR/Values.def"
+#define DEF_DISABLE_AUTO_UNDEF // Since we are including more than one .def.
+#include "llvm/SandboxIR/ValuesDefFilesList.def"
+#undef OP
+#undef OPCODES
+#undef DEF_INSTR
   };
 
 protected:
@@ -113,7 +117,21 @@ class Instruction : public User {
   }
 
 public:
-  LLVM_ABI static const char *getOpcodeName(Opcode Opc);
+  LLVM_ABI static const char *getOpcodeName(Opcode Opc) {
+    switch (Opc) {
+#define OP(OPC)                                                                \
+  case Opcode::OPC:                                                            \
+    return #OPC;
+#define OPCODES(...) __VA_ARGS__
+#define DEF_INSTR(ID, OPC, CLASS) OPC
+#define DEF_DISABLE_AUTO_UNDEF // Since we are including more than one .def.
+#include "llvm/SandboxIR/ValuesDefFilesList.def"
+#undef OPCODES
+#undef DEF_INSTR
+    }
+    llvm_unreachable("Unknown Opcode");
+  }
+
   /// This is used by BasicBlock::iterator.
   virtual unsigned getNumOfIRInstrs() const = 0;
   /// \Returns a BasicBlock::iterator for this Instruction.
diff --git a/llvm/include/llvm/SandboxIR/Use.h b/llvm/include/llvm/SandboxIR/Use.h
index 3435d56bca4ea..39c07e8e107ce 100644
--- a/llvm/include/llvm/SandboxIR/Use.h
+++ b/llvm/include/llvm/SandboxIR/Use.h
@@ -45,8 +45,12 @@ class Use {
   friend class OperandUseIterator; // For constructor
   friend class UserUseIterator;    // For accessing members
   friend class CallBase;           // For LLVMUse
-  friend class CallBrInst;         // For constructor
   friend class PHINode;            // For LLVMUse
+  // Friend instructions so that they can call the constructor if needed.
+#define DEF_INSTR(ID, OPC, CLASS) friend class CLASS;
+#define DEF_DISABLE_AUTO_UNDEF // Since we are including more than one .def.
+#include "llvm/SandboxIR/ValuesDefFilesList.def"
+#undef DEF_INSTR
 
 public:
   operator Value *() const { return get(); }
diff --git a/llvm/include/llvm/SandboxIR/Value.h b/llvm/include/llvm/SandboxIR/Value.h
index 0379f4df04c65..a4a15889823b9 100644
--- a/llvm/include/llvm/SandboxIR/Value.h
+++ b/llvm/include/llvm/SandboxIR/Value.h
@@ -20,7 +20,11 @@ namespace llvm::sandboxir {
 #define DEF_INSTR(ID, OPC, CLASS) class CLASS;
 #define DEF_CONST(ID, CLASS) class CLASS;
 #define DEF_USER(ID, CLASS) class CLASS;
-#include "llvm/SandboxIR/Values.def"
+#define DEF_DISABLE_AUTO_UNDEF // Since we are including more than one .def.
+#include "llvm/SandboxIR/ValuesDefFilesList.def"
+#undef DEF_INSTR
+#undef DEF_CONST
+#undef DEF_USER
 class Context;
 class FuncletPadInst;
 class Type;
@@ -72,7 +76,12 @@ class Value {
 #define DEF_USER(ID, CLASS) ID,
 #define DEF_CONST(ID, CLASS) ID,
 #define DEF_INSTR(ID, OPC, CLASS) ID,
-#include "llvm/SandboxIR/Values.def"
+#define DEF_DISABLE_AUTO_UNDEF // Since we are including more than one .def.
+#include "llvm/SandboxIR/ValuesDefFilesList.def"
+#undef DEF_VALUE
+#undef DEF_USER
+#undef DEF_CONST
+#undef DEF_INSTR
   };
 
 protected:
@@ -90,7 +99,12 @@ class Value {
 #define DEF_INSTR(ID, OPC, CLASS)                                              \
   case ClassID::ID:                                                            \
     return #ID;
-#include "llvm/SandboxIR/Values.def"
+#define DEF_DISABLE_AUTO_UNDEF // Since we are including more than one .def.
+#include "llvm/SandboxIR/ValuesDefFilesList.def"
+#undef DEF_VALUE
+#undef DEF_USER
+#undef DEF_CONST
+#undef DEF_INSTR
     }
     llvm_unreachable("Unimplemented ID");
   }
@@ -178,6 +192,11 @@ class Value {
   friend class ConstantDataArray; // For `Val`
   friend class ConstantDataVector; // For `Val`
 
+#define DEF_INSTR(ID, OPC, CLASS) friend class CLASS;
+#define DEF_DISABLE_AUTO_UNDEF // Since we are including more than one .def.
+#include "llvm/SandboxIR/ValuesDefFilesList.def"
+#undef DEF_INSTR
+
   /// All values point to the context.
   Context &Ctx;
   // This is used by eraseFromParent().
diff --git a/llvm/include/llvm/SandboxIR/Values.def b/llvm/include/llvm/SandboxIR/Values.def
index d7c28f8163860..ef53ea6f5cece 100644
--- a/llvm/include/llvm/SandboxIR/Values.def
+++ b/llvm/include/llvm/SandboxIR/Values.def
@@ -5,20 +5,43 @@
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
+//
+// NOTE: Please #define DEF_DISABLE_AUTO_UNDEF before including more than one
+//       .def file to stop the .def file from automatically undefying macros.
+//
 
-//    ClassID, Class
 #ifndef DEF_VALUE
 #define DEF_VALUE(ID, CLASS)
+#define DEF_VALUE_DEFINED_INTERNALLY
 #endif
 
 #ifndef DEF_USER
 #define DEF_USER(ID, CLASS)
+#define DEF_USER_DEFINED_INTERNALLY
 #endif
 
 #ifndef DEF_CONST
 #define DEF_CONST(ID, CLASS)
+#define DEF_CONST_DEFINED_INTERNALLY
+#endif
+
+#ifndef DEF_INSTR
+#define DEF_INSTR(ID, OPCODE, CLASS)
+#define DEF_INSTR_DEFINED_INTERNALLY
 #endif
 
+#ifndef OP
+#define OP(OPCODE)
+#define OP_DEFINED_INTERNALLY
+#endif
+
+#ifndef OPCODES
+#define OPCODES(...)
+#define OPCODES_DEFINED_INTERNALLY
+#endif
+
+//    ClassID, Class
+
 DEF_CONST(Function, Function)
 DEF_VALUE(Argument, Argument)
 DEF_VALUE(OpaqueValue, OpaqueValue)
@@ -47,17 +70,6 @@ DEF_CONST(ConstantExpr, ConstantExpr)
 DEF_CONST(DSOLocalEquivalent, DSOLocalEquivalent)
 DEF_CONST(ConstantTokenNone, ConstantTokenNone)
 
-#ifndef DEF_INSTR
-#define DEF_INSTR(ID, OPCODE, CLASS)
-#endif
-
-#ifndef OP
-#define OP(OPCODE)
-#endif
-
-#ifndef OPCODES
-#define OPCODES(...)
-#endif
 // clang-format off
 //        ClassID,        Opcode(s),          Class
 DEF_INSTR(Opaque,         OP(Opaque),         OpaqueInst)
@@ -135,6 +147,42 @@ DEF_INSTR(ICmp,           OP(ICmp),          FCmpInst)
 DEF_INSTR(FCmp,           OP(FCmp),          ICmpInst)
 
 // clang-format on
+
+// Undefine all internally defined macros.
+
+#ifdef DEF_VALUE_DEFINED_INTERNALLY
+#undef DEF_VALUE
+#undef DEF_VALUE_DEFINED_INTERNALLY
+#endif
+
+#ifdef DEF_USER_DEFINED_INTERNALLY
+#undef DEF_USER
+#undef DEF_USER_DEFINED_INTERNALLY
+#endif
+
+#ifdef DEF_CONST_DEFINED_INTERNALLY
+#undef DEF_CONST
+#undef DEF_CONST_DEFINED_INTERNALLY
+#endif
+
+#ifdef DEF_INSTR_DEFINED_INTERNALLY
+#undef DEF_INSTR
+#undef DEF_INSTR_DEFINED_INTERNALLY
+#endif
+
+#ifdef OP_DEFINED_INTERNALLY
+#undef OP
+#undef OP_DEFINED_INTERNALLY
+#endif
+
+#ifdef OPCODES_DEFINED_INTERNALLY
+#undef OPCODES
+#undef OPCODES_DEFINED_INTERNALLY
+#endif
+
+// Undefine all externally defined macros.
+#ifndef DEF_DISABLE_AUTO_UNDEF
+
 #ifdef DEF_VALUE
 #undef DEF_VALUE
 #endif
@@ -153,3 +201,6 @@ DEF_INSTR(FCmp,           OP(FCmp),          ICmpInst)
 #ifdef OPCODES
 #undef OPCODES
 #endif
+
+#endif // DEF_DISABLE_AUTO_UNDEF
+#undef DEF_DISABLE_AUTO_UNDEF
diff --git a/llvm/include/llvm/SandboxIR/ValuesDefFilesList.def b/llvm/include/llvm/SandboxIR/ValuesDefFilesList.def
new file mode 100644
index 0000000000000..5468b5cd93ee3
--- /dev/null
+++ b/llvm/include/llvm/SandboxIR/ValuesDefFilesList.def
@@ -0,0 +1,21 @@
+//===- DefFilesList.def -----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// List of all Values.def across all SandboxIR IR specializations.
+//
+
+#ifndef DEF_SPECIALIZATION
+#define DEF_SPECIALIZATION(NAME)
+#endif
+
+DEF_SPECIALIZATION(Base)
+#include "llvm/SandboxIR/Values.def"
+DEF_SPECIALIZATION(Vec)
+#include "llvm/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizerIRValues.def"
+
+#undef DEF_SPECIALIZATION
diff --git a/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizerIR.h b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizerIR.h
new file mode 100644
index 0000000000000..c6f4e3f2e7892
--- /dev/null
+++ b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizerIR.h
@@ -0,0 +1,62 @@
+//===- SandboxVectorizerIR.h ------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines a SandboxIR specialization for the vectorizer.
+//
+
+#ifndef LLVM_TRANSFORMS_VECTORIZE_SANDBOXVEC_SANDBOXVECTORIZERIR_H
+#define LLVM_TRANSFORMS_VECTORIZE_SANDBOXVEC_SANDBOXVECTORIZERIR_H
+
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/SandboxIR/Context.h"
+#include "llvm/SandboxIR/Instruction.h"
+#include "llvm/Support/ErrorHandling.h"
+
+namespace llvm::sandboxir {
+
+class SBVecContext;
+
+class PackInst final : public Instruction {
+  Use getOperandUseInternal(unsigned OperandIdx, bool Verify) const final {
+    llvm_unreachable("Unimplemented");
+  }
+  unsigned getUseOperandNo(const Use &Use) const final {
+    llvm_unreachable("Unimplemented");
+  }
+  SmallVector<llvm::Instruction *, 1> getLLVMInstrs() const final {
+    llvm_unreachable("Unimplemented");
+  }
+  unsigned getNumOfIRInstrs() const final { llvm_unreachable("Unimplemented"); }
+
+  friend class SBVecContext;
+  PackInst(ArrayRef<llvm::Instruction *> LLVMInstrs, Context &Ctx)
+      : Instruction(ClassID::Pack, Opcode::Pack, LLVMInstrs[0], Ctx) {
+    Ctx.assertSpecialization(SandboxIRSpecialization::Vec);
+  }
+
+public:
+  static Value *create(ArrayRef<Value *> PackOps, InsertPosition InsertBefore,
+                       SBVecContext &Ctx);
+
+  /// For isa/dyn_cast.
+  static bool classof(const Value *From);
+};
+
+class SBVecContext : public Context {
+  // Pack
+  PackInst *createPackInst(ArrayRef<llvm::Instruction *> PackInstrs);
+  friend class PackInst; // For createPackInst()
+
+public:
+  SBVecContext(llvm::LLVMContext &LLVMCtx)
+      : Context(LLVMCtx, SandboxIRSpecialization::Vec) {}
+};
+
+} // namespace llvm::sandboxir
+
+#endif // LLVM_TRANSFORMS_VECTORIZE_SANDBOXVEC_SANDBOXVECTORIZERIR_H
diff --git a/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizerIRValues.def b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizerIRValues.def
new file mode 100644
index 0000000000000..d5b8087d079d0
--- /dev/null
+++ b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizerIRValues.def
@@ -0,0 +1,52 @@
+//===- SandboxVectorizerIRValues.def ----------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// NOTE: Please #define DEF_DISABLE_AUTO_UNDEF before including more than one
+//       .def file to stop the .def file from automatically undefying macros.
+//
+
+#ifndef DEF_INSTR
+#define DEF_INSTR(ID, OPCODE, CLASS)
+#define DEF_INSTR_DEFINED_HERE
+#endif
+
+
+// SandboxVectorizerIR Instructions
+DEF_INSTR(Pack,           OP(Pack),          PackInst)
+
+
+// Undefine all externally defined macros.
+#ifdef DEF_INSTR_DEFINED_INTERNALLY
+#undef DEF_INSTR
+#undef DEF_INSTR_DEFINED_INTERNALLY
+#endif
+
+// Undefine all externally defined macros.
+#ifndef DEF_DISABLE_AUTO_UNDEF
+
+#ifdef DEF_VALUE
+#undef DEF_VALUE
+#endif
+#ifdef DEF_USER
+#undef DEF_USER
+#endif
+#ifdef DEF_CONST
+#undef DEF_CONST
+#endif
+#ifdef DEF_INSTR
+#undef DEF_INSTR
+#endif
+#ifdef OP
+#undef OP
+#endif
+#ifdef OPCODES
+#undef OPCODES
+#endif
+
+#endif // DEF_DISABLE_AUTO_UNDEF
+#undef DEF_DISABLE_AUTO_UNDEF
diff --git a/llvm/lib/SandboxIR/Context.cpp b/llvm/lib/SandboxIR/Context.cpp
index bf2ecda344824..8ebce584d5786 100644
--- a/llvm/lib/SandboxIR/Context.cpp
+++ b/llvm/lib/SandboxIR/Context.cpp
@@ -644,8 +644,8 @@ Value *Context::getValue(llvm::Value *V) const {
   return nullptr;
 }
 
-Context::Context(LLVMContext &LLVMCtx)
-    : LLVMCtx(LLVMCtx), IRTracker(*this),
+Context::Context(LLVMContext &LLVMCtx, SandboxIRSpecialization Specialization)
+    : Specialization(Specialization), LLVMCtx(LLVMCtx), IRTracker(*this),
       LLVMIRBuilder(LLVMCtx, ConstantFolder()) {}
 
 Context::~Context() = default;
diff --git a/llvm/lib/SandboxIR/Instruction.cpp b/llvm/lib/SandboxIR/Instruction.cpp
index 3f9be0d70ff89..bbcccf24cf3f4 100644
--- a/llvm/lib/SandboxIR/Instruction.cpp
+++ b/llvm/lib/SandboxIR/Instruction.cpp
@@ -11,18 +11,6 @@
 
 namespace llvm::sandboxir {
 
-const char *Instruction::getOpcodeName(Opcode Opc) {
-  switch (Opc) {
-#define OP(OPC)                                                                \
-  case Opcode::OPC:                                                            \
-    return #OPC;
-#define OPCODES(...) __VA_ARGS__
-#define DEF_INSTR(ID, OPC, CLASS) OPC
-#include "llvm/SandboxIR/Values.def"
-  }
-  llvm_unreachable("Unknown Opcode");
-}
-
 llvm::Instruction *Instruction::getTopmostLLVMInstruction() const {
   Instruction *Prev = getPrevNode();
   if (Prev == nullptr) {
diff --git a/llvm/lib/Transforms/Vectorize/CMakeLists.txt b/llvm/lib/Transforms/Vectorize/CMakeLists.txt
index 9f4a242214471..6c0427a1df892 100644
--- a/llvm/lib/Transforms/Vectorize/CMakeLists.txt
+++ b/llvm/lib/Transforms/Vectorize/CMakeLists.txt
@@ -15,6 +15,7 @@ add_llvm_component_library(LLVMVectorize
   SandboxVectorizer/Passes/TransactionAcceptOrRevert.cpp
   SandboxVectorizer/Passes/TransactionSave.cpp
   SandboxVectorizer/SandboxVectorizer.cpp
+  SandboxVectorizer/SandboxVectorizerIR.cpp
   SandboxVectorizer/SandboxVectorizerPassBuilder.cpp
   SandboxVectorizer/Scheduler.cpp
   SandboxVectorizer/SeedCollector.cpp
diff --git a/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Legality.cpp b/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Legality.cpp
index cac43241f6095..aa32baa383277 100644
--- a/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Legality.cpp
+++ b/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Legality.cpp
@@ -171,6 +171,7 @@ LegalityAnalysis::notVectorizableBasedOnOpcodesAndTypes(
   case Instruction::Opcode::Call:
   case Instruction::Opcode::GetElementPtr:
   case Instruction::Opcode::Switch:
+  case Instruction::Opcode::Pack:
     return ResultReason::Unimplemented;
   case Instruction::Opcode::VAArg:
   case Instruction::Opcode::Freeze:
diff --git a/llvm/lib/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizerIR.cpp b/llvm/lib/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizerIR.cpp
new file mode 100644
index 0000000000000..f175eba8d4f39
--- /dev/null
+++ b/llvm/lib/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizerIR.cpp
@@ -0,0 +1,48 @@
+//===- SandboxVectorizerIR.cpp - Sandbox IR Specialization ----------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizerIR.h"
+#include "llvm/SandboxIR/Type.h"
+#include "llvm/Transforms/Vectorize/SandboxVectorizer/VecUtils.h"
+
+namespace llvm::sandboxir {
+
+Value *PackInst::create(ArrayRef<Value *> PackOps, InsertPosition InsertBefore,
+                        SBVecContext &Ctx) {
+  auto &Builder = Instruction::setInsertPos(InsertBefore);
+  // TODO: Replace with actual instruction sequence!
+  auto *C = ConstantInt::get(Type::getInt32Ty(Ctx), 0);
+  auto *LLVMC = cast<llvm::Constant>(C->Val);
+  auto *LLVMVecTy = llvm::FixedVectorType::get(PackOps[0]->Val->getType(), 2);
+  auto *LLVMPoison = llvm::PoisonValue::get(LLVMVecTy);
+  llvm::Value *NewV =
+      Builder.CreateInsertElement(LLVMPoison, PackOps[0]->Val, LLVMC, "TEST");
+
+  if (auto *NewInsert = dyn_cast<llvm::InsertElementInst>(NewV))
+    return Ctx.createPackInst({NewInsert});
+  assert(isa<llvm::Constant>(NewV) && "Expected constant");
+  return Ctx.getOrCreateConstant(cast<llvm::Constant>(NewV));
+}
+
+bool PackInst::classof(const Value *From) {
+  return From->getSubclassID() == ClassID::Pack;
+}
+
+PackInst *
+SBVecContext::createPackInst(ArrayRef<llvm::Instruction *> PackInstrs) {
+  assert(all_of(PackInstrs,
+                [](llvm::Value *V) {
+                  return isa<llvm::InsertElementInst>(V) ||
+                         isa<llvm::ExtractElementInst>(V);
+                }) &&
+         "Expected inserts or extracts!");
+  auto NewPtr = std::unique_ptr<PackInst>(new PackInst(PackInstrs, *this));
+  return cast<PackInst>(registerValue(std::move(NewPtr)));
+}
+
+} // namespace llvm::sandboxir
diff --git a/llvm/unittests/SandboxIR/SandboxIRTest.cpp b/llvm/unittests/SandboxIR/SandboxIRTest.cpp
index 06a1227b71a56..36144401dcfcb 100644
--- a/llvm/unittests/SandboxIR/SandboxIRTest.cpp
+++ b/llvm/unittests/SandboxIR/SandboxIRTest.cpp
@@ -6219,6 +6219,7 @@ define void @foo() {
 
 /// Makes sure that all Instruction sub-classes have a classof().
 TEST_F(SandboxIRTest, CheckClassof) {
+#define DEF_ENABLE_AUTO_UNDEF
 #define DEF_INSTR(ID, OPC, CLASS)                                              \
   EXPECT_NE(&sandboxir::CLASS::classof, &sandboxir::Instruction::classof);
 #include "llvm/SandboxIR/Values.def"
diff --git a/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/CMakeLists.txt b/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/CMakeLists.txt
index 104a27975cfc0..40f28c0c45271 100644
--- a/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/CMakeLists.txt
+++ b/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/CMakeLists.txt
@@ -12,6 +12,7 @@ add_llvm_unittest(SandboxVectorizerTests
   InstrMapsTest.cpp
   IntervalTest.cpp
   LegalityTest.cpp
+  SandboxVectorizerIRTest.cpp
   SandboxVectorizerTest.cpp
   SchedulerTest.cpp
   SeedCollectorTest.cpp	
diff --git a/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizerIRTest.cpp b/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizerIRTest.cpp
new file mode 100644
index 0000000000000..8108b148df884
--- /dev/null
+++ b/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizerIRTest.cpp
@@ -0,0 +1,57 @@
+//===- SandboxVectorizerIRTest.cpp ----------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizerIR.h"
+#include "llvm/AsmParser/Parser.h"
+#include "llvm/SandboxIR/BasicBlock.h"
+#include "llvm/SandboxIR/Function.h"
+#include "llvm/Support/SourceMgr.h"
+#include "llvm/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizer.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+struct SandboxVectorizerIRTest : public testing::Test {
+  LLVMContext C;
+  std::unique_ptr<Module> M;
+
+  void parseIR(LLVMContext &C, const char *IR) {
+    SMDiagnostic Err;
+    M = parseAssemblyString(IR, Err, C);
+    if (!M)
+      Err.print("SandboxIRTest", errs());
+  }
+  BasicBlock *getBasicBlockByName(Function &F, StringRef Name) {
+    for (BasicBlock &BB : F)
+      if (BB.getName() == Name)
+        return &BB;
+    llvm_unreachable("Expected to find basic block!");
+  }
+};
+
+TEST_F(SandboxVectorizerIRTest, Basic) {
+  parseIR(C, R"IR(
+define void @foo(i8 %v0, i8 %v1) {
+  ret void
+}
+)IR");
+  Function &LLVMF = *M->getFunction("foo");
+  sandboxir::SBVecContext Ctx(C);
+  auto &F = *Ctx.createFunction(&LLVMF);
+  auto &BB = *F.begin();
+  auto *Arg0 = F.getArg(0);
+  auto *Arg1 = F.getArg(1);
+
+  // Check that we can access the new opcode Opcode::Pack and retrieve its name.
+  EXPECT_EQ(llvm::StringRef(sandboxir::Instruction::getOpcodeName(
+                sandboxir::Instruction::Opcode::Pack)),
+            "Pack");
+  auto *PackI = sandboxir::PackInst::create({Arg0, Arg1}, BB.begin(), Ctx);
+  // Check the class ID.
+  EXPECT_EQ(PackI->getSubclassID(), sandboxir::Value::ClassID::Pack);
+}

>From d2ff35398b464c759ca103dbc851a3678be9f740 Mon Sep 17 00:00:00 2001
From: Vasileios Porpodas <vasileios.porpodas at amd.com>
Date: Tue, 31 Mar 2026 20:55:01 +0000
Subject: [PATCH 2/2] fixup! [SandboxVec] SandboxVectorizerIR Boilerplate

---
 llvm/include/llvm/SandboxIR/Context.h             | 15 +--------------
 .../include/llvm/SandboxIR/ValuesDefFilesList.def | 10 +---------
 .../SandboxVectorizer/SandboxVectorizerIR.h       |  7 ++-----
 llvm/lib/SandboxIR/Context.cpp                    |  4 ++--
 4 files changed, 6 insertions(+), 30 deletions(-)

diff --git a/llvm/include/llvm/SandboxIR/Context.h b/llvm/include/llvm/SandboxIR/Context.h
index d37465860f615..0c936b138e7c5 100644
--- a/llvm/include/llvm/SandboxIR/Context.h
+++ b/llvm/include/llvm/SandboxIR/Context.h
@@ -30,19 +30,8 @@ class Region;
 class Value;
 class Use;
 
-enum class SandboxIRSpecialization {
-#define DEF_SPECIALIZATION(NAME) NAME,
-#include "llvm/SandboxIR/ValuesDefFilesList.def"
-};
-
 class Context {
-  SandboxIRSpecialization Specialization = SandboxIRSpecialization::Base;
-
 public:
-  SandboxIRSpecialization getSpecialization() const { return Specialization; }
-  void assertSpecialization(SandboxIRSpecialization S) const {
-    assert(Specialization == S && "Unexpected SandboxIR Specialization!");
-  }
   // A EraseInstrCallback receives the instruction about to be erased.
   using EraseInstrCallback = std::function<void(Instruction *)>;
   // A CreateInstrCallback receives the instruction about to be created.
@@ -250,9 +239,7 @@ class Context {
   friend FCmpInst; // For createFCmpInst()
 
 public:
-  LLVM_ABI
-  Context(LLVMContext &LLVMCtx, SandboxIRSpecialization Specialization =
-                                    SandboxIRSpecialization::Base);
+  LLVM_ABI Context(LLVMContext &LLVMCtx);
   LLVM_ABI ~Context();
   /// Clears function-level state.
   LLVM_ABI void clear();
diff --git a/llvm/include/llvm/SandboxIR/ValuesDefFilesList.def b/llvm/include/llvm/SandboxIR/ValuesDefFilesList.def
index 5468b5cd93ee3..76af72ea899b2 100644
--- a/llvm/include/llvm/SandboxIR/ValuesDefFilesList.def
+++ b/llvm/include/llvm/SandboxIR/ValuesDefFilesList.def
@@ -6,16 +6,8 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// List of all Values.def across all SandboxIR IR specializations.
+// List of all *Values.def across all SandboxIR IR specializations.
 //
 
-#ifndef DEF_SPECIALIZATION
-#define DEF_SPECIALIZATION(NAME)
-#endif
-
-DEF_SPECIALIZATION(Base)
 #include "llvm/SandboxIR/Values.def"
-DEF_SPECIALIZATION(Vec)
 #include "llvm/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizerIRValues.def"
-
-#undef DEF_SPECIALIZATION
diff --git a/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizerIR.h b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizerIR.h
index c6f4e3f2e7892..f2988bc8377ec 100644
--- a/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizerIR.h
+++ b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizerIR.h
@@ -35,9 +35,7 @@ class PackInst final : public Instruction {
 
   friend class SBVecContext;
   PackInst(ArrayRef<llvm::Instruction *> LLVMInstrs, Context &Ctx)
-      : Instruction(ClassID::Pack, Opcode::Pack, LLVMInstrs[0], Ctx) {
-    Ctx.assertSpecialization(SandboxIRSpecialization::Vec);
-  }
+      : Instruction(ClassID::Pack, Opcode::Pack, LLVMInstrs[0], Ctx) {}
 
 public:
   static Value *create(ArrayRef<Value *> PackOps, InsertPosition InsertBefore,
@@ -53,8 +51,7 @@ class SBVecContext : public Context {
   friend class PackInst; // For createPackInst()
 
 public:
-  SBVecContext(llvm::LLVMContext &LLVMCtx)
-      : Context(LLVMCtx, SandboxIRSpecialization::Vec) {}
+  SBVecContext(llvm::LLVMContext &LLVMCtx) : Context(LLVMCtx) {}
 };
 
 } // namespace llvm::sandboxir
diff --git a/llvm/lib/SandboxIR/Context.cpp b/llvm/lib/SandboxIR/Context.cpp
index 8ebce584d5786..bf2ecda344824 100644
--- a/llvm/lib/SandboxIR/Context.cpp
+++ b/llvm/lib/SandboxIR/Context.cpp
@@ -644,8 +644,8 @@ Value *Context::getValue(llvm::Value *V) const {
   return nullptr;
 }
 
-Context::Context(LLVMContext &LLVMCtx, SandboxIRSpecialization Specialization)
-    : Specialization(Specialization), LLVMCtx(LLVMCtx), IRTracker(*this),
+Context::Context(LLVMContext &LLVMCtx)
+    : LLVMCtx(LLVMCtx), IRTracker(*this),
       LLVMIRBuilder(LLVMCtx, ConstantFolder()) {}
 
 Context::~Context() = default;



More information about the llvm-commits mailing list