Skip to content

Commit bda2114

Browse files
committed
[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.
1 parent d1a4f0c commit bda2114

File tree

10 files changed

+331
-0
lines changed

10 files changed

+331
-0
lines changed
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
//===- SandboxIR.h ----------------------------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// Sandbox IR is a lightweight overlay transactional IR on top of LLVM IR.
10+
// Features:
11+
// - You can save/rollback the state of the IR at any time.
12+
// - Any changes made to Sandbox IR will automatically update the underlying
13+
// LLVM IR so both IRs are always in sync.
14+
// - Feels like LLVM IR, similar API.
15+
//
16+
// SandboxIR forms a class hierarchy that resembles that of LLVM IR
17+
// but is in the `sandboxir` namespace:
18+
//
19+
// +- Argument +- Constant +- OpaqueInst
20+
// | | |
21+
// Value -+- User ------+- Instruction -+- InsertElementInst
22+
// | |
23+
// +- BasicBlock +- ExtractElementInst
24+
// | |
25+
// +- Function +- ShuffleVectorInst
26+
// |
27+
// +- StoreInst
28+
// |
29+
// +- LoadInst
30+
// |
31+
// +- CmpInst
32+
// |
33+
// +- CastInst
34+
// |
35+
// +- PHINode
36+
// |
37+
// +- SelectInst
38+
// |
39+
// +- BinaryOperator
40+
// |
41+
// +- UnaryOperator
42+
//
43+
// Use
44+
//
45+
#ifndef LLVM_TRANSFORMS_SANDBOXIR_SANDBOXIR_H
46+
#define LLVM_TRANSFORMS_SANDBOXIR_SANDBOXIR_H
47+
48+
#include "llvm/IR/User.h"
49+
#include "llvm/IR/Value.h"
50+
#include "llvm/Support/raw_ostream.h"
51+
52+
namespace llvm {
53+
54+
namespace sandboxir {
55+
56+
class Context;
57+
58+
/// A SandboxIR Value has users. This is the base class.
59+
class Value {
60+
public:
61+
enum class ClassID : unsigned {
62+
#define DEF_VALUE(ID, CLASS) ID,
63+
#define DEF_USER(ID, CLASS) ID,
64+
#define DEF_INSTR(ID, OPC, CLASS) ID,
65+
#include "llvm/Transforms/SandboxIR/SandboxIRValues.def"
66+
};
67+
68+
protected:
69+
static const char *getSubclassIDStr(ClassID ID) {
70+
switch (ID) {
71+
// clang-format off
72+
#define DEF_VALUE(ID, CLASS) case ClassID::ID: return #ID;
73+
#define DEF_USER(ID, CLASS) case ClassID::ID: return #ID;
74+
#define DEF_INSTR(ID, OPC, CLASS) case ClassID::ID: return #ID;
75+
// clang-format on
76+
#include "llvm/Transforms/SandboxIR/SandboxIRValues.def"
77+
}
78+
llvm_unreachable("Unimplemented ID");
79+
}
80+
81+
/// For isa/dyn_cast.
82+
ClassID SubclassID;
83+
#ifndef NDEBUG
84+
/// A unique ID used for forming the name (used for debugging).
85+
unsigned UID;
86+
#endif
87+
/// The LLVM Value that corresponds to this SandboxIR Value.
88+
/// NOTE: Some SBInstructions, like Packs, may include more than one value.
89+
llvm::Value *Val = nullptr;
90+
91+
/// All values point to the context.
92+
Context &Ctxt;
93+
// This is used by eraseFromParent().
94+
void clearValue() { Val = nullptr; }
95+
template <typename ItTy, typename SBTy> friend class LLVMOpUserItToSBTy;
96+
97+
public:
98+
Value(ClassID SubclassID, llvm::Value *Val, Context &Ctxt);
99+
virtual ~Value() = default;
100+
ClassID getSubclassID() const { return SubclassID; }
101+
102+
Type *getType() const { return Val->getType(); }
103+
104+
Context &getContext() const;
105+
#ifndef NDEBUG
106+
/// Should crash if there is something wrong with the instruction.
107+
virtual void verify() const = 0;
108+
/// Returns the name in the form 'SB<number>.' like 'SB1.'
109+
std::string getName() const;
110+
virtual void dumpCommonHeader(raw_ostream &OS) const;
111+
void dumpCommonFooter(raw_ostream &OS) const;
112+
void dumpCommonPrefix(raw_ostream &OS) const;
113+
void dumpCommonSuffix(raw_ostream &OS) const;
114+
void printAsOperandCommon(raw_ostream &OS) const;
115+
#endif
116+
};
117+
118+
class User : public Value {
119+
public:
120+
User(ClassID ID, llvm::Value *V, Context &Ctxt) : Value(ID, V, Ctxt) {}
121+
/// For isa/dyn_cast.
122+
static bool classof(const Value *From);
123+
#ifndef NDEBUG
124+
void verify() const override {
125+
assert(isa<llvm::User>(Val) && "Expected User!");
126+
}
127+
void dumpCommonHeader(raw_ostream &OS) const final;
128+
#endif
129+
};
130+
131+
class Context {
132+
protected:
133+
LLVMContext &LLVMCtxt;
134+
135+
public:
136+
Context(LLVMContext &LLVMCtxt) : LLVMCtxt(LLVMCtxt) {}
137+
};
138+
} // namespace sandboxir
139+
} // namespace llvm
140+
141+
#endif // LLVM_TRANSFORMS_SANDBOXIR_SANDBOXIR_H
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//===- SandboxIRValues.def --------------------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// clang-format off
10+
11+
// ClassID, Class
12+
DEF_USER(User, sandboxir::User)
13+
14+
// clang-format on
15+
#ifdef DEF_VALUE
16+
#undef DEF_VALUE
17+
#endif
18+
#ifdef DEF_USER
19+
#undef DEF_USER
20+
#endif
21+
#ifdef DEF_INSTR
22+
#undef DEF_INSTR
23+
#endif
24+
#ifdef OPCODES
25+
#undef OPCODES
26+
#endif
27+
#ifdef OP
28+
#undef OP
29+
#endif

llvm/lib/Transforms/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ add_subdirectory(ObjCARC)
1010
add_subdirectory(Coroutines)
1111
add_subdirectory(CFGuard)
1212
add_subdirectory(HipStdPar)
13+
add_subdirectory(SandboxIR)
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
add_llvm_component_library(LLVMSandboxIR
2+
SandboxIR.cpp
3+
4+
ADDITIONAL_HEADER_DIRS
5+
${LLVM_MAIN_INCLUDE_DIR}/llvm/Transforms/SandboxIR
6+
7+
LINK_COMPONENTS
8+
Core
9+
Support
10+
)
11+
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
//===- SandboxIR.cpp - A transactional overlay IR on top of LLVM IR -------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "llvm/Transforms/SandboxIR/SandboxIR.h"
10+
#include "llvm/Support/Debug.h"
11+
#include <sstream>
12+
13+
using namespace llvm;
14+
using namespace sandboxir;
15+
16+
sandboxir::Value::Value(ClassID SubclassID, llvm::Value *Val, Context &Ctxt)
17+
: SubclassID(SubclassID), Val(Val), Ctxt(Ctxt) {
18+
#ifndef NDEBUG
19+
UID = 0; // FIXME: Once SBContext is available.
20+
#endif
21+
}
22+
23+
#ifndef NDEBUG
24+
std::string sandboxir::Value::getName() const {
25+
std::stringstream SS;
26+
SS << "SB" << UID << ".";
27+
return SS.str();
28+
}
29+
30+
void sandboxir::Value::dumpCommonHeader(raw_ostream &OS) const {
31+
OS << getName() << " " << getSubclassIDStr(SubclassID) << " ";
32+
}
33+
34+
void sandboxir::Value::dumpCommonFooter(raw_ostream &OS) const {
35+
OS.indent(2) << "Val: ";
36+
if (Val)
37+
OS << *Val;
38+
else
39+
OS << "NULL";
40+
OS << "\n";
41+
}
42+
43+
void sandboxir::Value::dumpCommonPrefix(raw_ostream &OS) const {
44+
if (Val)
45+
OS << *Val;
46+
else
47+
OS << "NULL ";
48+
}
49+
50+
void sandboxir::Value::dumpCommonSuffix(raw_ostream &OS) const {
51+
OS << " ; " << getName() << " (" << getSubclassIDStr(SubclassID) << ") "
52+
<< this;
53+
}
54+
55+
void sandboxir::Value::printAsOperandCommon(raw_ostream &OS) const {
56+
if (Val)
57+
Val->printAsOperand(OS);
58+
else
59+
OS << "NULL ";
60+
}
61+
62+
void sandboxir::User::dumpCommonHeader(raw_ostream &OS) const {
63+
Value::dumpCommonHeader(OS);
64+
// TODO: This is incomplete
65+
}
66+
#endif // NDEBUG

llvm/unittests/Transforms/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ add_subdirectory(IPO)
44
add_subdirectory(Scalar)
55
add_subdirectory(Utils)
66
add_subdirectory(Vectorize)
7+
add_subdirectory(SandboxIR)
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
set(LLVM_LINK_COMPONENTS
2+
AsmParser
3+
SandboxIR
4+
)
5+
6+
add_llvm_unittest(SandboxIRTests
7+
SandboxIRTest.cpp
8+
)
9+
10+
set_property(TARGET SandboxIRTests PROPERTY FOLDER "Tests/UnitTests/TransformsTests")
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
//===- SandboxIRTest.cpp --------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "llvm/Transforms/SandboxIR/SandboxIR.h"
10+
#include "llvm/AsmParser/Parser.h"
11+
#include "llvm/IR/BasicBlock.h"
12+
#include "llvm/IR/Function.h"
13+
#include "llvm/IR/Instruction.h"
14+
#include "llvm/IR/Module.h"
15+
#include "llvm/Support/SourceMgr.h"
16+
#include "gtest/gtest.h"
17+
18+
using namespace llvm;
19+
20+
struct SandboxIRTest : public testing::Test {
21+
LLVMContext C;
22+
std::unique_ptr<Module> M;
23+
24+
void parseIR(LLVMContext &C, const char *IR) {
25+
SMDiagnostic Err;
26+
M = parseAssemblyString(IR, Err, C);
27+
if (!M)
28+
Err.print("SandboxIRTest", errs());
29+
}
30+
};
31+
32+
TEST_F(SandboxIRTest, UserInstantiation) {
33+
parseIR(C, R"IR(
34+
define void @foo(i32 %v1) {
35+
ret void
36+
}
37+
)IR");
38+
Function &F = *M->getFunction("foo");
39+
auto *Ret = F.begin()->getTerminator();
40+
sandboxir::Context Ctxt(C);
41+
sandboxir::User U(sandboxir::Value::ClassID::User, Ret, Ctxt);
42+
(void)U;
43+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
static_library("SandboxIR") {
2+
output_name = "LLVMSandboxIR"
3+
deps = [
4+
"//llvm/lib/IR",
5+
"//llvm/lib/Support",
6+
]
7+
sources = [
8+
"SandboxIR.cpp",
9+
]
10+
}

utils/bazel/llvm-project-overlay/llvm/BUILD.bazel

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1467,6 +1467,23 @@ cc_library(
14671467
],
14681468
)
14691469

1470+
cc_library(
1471+
name = "SandboxIR",
1472+
srcs = glob([
1473+
"lib/Transforms/SandboxIR/*.cpp",
1474+
]),
1475+
hdrs = glob([
1476+
"include/llvm/Transforms/SandboxIR/*.h",
1477+
"include/llvm/Transforms/SandboxIR/*.def",
1478+
]),
1479+
copts = llvm_copts,
1480+
deps = [
1481+
":Core",
1482+
":Support",
1483+
":config",
1484+
],
1485+
)
1486+
14701487
cc_library(
14711488
name = "Vectorize",
14721489
srcs = glob([
@@ -1826,6 +1843,7 @@ cc_library(
18261843
":InstCombine",
18271844
":Instrumentation",
18281845
":ObjCARC",
1846+
":SandboxIR",
18291847
":Scalar",
18301848
":Vectorize",
18311849
],
@@ -2658,6 +2676,7 @@ cc_library(
26582676
":Instrumentation",
26592677
":MC",
26602678
":ObjCARC",
2679+
":SandboxIR",
26612680
":Scalar",
26622681
":Support",
26632682
":Target",

0 commit comments

Comments
 (0)