Skip to content

Commit 0959e58

Browse files
authored
[SandboxIR][Tracker] Track creation of instructions (#102013)
This patch adds tracking support for the creation of SandboxIR instructions. This allows us to undo the creation of instructions during revert(). Please note that we don't allow creation of detached instructions, meaning that the instructions need to be inserted into a block upon creation. This is why the tracker class combines creation and insertion.
1 parent accf5c9 commit 0959e58

File tree

4 files changed

+72
-0
lines changed

4 files changed

+72
-0
lines changed

llvm/include/llvm/SandboxIR/Tracker.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,23 @@ class InsertIntoBB final : public IRChangeBase {
328328
#endif // NDEBUG
329329
};
330330

331+
class CreateAndInsertInst final : public IRChangeBase {
332+
Instruction *NewI = nullptr;
333+
334+
public:
335+
CreateAndInsertInst(Instruction *NewI, Tracker &Tracker)
336+
: IRChangeBase(Tracker), NewI(NewI) {}
337+
void revert() final;
338+
void accept() final {}
339+
#ifndef NDEBUG
340+
void dump(raw_ostream &OS) const final {
341+
dumpCommon(OS);
342+
OS << "CreateAndInsertInst";
343+
}
344+
LLVM_DUMP_METHOD void dump() const final;
345+
#endif
346+
};
347+
331348
/// The tracker collects all the change objects and implements the main API for
332349
/// saving / reverting / accepting.
333350
class Tracker {

llvm/lib/SandboxIR/SandboxIR.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1359,6 +1359,16 @@ std::unique_ptr<Value> Context::detach(Value *V) {
13591359
Value *Context::registerValue(std::unique_ptr<Value> &&VPtr) {
13601360
assert(VPtr->getSubclassID() != Value::ClassID::User &&
13611361
"Can't register a user!");
1362+
1363+
// Track creation of instructions.
1364+
// Please note that we don't allow the creation of detached instructions,
1365+
// meaning that the instructions need to be inserted into a block upon
1366+
// creation. This is why the tracker class combines creation and insertion.
1367+
auto &Tracker = getTracker();
1368+
if (Tracker.isTracking())
1369+
if (auto *I = dyn_cast<Instruction>(VPtr.get()))
1370+
Tracker.track(std::make_unique<CreateAndInsertInst>(I, Tracker));
1371+
13621372
Value *V = VPtr.get();
13631373
[[maybe_unused]] auto Pair =
13641374
LLVMValueToValueMap.insert({VPtr->Val, std::move(VPtr)});

llvm/lib/SandboxIR/Tracker.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,15 @@ void InsertIntoBB::dump() const {
300300
}
301301
#endif
302302

303+
void CreateAndInsertInst::revert() { NewI->eraseFromParent(); }
304+
305+
#ifndef NDEBUG
306+
void CreateAndInsertInst::dump() const {
307+
dump(dbgs());
308+
dbgs() << "\n";
309+
}
310+
#endif
311+
303312
void Tracker::track(std::unique_ptr<IRChangeBase> &&Change) {
304313
assert(State == TrackerState::Record && "The tracker should be tracking!");
305314
Changes.push_back(std::move(Change));

llvm/unittests/SandboxIR/TrackerTest.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,42 @@ define void @foo(i32 %arg) {
505505
Add0->insertBefore(Ret);
506506
}
507507

508+
// TODO: Test multi-instruction patterns.
509+
TEST_F(TrackerTest, CreateAndInsertInst) {
510+
parseIR(C, R"IR(
511+
define void @foo(ptr %ptr) {
512+
%ld = load i8, ptr %ptr, align 64
513+
ret void
514+
}
515+
)IR");
516+
Function &LLVMF = *M->getFunction("foo");
517+
sandboxir::Context Ctx(C);
518+
519+
auto *F = Ctx.createFunction(&LLVMF);
520+
auto *Ptr = F->getArg(0);
521+
auto *BB = &*F->begin();
522+
auto It = BB->begin();
523+
auto *Ld = cast<sandboxir::LoadInst>(&*It++);
524+
auto *Ret = &*It++;
525+
526+
Ctx.save();
527+
// Check create(InsertBefore) with tracking enabled.
528+
sandboxir::LoadInst *NewLd =
529+
sandboxir::LoadInst::create(Ld->getType(), Ptr, Align(8),
530+
/*InsertBefore=*/Ld, Ctx, "NewLd");
531+
It = BB->begin();
532+
EXPECT_EQ(&*It++, NewLd);
533+
EXPECT_EQ(&*It++, Ld);
534+
EXPECT_EQ(&*It++, Ret);
535+
EXPECT_EQ(It, BB->end());
536+
// Check revert().
537+
Ctx.revert();
538+
It = BB->begin();
539+
EXPECT_EQ(&*It++, Ld);
540+
EXPECT_EQ(&*It++, Ret);
541+
EXPECT_EQ(It, BB->end());
542+
}
543+
508544
TEST_F(TrackerTest, CallBaseSetters) {
509545
parseIR(C, R"IR(
510546
declare void @bar1(i8)

0 commit comments

Comments
 (0)