Skip to content

Commit d255835

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 d255835

File tree

8 files changed

+315
-0
lines changed

8 files changed

+315
-0
lines changed
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
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 hierarcy that resembles that of LLVM IR
17+
// but is in the `sandboxir` namespace:
18+
//
19+
// namespace sandboxir {
20+
//
21+
// +- Argument +- BinaryOperator
22+
// | |
23+
// Value -+- BasicBlock +- BranchInst
24+
// | |
25+
// +- Function +- Constant +- CastInst
26+
// | | |
27+
// +- User ------+- Instruction -+- CallInst
28+
// |
29+
// +- CmpInst
30+
// |
31+
// +- ExtractElementInst
32+
// |
33+
// +- GetElementPtrInst
34+
// |
35+
// +- InsertElementInst
36+
// |
37+
// +- LoadInst
38+
// |
39+
// +- OpaqueInst
40+
// |
41+
// +- PHINode
42+
// |
43+
// +- RetInst
44+
// |
45+
// +- SelectInst
46+
// |
47+
// +- ShuffleVectorInst
48+
// |
49+
// +- StoreInst
50+
// |
51+
// +- UnaryOperator
52+
//
53+
// Use
54+
//
55+
// } // namespace sandboxir
56+
//
57+
58+
#ifndef LLVM_TRANSFORMS_SANDBOXIR_SANDBOXIR_H
59+
#define LLVM_TRANSFORMS_SANDBOXIR_SANDBOXIR_H
60+
61+
#include "llvm/IR/User.h"
62+
#include "llvm/IR/Value.h"
63+
#include "llvm/Support/raw_ostream.h"
64+
65+
namespace llvm {
66+
67+
namespace sandboxir {
68+
69+
class Context;
70+
71+
/// A SandboxIR Value has users. This is the base class.
72+
class Value {
73+
public:
74+
enum class ClassID : unsigned {
75+
#define DEF_VALUE(ID, CLASS) ID,
76+
#define DEF_USER(ID, CLASS) ID,
77+
#define DEF_INSTR(ID, OPC, CLASS) ID,
78+
#include "llvm/Transforms/SandboxIR/SandboxIRValues.def"
79+
};
80+
81+
protected:
82+
static const char *getSubclassIDStr(ClassID ID) {
83+
switch (ID) {
84+
// clang-format off
85+
#define DEF_VALUE(ID, CLASS) case ClassID::ID: return #ID;
86+
#define DEF_USER(ID, CLASS) case ClassID::ID: return #ID;
87+
#define DEF_INSTR(ID, OPC, CLASS) case ClassID::ID: return #ID;
88+
// clang-format on
89+
#include "llvm/Transforms/SandboxIR/SandboxIRValues.def"
90+
}
91+
llvm_unreachable("Unimplemented ID");
92+
}
93+
94+
/// For isa/dyn_cast.
95+
ClassID SubclassID;
96+
#ifndef NDEBUG
97+
/// A unique ID used for forming the name (used for debugging).
98+
unsigned UID;
99+
#endif
100+
/// The LLVM Value that corresponds to this SandboxIR Value.
101+
/// NOTE: Some SBInstructions, like Packs, may include more than one value.
102+
llvm::Value *Val = nullptr;
103+
104+
/// All values point to the context.
105+
Context &Ctxt;
106+
// This is used by eraseFromParent().
107+
void clearValue() { Val = nullptr; }
108+
template <typename ItTy, typename SBTy> friend class LLVMOpUserItToSBTy;
109+
110+
public:
111+
Value(ClassID SubclassID, llvm::Value *Val, Context &Ctxt);
112+
virtual ~Value() = default;
113+
ClassID getSubclassID() const { return SubclassID; }
114+
115+
Type *getType() const { return Val->getType(); }
116+
117+
Context &getContext() const;
118+
#ifndef NDEBUG
119+
/// Should crash if there is something wrong with the instruction.
120+
virtual void verify() const = 0;
121+
/// Returns the name in the form 'SB<number>.' like 'SB1.'
122+
std::string getName() const;
123+
virtual void dumpCommonHeader(raw_ostream &OS) const;
124+
void dumpCommonFooter(raw_ostream &OS) const;
125+
void dumpCommonPrefix(raw_ostream &OS) const;
126+
void dumpCommonSuffix(raw_ostream &OS) const;
127+
void printAsOperandCommon(raw_ostream &OS) const;
128+
#endif
129+
};
130+
131+
class User : public Value {
132+
public:
133+
User(ClassID ID, llvm::Value *V, Context &Ctxt) : Value(ID, V, Ctxt) {}
134+
/// For isa/dyn_cast.
135+
static bool classof(const Value *From);
136+
#ifndef NDEBUG
137+
void verify() const override {
138+
assert(isa<llvm::User>(Val) && "Expected User!");
139+
}
140+
void dumpCommonHeader(raw_ostream &OS) const final;
141+
#endif
142+
};
143+
144+
class Context {
145+
protected:
146+
LLVMContext &LLVMCtxt;
147+
148+
public:
149+
Context(LLVMContext &LLVMCtxt) : LLVMCtxt(LLVMCtxt) {}
150+
};
151+
} // namespace sandboxir
152+
} // namespace llvm
153+
154+
#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+
}

0 commit comments

Comments
 (0)