[llvm] [SandboxIR] Boilerplate code (PR #95814)

via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 27 15:12:33 PDT 2024


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

>From d255835315153b6718b30b4bbd0bbc7f9a688af5 Mon Sep 17 00:00:00 2001
From: Vasileios Porpodas <vporpodas at google.com>
Date: Mon, 17 Jun 2024 10:06:29 -0700
Subject: [PATCH] [SandboxIR] Boilerplate code

This is the first patch in a series of patches for the Sandbox Vectorizer
project.
SandboxIR is not tightly coupled to the Sandbox Vectorizer and could be used
independently as a transactional layer on top of LLVM IR.

For a more detailed description of the project please refer to the RFC:
https://discourse.llvm.org/t/rfc-sandbox-vectorizer-an-experimental-modular-vectorizer/79059

This patch adds some basic boilerplate code for the SandboxIR which includes
parts of the SandboxIR `Value` class.
---
 .../llvm/Transforms/SandboxIR/SandboxIR.h     | 154 ++++++++++++++++++
 .../Transforms/SandboxIR/SandboxIRValues.def  |  29 ++++
 llvm/lib/Transforms/CMakeLists.txt            |   1 +
 llvm/lib/Transforms/SandboxIR/CMakeLists.txt  |  11 ++
 llvm/lib/Transforms/SandboxIR/SandboxIR.cpp   |  66 ++++++++
 llvm/unittests/Transforms/CMakeLists.txt      |   1 +
 .../Transforms/SandboxIR/CMakeLists.txt       |  10 ++
 .../Transforms/SandboxIR/SandboxIRTest.cpp    |  43 +++++
 8 files changed, 315 insertions(+)
 create mode 100644 llvm/include/llvm/Transforms/SandboxIR/SandboxIR.h
 create mode 100644 llvm/include/llvm/Transforms/SandboxIR/SandboxIRValues.def
 create mode 100644 llvm/lib/Transforms/SandboxIR/CMakeLists.txt
 create mode 100644 llvm/lib/Transforms/SandboxIR/SandboxIR.cpp
 create mode 100644 llvm/unittests/Transforms/SandboxIR/CMakeLists.txt
 create mode 100644 llvm/unittests/Transforms/SandboxIR/SandboxIRTest.cpp

diff --git a/llvm/include/llvm/Transforms/SandboxIR/SandboxIR.h b/llvm/include/llvm/Transforms/SandboxIR/SandboxIR.h
new file mode 100644
index 0000000000000..47cd46ac492f3
--- /dev/null
+++ b/llvm/include/llvm/Transforms/SandboxIR/SandboxIR.h
@@ -0,0 +1,154 @@
+//===- SandboxIR.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
+//
+//===----------------------------------------------------------------------===//
+//
+// Sandbox IR is a lightweight overlay transactional IR on top of LLVM IR.
+// Features:
+// - You can save/rollback the state of the IR at any time.
+// - Any changes made to Sandbox IR will automatically update the underlying
+//   LLVM IR so both IRs are always in sync.
+// - Feels like LLVM IR, similar API.
+//
+// SandboxIR forms a class hierarcy that resembles that of LLVM IR
+// but is in the `sandboxir` namespace:
+//
+// namespace sandboxir {
+//
+//        +- Argument                   +- BinaryOperator
+//        |                             |
+// Value -+- BasicBlock                 +- BranchInst
+//        |                             |
+//        +- Function   +- Constant     +- CastInst
+//        |             |               |
+//        +- User ------+- Instruction -+- CallInst
+//                                      |
+//                                      +- CmpInst
+//                                      |
+//                                      +- ExtractElementInst
+//                                      |
+//                                      +- GetElementPtrInst
+//                                      |
+//                                      +- InsertElementInst
+//                                      |
+//                                      +- LoadInst
+//                                      |
+//                                      +- OpaqueInst
+//                                      |
+//                                      +- PHINode
+//                                      |
+//                                      +- RetInst
+//                                      |
+//                                      +- SelectInst
+//                                      |
+//                                      +- ShuffleVectorInst
+//                                      |
+//                                      +- StoreInst
+//                                      |
+//                                      +- UnaryOperator
+//
+// Use
+//
+// } // namespace sandboxir
+//
+
+#ifndef LLVM_TRANSFORMS_SANDBOXIR_SANDBOXIR_H
+#define LLVM_TRANSFORMS_SANDBOXIR_SANDBOXIR_H
+
+#include "llvm/IR/User.h"
+#include "llvm/IR/Value.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace llvm {
+
+namespace sandboxir {
+
+class Context;
+
+/// A SandboxIR Value has users. This is the base class.
+class Value {
+public:
+  enum class ClassID : unsigned {
+#define DEF_VALUE(ID, CLASS) ID,
+#define DEF_USER(ID, CLASS) ID,
+#define DEF_INSTR(ID, OPC, CLASS) ID,
+#include "llvm/Transforms/SandboxIR/SandboxIRValues.def"
+  };
+
+protected:
+  static const char *getSubclassIDStr(ClassID ID) {
+    switch (ID) {
+      // clang-format off
+#define DEF_VALUE(ID, CLASS) case ClassID::ID: return #ID;
+#define DEF_USER(ID,  CLASS) case ClassID::ID: return #ID;
+#define DEF_INSTR(ID, OPC, CLASS) case ClassID::ID: return #ID;
+      // clang-format on
+#include "llvm/Transforms/SandboxIR/SandboxIRValues.def"
+    }
+    llvm_unreachable("Unimplemented ID");
+  }
+
+  /// For isa/dyn_cast.
+  ClassID SubclassID;
+#ifndef NDEBUG
+  /// A unique ID used for forming the name (used for debugging).
+  unsigned UID;
+#endif
+  /// The LLVM Value that corresponds to this SandboxIR Value.
+  /// NOTE: Some SBInstructions, like Packs, may include more than one value.
+  llvm::Value *Val = nullptr;
+
+  /// All values point to the context.
+  Context &Ctxt;
+  // This is used by eraseFromParent().
+  void clearValue() { Val = nullptr; }
+  template <typename ItTy, typename SBTy> friend class LLVMOpUserItToSBTy;
+
+public:
+  Value(ClassID SubclassID, llvm::Value *Val, Context &Ctxt);
+  virtual ~Value() = default;
+  ClassID getSubclassID() const { return SubclassID; }
+
+  Type *getType() const { return Val->getType(); }
+
+  Context &getContext() const;
+#ifndef NDEBUG
+  /// Should crash if there is something wrong with the instruction.
+  virtual void verify() const = 0;
+  /// Returns the name in the form 'SB<number>.' like 'SB1.'
+  std::string getName() const;
+  virtual void dumpCommonHeader(raw_ostream &OS) const;
+  void dumpCommonFooter(raw_ostream &OS) const;
+  void dumpCommonPrefix(raw_ostream &OS) const;
+  void dumpCommonSuffix(raw_ostream &OS) const;
+  void printAsOperandCommon(raw_ostream &OS) const;
+#endif
+};
+
+class User : public Value {
+public:
+  User(ClassID ID, llvm::Value *V, Context &Ctxt) : Value(ID, V, Ctxt) {}
+  /// For isa/dyn_cast.
+  static bool classof(const Value *From);
+#ifndef NDEBUG
+  void verify() const override {
+    assert(isa<llvm::User>(Val) && "Expected User!");
+  }
+  void dumpCommonHeader(raw_ostream &OS) const final;
+#endif
+};
+
+class Context {
+protected:
+  LLVMContext &LLVMCtxt;
+
+public:
+  Context(LLVMContext &LLVMCtxt) : LLVMCtxt(LLVMCtxt) {}
+};
+} // namespace sandboxir
+} // namespace llvm
+
+#endif // LLVM_TRANSFORMS_SANDBOXIR_SANDBOXIR_H
diff --git a/llvm/include/llvm/Transforms/SandboxIR/SandboxIRValues.def b/llvm/include/llvm/Transforms/SandboxIR/SandboxIRValues.def
new file mode 100644
index 0000000000000..25ec5f1259194
--- /dev/null
+++ b/llvm/include/llvm/Transforms/SandboxIR/SandboxIRValues.def
@@ -0,0 +1,29 @@
+//===- SandboxIRValues.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
+//
+//===----------------------------------------------------------------------===//
+
+// clang-format off
+
+//        ClassID,                        Class
+DEF_USER(User,                            sandboxir::User)
+
+// clang-format on
+#ifdef DEF_VALUE
+#undef DEF_VALUE
+#endif
+#ifdef DEF_USER
+#undef DEF_USER
+#endif
+#ifdef DEF_INSTR
+#undef DEF_INSTR
+#endif
+#ifdef OPCODES
+#undef OPCODES
+#endif
+#ifdef OP
+#undef OP
+#endif
diff --git a/llvm/lib/Transforms/CMakeLists.txt b/llvm/lib/Transforms/CMakeLists.txt
index 84a7e34147d08..d9857034ba1a9 100644
--- a/llvm/lib/Transforms/CMakeLists.txt
+++ b/llvm/lib/Transforms/CMakeLists.txt
@@ -10,3 +10,4 @@ add_subdirectory(ObjCARC)
 add_subdirectory(Coroutines)
 add_subdirectory(CFGuard)
 add_subdirectory(HipStdPar)
