Skip to content

Commit 1dbbabf

Browse files
committed
[SandboxIR][Tracker] Track InsertIntoBB
This tracks the insertion of an Instruction into a BasicBlock.
1 parent f9392fc commit 1dbbabf

File tree

4 files changed

+104
-1
lines changed

4 files changed

+104
-1
lines changed

llvm/include/llvm/SandboxIR/Tracker.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,22 @@ class MoveInstr : public IRChangeBase {
291291
#endif // NDEBUG
292292
};
293293

294+
class InsertIntoBB final : public IRChangeBase {
295+
Instruction *InsertedI = nullptr;
296+
297+
public:
298+
InsertIntoBB(Instruction *InsertedI, Tracker &Tracker);
299+
void revert() final;
300+
void accept() final {}
301+
#ifndef NDEBUG
302+
void dump(raw_ostream &OS) const final {
303+
dumpCommon(OS);
304+
OS << "InsertIntoBB";
305+
}
306+
LLVM_DUMP_METHOD void dump() const final;
307+
#endif // NDEBUG
308+
};
309+
294310
/// The tracker collects all the change objects and implements the main API for
295311
/// saving / reverting / accepting.
296312
class Tracker {

llvm/lib/SandboxIR/SandboxIR.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,11 @@ void Instruction::insertBefore(Instruction *BeforeI) {
430430
assert(is_sorted(getLLVMInstrs(),
431431
[](auto *I1, auto *I2) { return I1->comesBefore(I2); }) &&
432432
"Expected program order!");
433+
434+
auto &Tracker = Ctx.getTracker();
435+
if (Tracker.isTracking())
436+
Tracker.track(std::make_unique<InsertIntoBB>(this, Tracker));
437+
433438
// Insert the LLVM IR Instructions in program order.
434439
for (llvm::Instruction *I : getLLVMInstrs())
435440
I->insertBefore(BeforeTopI);
@@ -443,14 +448,21 @@ void Instruction::insertInto(BasicBlock *BB, const BBIterator &WhereIt) {
443448
llvm::BasicBlock *LLVMBB = cast<llvm::BasicBlock>(BB->Val);
444449
llvm::Instruction *LLVMBeforeI;
445450
llvm::BasicBlock::iterator LLVMBeforeIt;
451+
Instruction *BeforeI;
446452
if (WhereIt != BB->end()) {
447-
Instruction *BeforeI = &*WhereIt;
453+
BeforeI = &*WhereIt;
448454
LLVMBeforeI = BeforeI->getTopmostLLVMInstruction();
449455
LLVMBeforeIt = LLVMBeforeI->getIterator();
450456
} else {
457+
BeforeI = nullptr;
451458
LLVMBeforeI = nullptr;
452459
LLVMBeforeIt = LLVMBB->end();
453460
}
461+
462+
auto &Tracker = Ctx.getTracker();
463+
if (Tracker.isTracking())
464+
Tracker.track(std::make_unique<InsertIntoBB>(this, Tracker));
465+
454466
// Insert the LLVM IR Instructions in program order.
455467
for (llvm::Instruction *I : getLLVMInstrs())
456468
I->insertInto(LLVMBB, LLVMBeforeIt);

llvm/lib/SandboxIR/Tracker.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,18 @@ void MoveInstr::dump() const {
259259
}
260260
#endif
261261

262+
void InsertIntoBB::revert() { InsertedI->removeFromParent(); }
263+
264+
InsertIntoBB::InsertIntoBB(Instruction *InsertedI, Tracker &Tracker)
265+
: IRChangeBase(Tracker), InsertedI(InsertedI) {}
266+
267+
#ifndef NDEBUG
268+
void InsertIntoBB::dump() const {
269+
dump(dbgs());
270+
dbgs() << "\n";
271+
}
272+
#endif
273+
262274
void Tracker::track(std::unique_ptr<IRChangeBase> &&Change) {
263275
assert(State == TrackerState::Record && "The tracker should be tracking!");
264276
Changes.push_back(std::move(Change));

llvm/unittests/SandboxIR/TrackerTest.cpp

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,69 @@ define i32 @foo(i32 %arg) {
442442
EXPECT_EQ(It, BB->end());
443443
}
444444

445+
// TODO: Test multi-instruction patterns.
446+
TEST_F(TrackerTest, InsertIntoBB) {
447+
parseIR(C, R"IR(
448+
define void @foo(i32 %arg) {
449+
%add0 = add i32 %arg, %arg
450+
ret void
451+
}
452+
)IR");
453+
Function &LLVMF = *M->getFunction("foo");
454+
sandboxir::Context Ctx(C);
455+
456+
auto *F = Ctx.createFunction(&LLVMF);
457+
auto *BB = &*F->begin();
458+
auto It = BB->begin();
459+
sandboxir::Instruction *Add0 = &*It++;
460+
sandboxir::Instruction *Ret = &*It++;
461+
// Detach `Add0` before we save.
462+
Add0->removeFromParent();
463+
464+
// Check insertBefore(Instruction *) with tracking enabled.
465+
Ctx.save();
466+
Add0->insertBefore(Ret);
467+
It = BB->begin();
468+
EXPECT_EQ(&*It++, Add0);
469+
EXPECT_EQ(&*It++, Ret);
470+
EXPECT_EQ(It, BB->end());
471+
// Check revert().
472+
Ctx.revert();
473+
It = BB->begin();
474+
EXPECT_EQ(&*It++, Ret);
475+
EXPECT_EQ(It, BB->end());
476+
477+
// Check insertAfter(Instruction *) with tracking enabled.
478+
Ctx.save();
479+
Add0->insertAfter(Ret);
480+
It = BB->begin();
481+
EXPECT_EQ(&*It++, Ret);
482+
EXPECT_EQ(&*It++, Add0);
483+
EXPECT_EQ(It, BB->end());
484+
// Check revert().
485+
Ctx.revert();
486+
It = BB->begin();
487+
EXPECT_EQ(&*It++, Ret);
488+
EXPECT_EQ(It, BB->end());
489+
490+
// Check insertInto(BasicBlock *, BasicBlock::iterator) with tracking enabled.
491+
Ctx.save();
492+
Add0->insertInto(BB, Ret->getIterator());
493+
It = BB->begin();
494+
EXPECT_EQ(&*It++, Add0);
495+
EXPECT_EQ(&*It++, Ret);
496+
EXPECT_EQ(It, BB->end());
497+
// Check revert().
498+
Ctx.revert();
499+
It = BB->begin();
500+
EXPECT_EQ(&*It++, Ret);
501+
EXPECT_EQ(It, BB->end());
502+
503+
// To make sure we don't leak memory insert `Add0` back into the BB before the
504+
// end of the test.
505+
Add0->insertBefore(Ret);
506+
}
507+
445508
TEST_F(TrackerTest, CallBaseSetters) {
446509
parseIR(C, R"IR(
447510
declare void @bar1(i8)

0 commit comments

Comments
 (0)