[llvm] e8574e8 - [SandboxIR] Boilerplate code (#95814)

via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 1 08:50:44 PDT 2024


Author: vporpo
Date: 2024-07-01T08:50:40-07:00
New Revision: e8574e8ada76e38fab951969dc1c97eef5b0cc60

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

LOG: [SandboxIR] Boilerplate code (#95814)

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 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`, `User` and `Context` classes.

Added: 
    llvm/include/llvm/SandboxIR/SandboxIR.h
    llvm/include/llvm/SandboxIR/SandboxIRValues.def
    llvm/lib/SandboxIR/CMakeLists.txt
    llvm/lib/SandboxIR/SandboxIR.cpp
    llvm/unittests/SandboxIR/CMakeLists.txt
    llvm/unittests/SandboxIR/SandboxIRTest.cpp

Modified: 
    llvm/lib/CMakeLists.txt
    llvm/unittests/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/SandboxIR/SandboxIR.h b/llvm/include/llvm/SandboxIR/SandboxIR.h
new file mode 100644
index 0000000000000..ec7ec1a268fa7
--- /dev/null
+++ b/llvm/include/llvm/SandboxIR/SandboxIR.h
@@ -0,0 +1,158 @@
+//===- 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 hierarchy 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/SandboxIR/SandboxIRValues.def"
+  };
+
+protected:
+  static const char *getSubclassIDStr(ClassID ID) {
+    switch (ID) {
+#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;
+#include "llvm/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 &Ctx;
+  // 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 &Ctx);
+  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 &Ctx) : Value(ID, V, Ctx) {}
+  /// 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 &LLVMCtx;
+
+public:
+  Context(LLVMContext &LLVMCtx) : LLVMCtx(LLVMCtx) {}
+};
+} // namespace sandboxir
+} // namespace llvm
+
+#endif // LLVM_TRANSFORMS_SANDBOXIR_SANDBOXIR_H

diff  --git a/llvm/include/llvm/SandboxIR/SandboxIRValues.def b/llvm/include/llvm/SandboxIR/SandboxIRValues.def
new file mode 100644
index 0000000000000..d41d8dce56e68
--- /dev/null
+++ b/llvm/include/llvm/SandboxIR/SandboxIRValues.def
@@ -0,0 +1,26 @@
+//===- 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
+//
+//===----------------------------------------------------------------------===//
+
+//    ClassID, Class
+DEF_USER(User, sandboxir::User)
+
+#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/CMakeLists.txt b/llvm/lib/CMakeLists.txt
index 74e2d03c07953..08f198679551d 100644
--- a/llvm/lib/CMakeLists.txt
+++ b/llvm/lib/CMakeLists.txt
@@ -33,6 +33,7 @@ add_subdirectory(DebugInfo)
 add_subdirectory(DWP)
 add_subdirectory(ExecutionEngine)
 add_subdirectory(Target)
+add_subdirectory(SandboxIR)
 add_subdirectory(AsmParser)
 add_subdirectory(LineEditor)
 add_subdirectory(ProfileData)

diff  --git a/llvm/lib/SandboxIR/CMakeLists.txt b/llvm/lib/SandboxIR/CMakeLists.txt
new file mode 100644
index 0000000000000..225eca0cadd1a
--- /dev/null
+++ b/llvm/lib/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/SandboxIR/SandboxIR.cpp b/llvm/lib/SandboxIR/SandboxIR.cpp
new file mode 100644
index 0000000000000..70101ab10ff12
--- /dev/null
+++ b/llvm/lib/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/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 &Ctx)
+    : SubclassID(SubclassID), Val(Val), Ctx(Ctx) {
+#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/CMakeLists.txt b/llvm/unittests/CMakeLists.txt
index b2f10b2185880..696926110df7a 100644
--- a/llvm/unittests/CMakeLists.txt
+++ b/llvm/unittests/CMakeLists.txt
@@ -43,6 +43,7 @@ add_subdirectory(Option)
 add_subdirectory(Remarks)
 add_subdirectory(Passes)
 add_subdirectory(ProfileData)
+add_subdirectory(SandboxIR)
 add_subdirectory(Support)
 add_subdirectory(TableGen)
 add_subdirectory(Target)

diff  --git a/llvm/unittests/SandboxIR/CMakeLists.txt b/llvm/unittests/SandboxIR/CMakeLists.txt
new file mode 100644
index 0000000000000..1cce736b2d8b7
--- /dev/null
+++ b/llvm/unittests/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/SandboxIR/SandboxIRTest.cpp b/llvm/unittests/SandboxIR/SandboxIRTest.cpp
new file mode 100644
index 0000000000000..14e6e745f757a
--- /dev/null
+++ b/llvm/unittests/SandboxIR/SandboxIRTest.cpp
@@ -0,0 +1,42 @@
+//===- 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/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 Ctx(C);
+  [[maybe_unused]] sandboxir::User U(sandboxir::Value::ClassID::User, Ret, Ctx);
+}


        


More information about the llvm-commits mailing list