Skip to content

Commit be958f7

Browse files
committed
[SandboxIR][Tracker] Track Instruction::moveBefore()
Track instruction movement. This supports both moveBefore() and moveAfter().
1 parent 043aca3 commit be958f7

File tree

4 files changed

+164
-0
lines changed

4 files changed

+164
-0
lines changed

llvm/include/llvm/SandboxIR/Tracker.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,26 @@ class RemoveFromParent : public IRChangeBase {
156156
#endif // NDEBUG
157157
};
158158

159+
class MoveInstr : public IRChangeBase {
160+
/// The instruction that moved.
161+
Instruction *MovedI;
162+
/// This is either the next instruction in the block, or the parent BB if at
163+
/// the end of the BB.
164+
PointerUnion<Instruction *, BasicBlock *> NextInstrOrBB;
165+
166+
public:
167+
MoveInstr(sandboxir::Instruction *I, Tracker &Tracker);
168+
void revert() final;
169+
void accept() final {}
170+
#ifndef NDEBUG
171+
void dump(raw_ostream &OS) const final {
172+
dumpCommon(OS);
173+
OS << "MoveInstr";
174+
}
175+
LLVM_DUMP_METHOD void dump() const final;
176+
#endif // NDEBUG
177+
};
178+
159179
/// The tracker collects all the change objects and implements the main API for
160180
/// saving / reverting / accepting.
161181
class Tracker {

llvm/lib/SandboxIR/SandboxIR.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,11 @@ void Instruction::moveBefore(BasicBlock &BB, const BBIterator &WhereIt) {
371371
if (std::next(getIterator()) == WhereIt)
372372
// Destination is same as origin, nothing to do.
373373
return;
374+
375+
auto &Tracker = Ctx.getTracker();
376+
if (Tracker.isTracking())
377+
Tracker.track(std::make_unique<MoveInstr>(this, Tracker));
378+
374379
auto *LLVMBB = cast<llvm::BasicBlock>(BB.Val);
375380
llvm::BasicBlock::iterator It;
376381
if (WhereIt == BB.end()) {

llvm/lib/SandboxIR/Tracker.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,30 @@ void RemoveFromParent::dump() const {
124124
}
125125
#endif
126126

127+
MoveInstr::MoveInstr(Instruction *MovedI, Tracker &Tracker)
128+
: IRChangeBase(Tracker), MovedI(MovedI) {
129+
if (auto *NextI = MovedI->getNextNode())
130+
NextInstrOrBB = NextI;
131+
else
132+
NextInstrOrBB = MovedI->getParent();
133+
}
134+
135+
void MoveInstr::revert() {
136+
if (auto *NextI = NextInstrOrBB.dyn_cast<Instruction *>()) {
137+
MovedI->moveBefore(NextI);
138+
} else {
139+
auto *BB = NextInstrOrBB.get<BasicBlock *>();
140+
MovedI->moveBefore(*BB, BB->end());
141+
}
142+
}
143+
144+
#ifndef NDEBUG
145+
void MoveInstr::dump() const {
146+
dump(dbgs());
147+
dbgs() << "\n";
148+
}
149+
#endif
150+
127151
void Tracker::track(std::unique_ptr<IRChangeBase> &&Change) {
128152
assert(State == TrackerState::Record && "The tracker should be tracking!");
129153
Changes.push_back(std::move(Change));

llvm/unittests/SandboxIR/TrackerTest.cpp

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,3 +255,118 @@ define i32 @foo(i32 %arg) {
255255
EXPECT_EQ(&*It++, Ret);
256256
EXPECT_EQ(It, BB->end());
257257
}
258+
259+
// TODO: Test multi-instruction patterns.
260+
TEST_F(TrackerTest, MoveInstr) {
261+
parseIR(C, R"IR(
262+
define i32 @foo(i32 %arg) {
263+
%add0 = add i32 %arg, %arg
264+
%add1 = add i32 %add0, %arg
265+
ret i32 %add1
266+
}
267+
)IR");
268+
Function &LLVMF = *M->getFunction("foo");
269+
sandboxir::Context Ctx(C);
270+
271+
auto *F = Ctx.createFunction(&LLVMF);
272+
auto *BB = &*F->begin();
273+
auto It = BB->begin();
274+
sandboxir::Instruction *Add0 = &*It++;
275+
sandboxir::Instruction *Add1 = &*It++;
276+
sandboxir::Instruction *Ret = &*It++;
277+
278+
// Check moveBefore(Instruction *) with tracking enabled.
279+
Ctx.save();
280+
Add1->moveBefore(Add0);
281+
It = BB->begin();
282+
EXPECT_EQ(&*It++, Add1);
283+
EXPECT_EQ(&*It++, Add0);
284+
EXPECT_EQ(&*It++, Ret);
285+
EXPECT_EQ(It, BB->end());
286+
// Check revert().
287+
Ctx.revert();
288+
It = BB->begin();
289+
EXPECT_EQ(&*It++, Add0);
290+
EXPECT_EQ(&*It++, Add1);
291+
EXPECT_EQ(&*It++, Ret);
292+
EXPECT_EQ(It, BB->end());
293+
294+
// Same for the last instruction in the block.
295+
Ctx.save();
296+
Ret->moveBefore(Add0);
297+
It = BB->begin();
298+
EXPECT_EQ(&*It++, Ret);
299+
EXPECT_EQ(&*It++, Add0);
300+
EXPECT_EQ(&*It++, Add1);
301+
EXPECT_EQ(It, BB->end());
302+
Ctx.revert();
303+
It = BB->begin();
304+
EXPECT_EQ(&*It++, Add0);
305+
EXPECT_EQ(&*It++, Add1);
306+
EXPECT_EQ(&*It++, Ret);
307+
EXPECT_EQ(It, BB->end());
308+
309+
// Check moveBefore(BasicBlock &, BasicBlock::iterator) with tracking enabled.
310+
Ctx.save();
311+
Add1->moveBefore(*BB, Add0->getIterator());
312+
It = BB->begin();
313+
EXPECT_EQ(&*It++, Add1);
314+
EXPECT_EQ(&*It++, Add0);
315+
EXPECT_EQ(&*It++, Ret);
316+
EXPECT_EQ(It, BB->end());
317+
// Check revert().
318+
Ctx.revert();
319+
It = BB->begin();
320+
EXPECT_EQ(&*It++, Add0);
321+
EXPECT_EQ(&*It++, Add1);
322+
EXPECT_EQ(&*It++, Ret);
323+
EXPECT_EQ(It, BB->end());
324+
325+
// Same for the last instruction in the block.
326+
Ctx.save();
327+
Ret->moveBefore(*BB, Add0->getIterator());
328+
It = BB->begin();
329+
EXPECT_EQ(&*It++, Ret);
330+
EXPECT_EQ(&*It++, Add0);
331+
EXPECT_EQ(&*It++, Add1);
332+
EXPECT_EQ(It, BB->end());
333+
// Check revert().
334+
Ctx.revert();
335+
It = BB->begin();
336+
EXPECT_EQ(&*It++, Add0);
337+
EXPECT_EQ(&*It++, Add1);
338+
EXPECT_EQ(&*It++, Ret);
339+
EXPECT_EQ(It, BB->end());
340+
341+
// Check moveAfter(Instruction *) with tracking enabled.
342+
Ctx.save();
343+
Add0->moveAfter(Add1);
344+
It = BB->begin();
345+
EXPECT_EQ(&*It++, Add1);
346+
EXPECT_EQ(&*It++, Add0);
347+
EXPECT_EQ(&*It++, Ret);
348+
EXPECT_EQ(It, BB->end());
349+
// Check revert().
350+
Ctx.revert();
351+
It = BB->begin();
352+
EXPECT_EQ(&*It++, Add0);
353+
EXPECT_EQ(&*It++, Add1);
354+
EXPECT_EQ(&*It++, Ret);
355+
EXPECT_EQ(It, BB->end());
356+
357+
// Same for the last instruction in the block.
358+
Ctx.save();
359+
Ret->moveAfter(Add0);
360+
It = BB->begin();
361+
EXPECT_EQ(&*It++, Add0);
362+
EXPECT_EQ(&*It++, Ret);
363+
EXPECT_EQ(&*It++, Add1);
364+
EXPECT_EQ(It, BB->end());
365+
// Check revert().
366+
Ctx.revert();
367+
It = BB->begin();
368+
EXPECT_EQ(&*It++, Add0);
369+
EXPECT_EQ(&*It++, Add1);
370+
EXPECT_EQ(&*It++, Ret);
371+
EXPECT_EQ(It, BB->end());
372+
}

0 commit comments

Comments
 (0)