+add_subdirectory(SandboxIR)
diff --git a/llvm/lib/Transforms/SandboxIR/CMakeLists.txt b/llvm/lib/Transforms/SandboxIR/CMakeLists.txt
new file mode 100644
index 0000000000000..225eca0cadd1a
--- /dev/null
+++ b/llvm/lib/Transforms/SandboxIR/CMakeLists.txt
@@ -0,0 +1,11 @@
+add_llvm_component_library(LLVMSandboxIR
+  SandboxIR.cpp
+
+  ADDITIONAL_HEADER_DIRS
+  ${LLVM_MAIN_INCLUDE_DIR}/llvm/Transforms/SandboxIR
+
+  LINK_COMPONENTS
+  Core
+  Support
+  )
+
diff --git a/llvm/lib/Transforms/SandboxIR/SandboxIR.cpp b/llvm/lib/Transforms/SandboxIR/SandboxIR.cpp
new file mode 100644
index 0000000000000..bc33d131af1f1
--- /dev/null
+++ b/llvm/lib/Transforms/SandboxIR/SandboxIR.cpp
@@ -0,0 +1,66 @@
+//===- SandboxIR.cpp - A transactional overlay IR on top of LLVM IR -------===//
+//
+// 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/SandboxIR/SandboxIR.h"
+#include "llvm/Support/Debug.h"
+#include <sstream>
+
+using namespace llvm;
+using namespace sandboxir;
+
+sandboxir::Value::Value(ClassID SubclassID, llvm::Value *Val, Context &Ctxt)
+    : SubclassID(SubclassID), Val(Val), Ctxt(Ctxt) {
+#ifndef NDEBUG
+  UID = 0; // FIXME: Once SBContext is available.
+#endif
+}
+
+#ifndef NDEBUG
+std::string sandboxir::Value::getName() const {
+  std::stringstream SS;
+  SS << "SB" << UID << ".";
+  return SS.str();
+}
+
+void sandboxir::Value::dumpCommonHeader(raw_ostream &OS) const {
+  OS << getName() << " " << getSubclassIDStr(SubclassID) << " ";
+}
+
+void sandboxir::Value::dumpCommonFooter(raw_ostream &OS) const {
+  OS.indent(2) << "Val: ";
+  if (Val)
+    OS << *Val;
+  else
+    OS << "NULL";
+  OS << "\n";
+}
+
+void sandboxir::Value::dumpCommonPrefix(raw_ostream &OS) const {
+  if (Val)
+    OS << *Val;
+  else
+    OS << "NULL ";
+}
+
+void sandboxir::Value::dumpCommonSuffix(raw_ostream &OS) const {
+  OS << " ; " << getName() << " (" << getSubclassIDStr(SubclassID) << ") "
+     << this;
+}
+
+void sandboxir::Value::printAsOperandCommon(raw_ostream &OS) const {
+  if (Val)
+    Val->printAsOperand(OS);
+  else
+    OS << "NULL ";
+}
+
+void sandboxir::User::dumpCommonHeader(raw_ostream &OS) const {
+  Value::dumpCommonHeader(OS);
+  // TODO: This is incomplete
+}
+#endif // NDEBUG
diff --git a/llvm/unittests/Transforms/CMakeLists.txt b/llvm/unittests/Transforms/CMakeLists.txt
index 320cdf5674149..e136430c549be 100644
--- a/llvm/unittests/Transforms/CMakeLists.txt
+++ b/llvm/unittests/Transforms/CMakeLists.txt
@@ -4,3 +4,4 @@ add_subdirectory(IPO)
 add_subdirectory(Scalar)
 add_subdirectory(Utils)
 add_subdirectory(Vectorize)
