Skip to content

Commit 491375c

Browse files
authored
[SandboxIR][NFC] Move BasicBlock class into a separate file (#110194)
1 parent c674733 commit 491375c

File tree

6 files changed

+280
-239
lines changed

6 files changed

+280
-239
lines changed
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
//===- BasicBlock.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+
#ifndef LLVM_SANDBOXIR_BASICBLOCK_H
10+
#define LLVM_SANDBOXIR_BASICBLOCK_H
11+
12+
#include "llvm/IR/BasicBlock.h"
13+
#include "llvm/SandboxIR/Value.h"
14+
15+
namespace llvm::sandboxir {
16+
17+
class BasicBlock;
18+
class Function;
19+
class Instruction;
20+
21+
/// Iterator for `Instruction`s in a `BasicBlock.
22+
/// \Returns an sandboxir::Instruction & when derereferenced.
23+
class BBIterator {
24+
public:
25+
using difference_type = std::ptrdiff_t;
26+
using value_type = Instruction;
27+
using pointer = value_type *;
28+
using reference = value_type &;
29+
using iterator_category = std::bidirectional_iterator_tag;
30+
31+
private:
32+
llvm::BasicBlock *BB;
33+
llvm::BasicBlock::iterator It;
34+
Context *Ctx;
35+
pointer getInstr(llvm::BasicBlock::iterator It) const;
36+
37+
public:
38+
BBIterator() : BB(nullptr), Ctx(nullptr) {}
39+
BBIterator(llvm::BasicBlock *BB, llvm::BasicBlock::iterator It, Context *Ctx)
40+
: BB(BB), It(It), Ctx(Ctx) {}
41+
reference operator*() const { return *getInstr(It); }
42+
BBIterator &operator++();
43+
BBIterator operator++(int) {
44+
auto Copy = *this;
45+
++*this;
46+
return Copy;
47+
}
48+
BBIterator &operator--();
49+
BBIterator operator--(int) {
50+
auto Copy = *this;
51+
--*this;
52+
return Copy;
53+
}
54+
bool operator==(const BBIterator &Other) const {
55+
assert(Ctx == Other.Ctx && "BBIterators in different context!");
56+
return It == Other.It;
57+
}
58+
bool operator!=(const BBIterator &Other) const { return !(*this == Other); }
59+
/// \Returns the SBInstruction that corresponds to this iterator, or null if
60+
/// the instruction is not found in the IR-to-SandboxIR tables.
61+
pointer get() const { return getInstr(It); }
62+
/// \Returns the parent BB.
63+
BasicBlock *getNodeParent() const;
64+
};
65+
66+
/// Contains a list of sandboxir::Instruction's.
67+
class BasicBlock : public Value {
68+
/// Builds a graph that contains all values in \p BB in their original form
69+
/// i.e., no vectorization is taking place here.
70+
void buildBasicBlockFromLLVMIR(llvm::BasicBlock *LLVMBB);
71+
friend class Context; // For `buildBasicBlockFromIR`
72+
friend class Instruction; // For LLVM Val.
73+
74+
BasicBlock(llvm::BasicBlock *BB, Context &SBCtx)
75+
: Value(ClassID::Block, BB, SBCtx) {
76+
buildBasicBlockFromLLVMIR(BB);
77+
}
78+
79+
public:
80+
~BasicBlock() = default;
81+
/// For isa/dyn_cast.
82+
static bool classof(const Value *From) {
83+
return From->getSubclassID() == Value::ClassID::Block;
84+
}
85+
Function *getParent() const;
86+
using iterator = BBIterator;
87+
iterator begin() const;
88+
iterator end() const {
89+
auto *BB = cast<llvm::BasicBlock>(Val);
90+
return iterator(BB, BB->end(), &Ctx);
91+
}
92+
std::reverse_iterator<iterator> rbegin() const {
93+
return std::make_reverse_iterator(end());
94+
}
95+
std::reverse_iterator<iterator> rend() const {
96+
return std::make_reverse_iterator(begin());
97+
}
98+
Context &getContext() const { return Ctx; }
99+
Instruction *getTerminator() const;
100+
bool empty() const { return begin() == end(); }
101+
Instruction &front() const;
102+
Instruction &back() const;
103+
104+
#ifndef NDEBUG
105+
void verify() const final;
106+
void dumpOS(raw_ostream &OS) const final;
107+
#endif
108+
};
109+
110+
} // namespace llvm::sandboxir
111+
112+
#endif // LLVM_SANDBOXIR_BASICBLOCK_H

llvm/include/llvm/SandboxIR/SandboxIR.h

Lines changed: 1 addition & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@
110110
#include "llvm/IR/User.h"
111111
#include "llvm/IR/Value.h"
112112
#include "llvm/SandboxIR/Argument.h"
113+
#include "llvm/SandboxIR/BasicBlock.h"
113114
#include "llvm/SandboxIR/Constant.h"
114115
#include "llvm/SandboxIR/Context.h"
115116
#include "llvm/SandboxIR/Module.h"
@@ -191,95 +192,6 @@ class CmpInst;
191192
class ICmpInst;
192193
class FCmpInst;
193194

194-
/// Iterator for `Instruction`s in a `BasicBlock.
195-
/// \Returns an sandboxir::Instruction & when derereferenced.
196-
class BBIterator {
197-
public:
198-
using difference_type = std::ptrdiff_t;
199-
using value_type = Instruction;
200-
using pointer = value_type *;
201-
using reference = value_type &;
202-
using iterator_category = std::bidirectional_iterator_tag;
203-
204-
private:
205-
llvm::BasicBlock *BB;
206-
llvm::BasicBlock::iterator It;
207-
Context *Ctx;
208-
pointer getInstr(llvm::BasicBlock::iterator It) const;
209-
210-
public:
211-
BBIterator() : BB(nullptr), Ctx(nullptr) {}
212-
BBIterator(llvm::BasicBlock *BB, llvm::BasicBlock::iterator It, Context *Ctx)
213-
: BB(BB), It(It), Ctx(Ctx) {}
214-
reference operator*() const { return *getInstr(It); }
215-
BBIterator &operator++();
216-
BBIterator operator++(int) {
217-
auto Copy = *this;
218-
++*this;
219-
return Copy;
220-
}
221-
BBIterator &operator--();
222-
BBIterator operator--(int) {
223-
auto Copy = *this;
224-
--*this;
225-
return Copy;
226-
}
227-
bool operator==(const BBIterator &Other) const {
228-
assert(Ctx == Other.Ctx && "BBIterators in different context!");
229-
return It == Other.It;
230-
}
231-
bool operator!=(const BBIterator &Other) const { return !(*this == Other); }
232-
/// \Returns the SBInstruction that corresponds to this iterator, or null if
233-
/// the instruction is not found in the IR-to-SandboxIR tables.
234-
pointer get() const { return getInstr(It); }
235-
/// \Returns the parent BB.
236-
BasicBlock *getNodeParent() const;
237-
};
238-
239-
/// Contains a list of sandboxir::Instruction's.
240-
class BasicBlock : public Value {
241-
/// Builds a graph that contains all values in \p BB in their original form
242-
/// i.e., no vectorization is taking place here.
243-
void buildBasicBlockFromLLVMIR(llvm::BasicBlock *LLVMBB);
244-
friend class Context; // For `buildBasicBlockFromIR`
245-
friend class Instruction; // For LLVM Val.
246-
247-
BasicBlock(llvm::BasicBlock *BB, Context &SBCtx)
248-
: Value(ClassID::Block, BB, SBCtx) {
249-
buildBasicBlockFromLLVMIR(BB);
250-
}
251-
252-
public:
253-
~BasicBlock() = default;
254-
/// For isa/dyn_cast.
255-
static bool classof(const Value *From) {
256-
return From->getSubclassID() == Value::ClassID::Block;
257-
}
258-
Function *getParent() const;
259-
using iterator = BBIterator;
260-
iterator begin() const;
261-
iterator end() const {
262-
auto *BB = cast<llvm::BasicBlock>(Val);
263-
return iterator(BB, BB->end(), &Ctx);
264-
}
265-
std::reverse_iterator<iterator> rbegin() const {
266-
return std::make_reverse_iterator(end());
267-
}
268-
std::reverse_iterator<iterator> rend() const {
269-
return std::make_reverse_iterator(begin());
270-
}
271-
Context &getContext() const { return Ctx; }
272-
Instruction *getTerminator() const;
273-
bool empty() const { return begin() == end(); }
274-
Instruction &front() const;
275-
Instruction &back() const;
276-
277-
#ifndef NDEBUG
278-
void verify() const final;
279-
void dumpOS(raw_ostream &OS) const final;
280-
#endif
281-
};
282-
283195
/// A sandboxir::User with operands, opcode and linked with previous/next
284196
/// instructions in an instruction list.
285197
class Instruction : public sandboxir::User {

llvm/lib/SandboxIR/BasicBlock.cpp

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
//===- BasicBlock.cpp - The BasicBlock class of Sandbox 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/SandboxIR/BasicBlock.h"
10+
#include "llvm/SandboxIR/Context.h"
11+
#include "llvm/SandboxIR/SandboxIR.h" // TODO: remove this
12+
13+
namespace llvm::sandboxir {
14+
15+
BBIterator &BBIterator::operator++() {
16+
auto ItE = BB->end();
17+
assert(It != ItE && "Already at end!");
18+
++It;
19+
if (It == ItE)
20+
return *this;
21+
Instruction &NextI = *cast<sandboxir::Instruction>(Ctx->getValue(&*It));
22+
unsigned Num = NextI.getNumOfIRInstrs();
23+
assert(Num > 0 && "Bad getNumOfIRInstrs()");
24+
It = std::next(It, Num - 1);
25+
return *this;
26+
}
27+
28+
BBIterator &BBIterator::operator--() {
29+
assert(It != BB->begin() && "Already at begin!");
30+
if (It == BB->end()) {
31+
--It;
32+
return *this;
33+
}
34+
Instruction &CurrI = **this;
35+
unsigned Num = CurrI.getNumOfIRInstrs();
36+
assert(Num > 0 && "Bad getNumOfIRInstrs()");
37+
assert(std::prev(It, Num - 1) != BB->begin() && "Already at begin!");
38+
It = std::prev(It, Num);
39+
return *this;
40+
}
41+
42+
BasicBlock *BBIterator::getNodeParent() const {
43+
llvm::BasicBlock *Parent = const_cast<BBIterator *>(this)->It.getNodeParent();
44+
return cast<BasicBlock>(Ctx->getValue(Parent));
45+
}
46+
47+
BasicBlock::iterator::pointer
48+
BasicBlock::iterator::getInstr(llvm::BasicBlock::iterator It) const {
49+
return cast_or_null<Instruction>(Ctx->getValue(&*It));
50+
}
51+
52+
Function *BasicBlock::getParent() const {
53+
auto *BB = cast<llvm::BasicBlock>(Val);
54+
auto *F = BB->getParent();
55+
if (F == nullptr)
56+
// Detached
57+
return nullptr;
58+
return cast_or_null<Function>(Ctx.getValue(F));
59+
}
60+
61+
void BasicBlock::buildBasicBlockFromLLVMIR(llvm::BasicBlock *LLVMBB) {
62+
for (llvm::Instruction &IRef : reverse(*LLVMBB)) {
63+
llvm::Instruction *I = &IRef;
64+
Ctx.getOrCreateValue(I);
65+
for (auto [OpIdx, Op] : enumerate(I->operands())) {
66+
// Skip instruction's label operands
67+
if (isa<llvm::BasicBlock>(Op))
68+
continue;
69+
// Skip metadata
70+
if (isa<llvm::MetadataAsValue>(Op))
71+
continue;
72+
// Skip asm
73+
if (isa<llvm::InlineAsm>(Op))
74+
continue;
75+
Ctx.getOrCreateValue(Op);
76+
}
77+
}
78+
#if !defined(NDEBUG)
79+
verify();
80+
#endif
81+
}
82+
83+
BasicBlock::iterator BasicBlock::begin() const {
84+
llvm::BasicBlock *BB = cast<llvm::BasicBlock>(Val);
85+
llvm::BasicBlock::iterator It = BB->begin();
86+
if (!BB->empty()) {
87+
auto *V = Ctx.getValue(&*BB->begin());
88+
assert(V != nullptr && "No SandboxIR for BB->begin()!");
89+
auto *I = cast<Instruction>(V);
90+
unsigned Num = I->getNumOfIRInstrs();
91+
assert(Num >= 1u && "Bad getNumOfIRInstrs()");
92+
It = std::next(It, Num - 1);
93+
}
94+
return iterator(BB, It, &Ctx);
95+
}
96+
97+
Instruction *BasicBlock::getTerminator() const {
98+
auto *TerminatorV =
99+
Ctx.getValue(cast<llvm::BasicBlock>(Val)->getTerminator());
100+
return cast_or_null<Instruction>(TerminatorV);
101+
}
102+
103+
Instruction &BasicBlock::front() const {
104+
auto *BB = cast<llvm::BasicBlock>(Val);
105+
assert(!BB->empty() && "Empty block!");
106+
auto *SBI = cast<Instruction>(getContext().getValue(&*BB->begin()));
107+
assert(SBI != nullptr && "Expected Instr!");
108+
return *SBI;
109+
}
110+
111+
Instruction &BasicBlock::back() const {
112+
auto *BB = cast<llvm::BasicBlock>(Val);
113+
assert(!BB->empty() && "Empty block!");
114+
auto *SBI = cast<Instruction>(getContext().getValue(&*BB->rbegin()));
115+
assert(SBI != nullptr && "Expected Instr!");
116+
return *SBI;
117+
}
118+
119+
#ifndef NDEBUG
120+
void BasicBlock::dumpOS(raw_ostream &OS) const {
121+
llvm::BasicBlock *BB = cast<llvm::BasicBlock>(Val);
122+
const auto &Name = BB->getName();
123+
OS << Name;
124+
if (!Name.empty())
125+
OS << ":\n";
126+
// If there are Instructions in the BB that are not mapped to SandboxIR, then
127+
// use a crash-proof dump.
128+
if (any_of(*BB, [this](llvm::Instruction &I) {
129+
return Ctx.getValue(&I) == nullptr;
130+
})) {
131+
OS << "<Crash-proof mode!>\n";
132+
DenseSet<Instruction *> Visited;
133+
for (llvm::Instruction &IRef : *BB) {
134+
Value *SBV = Ctx.getValue(&IRef);
135+
if (SBV == nullptr)
136+
OS << IRef << " *** No SandboxIR ***\n";
137+
else {
138+
auto *SBI = dyn_cast<Instruction>(SBV);
139+
if (SBI == nullptr) {
140+
OS << IRef << " *** Not a SBInstruction!!! ***\n";
141+
} else {
142+
if (Visited.insert(SBI).second)
143+
OS << *SBI << "\n";
144+
}
145+
}
146+
}
147+
} else {
148+
for (auto &SBI : *this) {
149+
SBI.dumpOS(OS);
150+
OS << "\n";
151+
}
152+
}
153+
}
154+
155+
void BasicBlock::verify() const {
156+
assert(isa<llvm::BasicBlock>(Val) && "Expected BasicBlock!");
157+
for (const auto &I : *this) {
158+
I.verify();
159+
}
160+
}
161+
#endif // NDEBUG
162+
163+
} // namespace llvm::sandboxir

llvm/lib/SandboxIR/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
add_llvm_component_library(LLVMSandboxIR
22
Argument.cpp
3+
BasicBlock.cpp
34
Constant.cpp
45
Context.cpp
56
Module.cpp

llvm/lib/SandboxIR/Constant.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "llvm/SandboxIR/Constant.h"
10+
#include "llvm/SandboxIR/Argument.h"
11+
#include "llvm/SandboxIR/BasicBlock.h"
1012
#include "llvm/SandboxIR/Context.h"
11-
#include "llvm/SandboxIR/SandboxIR.h" // TODO: Try to remove this
1213

1314
namespace llvm::sandboxir {
1415

0 commit comments

Comments
 (0)