Skip to content

Commit 4f786c6

Browse files
authored
[SandboxIR][Tracker] Track Instruction::removeFromParent() (#99541)
This patch adds the necessary functionality to the Tracker and to the Sandbox IR API functions for tracking calls to removeFromParent().
1 parent 50b5bb7 commit 4f786c6

File tree

4 files changed

+106
-0
lines changed

4 files changed

+106
-0
lines changed

llvm/include/llvm/SandboxIR/Tracker.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
namespace llvm::sandboxir {
5454

5555
class BasicBlock;
56+
class Instruction;
5657
class Tracker;
5758

5859
/// The base class for IR Change classes.
@@ -135,6 +136,26 @@ class EraseFromParent : public IRChangeBase {
135136
#endif
136137
};
137138

139+
class RemoveFromParent : public IRChangeBase {
140+
/// The instruction that is about to get removed.
141+
Instruction *RemovedI = nullptr;
142+
/// This is either the next instr, or the parent BB if at the end of the BB.
143+
PointerUnion<Instruction *, BasicBlock *> NextInstrOrBB;
144+
145+
public:
146+
RemoveFromParent(Instruction *RemovedI, Tracker &Tracker);
147+
void revert() final;
148+
void accept() final {};
149+
Instruction *getInstruction() const { return RemovedI; }
150+
#ifndef NDEBUG
151+
void dump(raw_ostream &OS) const final {
152+
dumpCommon(OS);
153+
OS << "RemoveFromParent";
154+
}
155+
LLVM_DUMP_METHOD void dump() const final;
156+
#endif // NDEBUG
157+
};
158+
138159
/// The tracker collects all the change objects and implements the main API for
139160
/// saving / reverting / accepting.
140161
class Tracker {

llvm/lib/SandboxIR/SandboxIR.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,10 @@ Instruction *Instruction::getPrevNode() const {
333333
}
334334

335335
void Instruction::removeFromParent() {
336+
auto &Tracker = Ctx.getTracker();
337+
if (Tracker.isTracking())
338+
Tracker.track(std::make_unique<RemoveFromParent>(this, Tracker));
339+
336340
// Detach all the LLVM IR instructions from their parent BB.
337341
for (llvm::Instruction *I : getLLVMInstrs())
338342
I->removeFromParent();

llvm/lib/SandboxIR/Tracker.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,30 @@ void EraseFromParent::dump() const {
9898
dump(dbgs());
9999
dbgs() << "\n";
100100
}
101+
#endif // NDEBUG
102+
103+
RemoveFromParent::RemoveFromParent(Instruction *RemovedI, Tracker &Tracker)
104+
: IRChangeBase(Tracker), RemovedI(RemovedI) {
105+
if (auto *NextI = RemovedI->getNextNode())
106+
NextInstrOrBB = NextI;
107+
else
108+
NextInstrOrBB = RemovedI->getParent();
109+
}
110+
111+
void RemoveFromParent::revert() {
112+
if (auto *NextI = NextInstrOrBB.dyn_cast<Instruction *>()) {
113+
RemovedI->insertBefore(NextI);
114+
} else {
115+
auto *BB = NextInstrOrBB.get<BasicBlock *>();
116+
RemovedI->insertInto(BB, BB->end());
117+
}
118+
}
119+
120+
#ifndef NDEBUG
121+
void RemoveFromParent::dump() const {
122+
dump(dbgs());
123+
dbgs() << "\n";
124+
}
101125
#endif
102126

103127
void Tracker::track(std::unique_ptr<IRChangeBase> &&Change) {

llvm/unittests/SandboxIR/TrackerTest.cpp

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,3 +198,60 @@ define void @foo(i32 %v1) {
198198
EXPECT_EQ(&*It++, Ret);
199199
EXPECT_EQ(It, BB->end());
200200
}
201+
202+
// TODO: Test multi-instruction patterns.
203+
TEST_F(TrackerTest, RemoveFromParent) {
204+
parseIR(C, R"IR(
205+
define i32 @foo(i32 %arg) {
206+
%add0 = add i32 %arg, %arg
207+
%add1 = add i32 %add0, %arg
208+
ret i32 %add1
209+
}
210+
)IR");
211+
Function &LLVMF = *M->getFunction("foo");
212+
sandboxir::Context Ctx(C);
213+
214+
auto *F = Ctx.createFunction(&LLVMF);
215+
auto *Arg = F->getArg(0);
216+
auto *BB = &*F->begin();
217+
auto It = BB->begin();
218+
sandboxir::Instruction *Add0 = &*It++;
219+
sandboxir::Instruction *Add1 = &*It++;
220+
sandboxir::Instruction *Ret = &*It++;
221+
222+
Ctx.save();
223+
// Check removeFromParent().
224+
Add1->removeFromParent();
225+
It = BB->begin();
226+
EXPECT_EQ(&*It++, Add0);
227+
EXPECT_EQ(&*It++, Ret);
228+
EXPECT_EQ(It, BB->end());
229+
// Removed instruction still be connected to operands and users.
230+
EXPECT_EQ(Add1->getOperand(0), Add0);
231+
EXPECT_EQ(Add1->getOperand(1), Arg);
232+
EXPECT_EQ(Add0->getNumUses(), 1u);
233+
234+
// Check revert().
235+
Ctx.revert();
236+
It = BB->begin();
237+
EXPECT_EQ(&*It++, Add0);
238+
EXPECT_EQ(&*It++, Add1);
239+
EXPECT_EQ(&*It++, Ret);
240+
EXPECT_EQ(It, BB->end());
241+
EXPECT_EQ(Add1->getOperand(0), Add0);
242+
243+
// Same for the last instruction in the block.
244+
Ctx.save();
245+
Ret->removeFromParent();
246+
It = BB->begin();
247+
EXPECT_EQ(&*It++, Add0);
248+
EXPECT_EQ(&*It++, Add1);
249+
EXPECT_EQ(It, BB->end());
250+
EXPECT_EQ(Ret->getOperand(0), Add1);
251+
Ctx.revert();
252+
It = BB->begin();
253+
EXPECT_EQ(&*It++, Add0);
254+
EXPECT_EQ(&*It++, Add1);
255+
EXPECT_EQ(&*It++, Ret);
256+
EXPECT_EQ(It, BB->end());
257+
}

0 commit comments

Comments
 (0)