+add_subdirectory(SandboxIR)
diff --git a/llvm/unittests/Transforms/SandboxIR/CMakeLists.txt b/llvm/unittests/Transforms/SandboxIR/CMakeLists.txt
new file mode 100644
index 0000000000000..1cce736b2d8b7
--- /dev/null
+++ b/llvm/unittests/Transforms/SandboxIR/CMakeLists.txt
@@ -0,0 +1,10 @@
+set(LLVM_LINK_COMPONENTS
+  AsmParser
+  SandboxIR
+  )
+
+add_llvm_unittest(SandboxIRTests
+  SandboxIRTest.cpp
+  )
+
+set_property(TARGET SandboxIRTests PROPERTY FOLDER "Tests/UnitTests/TransformsTests")
diff --git a/llvm/unittests/Transforms/SandboxIR/SandboxIRTest.cpp b/llvm/unittests/Transforms/SandboxIR/SandboxIRTest.cpp
new file mode 100644
index 0000000000000..3a2968c577be2
--- /dev/null
+++ b/llvm/unittests/Transforms/SandboxIR/SandboxIRTest.cpp
@@ -0,0 +1,43 @@
+//===- SandboxIRTest.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/SandboxIR/SandboxIR.h"
+#include "llvm/AsmParser/Parser.h"
+#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/Instruction.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Support/SourceMgr.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+struct SandboxIRTest : 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());
+  }
+};
+
+TEST_F(SandboxIRTest, UserInstantiation) {
+  parseIR(C, R"IR(
+define void @foo(i32 %v1) {
+  ret void
+}
+)IR");
+  Function &F = *M->getFunction("foo");
+  auto *Ret = F.begin()->getTerminator();
+  sandboxir::Context Ctxt(C);
+  sandboxir::User U(sandboxir::Value::ClassID::User, Ret, Ctxt);
+  (void)U;
+}



More information about the llvm-commits mailing list