Skip to content

Commit

Permalink
[SandboxIR][Tracker] Track InsertIntoBB
Browse files Browse the repository at this point in the history
This tracks the insertion of an Instruction into a BasicBlock.
  • Loading branch information
vporpo committed Aug 3, 2024
1 parent f9392fc commit 1dbbabf
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 1 deletion.
16 changes: 16 additions & 0 deletions llvm/include/llvm/SandboxIR/Tracker.h
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,22 @@ class MoveInstr : public IRChangeBase {
#endif // NDEBUG
};

class InsertIntoBB final : public IRChangeBase {
Instruction *InsertedI = nullptr;

public:
InsertIntoBB(Instruction *InsertedI, Tracker &Tracker);
void revert() final;
void accept() final {}
#ifndef NDEBUG
void dump(raw_ostream &OS) const final {
dumpCommon(OS);
OS << "InsertIntoBB";
}
LLVM_DUMP_METHOD void dump() const final;
#endif // NDEBUG
};

/// The tracker collects all the change objects and implements the main API for
/// saving / reverting / accepting.
class Tracker {
Expand Down
14 changes: 13 additions & 1 deletion llvm/lib/SandboxIR/SandboxIR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,11 @@ void Instruction::insertBefore(Instruction *BeforeI) {
assert(is_sorted(getLLVMInstrs(),
[](auto *I1, auto *I2) { return I1->comesBefore(I2); }) &&
"Expected program order!");

auto &Tracker = Ctx.getTracker();
if (Tracker.isTracking())
Tracker.track(std::make_unique<InsertIntoBB>(this, Tracker));

// Insert the LLVM IR Instructions in program order.
for (llvm::Instruction *I : getLLVMInstrs())
I->insertBefore(BeforeTopI);
Expand All @@ -443,14 +448,21 @@ void Instruction::insertInto(BasicBlock *BB, const BBIterator &WhereIt) {
llvm::BasicBlock *LLVMBB = cast<llvm::BasicBlock>(BB->Val);
llvm::Instruction *LLVMBeforeI;
llvm::BasicBlock::iterator LLVMBeforeIt;
Instruction *BeforeI;
if (WhereIt != BB->end()) {
Instruction *BeforeI = &*WhereIt;
BeforeI = &*WhereIt;
LLVMBeforeI = BeforeI->getTopmostLLVMInstruction();
LLVMBeforeIt = LLVMBeforeI->getIterator();
} else {
BeforeI = nullptr;
LLVMBeforeI = nullptr;
LLVMBeforeIt = LLVMBB->end();
}

auto &Tracker = Ctx.getTracker();
if (Tracker.isTracking())
Tracker.track(std::make_unique<InsertIntoBB>(this, Tracker));

// Insert the LLVM IR Instructions in program order.
for (llvm::Instruction *I : getLLVMInstrs())
I->insertInto(LLVMBB, LLVMBeforeIt);
Expand Down
12 changes: 12 additions & 0 deletions llvm/lib/SandboxIR/Tracker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,18 @@ void MoveInstr::dump() const {
}
#endif

void InsertIntoBB::revert() { InsertedI->removeFromParent(); }

InsertIntoBB::InsertIntoBB(Instruction *InsertedI, Tracker &Tracker)
: IRChangeBase(Tracker), InsertedI(InsertedI) {}

#ifndef NDEBUG
void InsertIntoBB::dump() const {
dump(dbgs());
dbgs() << "\n";
}
#endif

void Tracker::track(std::unique_ptr<IRChangeBase> &&Change) {
assert(State == TrackerState::Record && "The tracker should be tracking!");
Changes.push_back(std::move(Change));
Expand Down
63 changes: 63 additions & 0 deletions llvm/unittests/SandboxIR/TrackerTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,69 @@ define i32 @foo(i32 %arg) {
EXPECT_EQ(It, BB->end());
}

// TODO: Test multi-instruction patterns.
TEST_F(TrackerTest, InsertIntoBB) {
parseIR(C, R"IR(
define void @foo(i32 %arg) {
%add0 = add i32 %arg, %arg
ret void
}
)IR");
Function &LLVMF = *M->getFunction("foo");
sandboxir::Context Ctx(C);

auto *F = Ctx.createFunction(&LLVMF);
auto *BB = &*F->begin();
auto It = BB->begin();
sandboxir::Instruction *Add0 = &*It++;
sandboxir::Instruction *Ret = &*It++;
// Detach `Add0` before we save.
Add0->removeFromParent();

// Check insertBefore(Instruction *) with tracking enabled.
Ctx.save();
Add0->insertBefore(Ret);
It = BB->begin();
EXPECT_EQ(&*It++, Add0);
EXPECT_EQ(&*It++, Ret);
EXPECT_EQ(It, BB->end());
// Check revert().
Ctx.revert();
It = BB->begin();
EXPECT_EQ(&*It++, Ret);
EXPECT_EQ(It, BB->end());

// Check insertAfter(Instruction *) with tracking enabled.
Ctx.save();
Add0->insertAfter(Ret);
It = BB->begin();
EXPECT_EQ(&*It++, Ret);
EXPECT_EQ(&*It++, Add0);
EXPECT_EQ(It, BB->end());
// Check revert().
Ctx.revert();
It = BB->begin();
EXPECT_EQ(&*It++, Ret);
EXPECT_EQ(It, BB->end());

// Check insertInto(BasicBlock *, BasicBlock::iterator) with tracking enabled.
Ctx.save();
Add0->insertInto(BB, Ret->getIterator());
It = BB->begin();
EXPECT_EQ(&*It++, Add0);
EXPECT_EQ(&*It++, Ret);
EXPECT_EQ(It, BB->end());
// Check revert().
Ctx.revert();
It = BB->begin();
EXPECT_EQ(&*It++, Ret);
EXPECT_EQ(It, BB->end());

// To make sure we don't leak memory insert `Add0` back into the BB before the
// end of the test.
Add0->insertBefore(Ret);
}

TEST_F(TrackerTest, CallBaseSetters) {
parseIR(C, R"IR(
declare void @bar1(i8)
Expand Down

0 comments on commit 1dbbabf

Please sign in to comment.