Skip to content

Commit 31b6c65

Browse files
committed
Fix a logic error in eraseUseOfValue.
I failed to create a test case. And we hav existing tests in FSO that will exercise this. rdar://25559780
1 parent 46e3590 commit 31b6c65

File tree

2 files changed

+27
-22
lines changed

2 files changed

+27
-22
lines changed

include/swift/SILOptimizer/Utils/Local.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,12 @@ bool isInstructionTriviallyDead(SILInstruction *I);
7777
bool isIntermediateRelease(SILInstruction *I,
7878
ConsumedArgToEpilogueReleaseMatcher &ERM);
7979

80+
/// \brief Recursively collect all the uses and transistive uses of the
81+
/// instruction.
82+
void collectUsesOfValue(SILValue V, llvm::DenseSet<SILInstruction *> &Insts);
83+
8084
/// \brief Recursively erase all of the uses of the instruction (but not the
81-
/// instruction itself) and delete instructions that will become trivially
82-
/// dead when this instruction is removed.
85+
/// instruction itself)
8386
void eraseUsesOfInstruction(
8487
SILInstruction *Inst,
8588
std::function<void(SILInstruction *)> C = [](SILInstruction *){});

lib/SILOptimizer/Utils/Local.cpp

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -207,29 +207,31 @@ void swift::eraseUsesOfInstruction(SILInstruction *Inst,
207207
}
208208
}
209209

210-
void swift::eraseUsesOfValue(SILValue V) {
211-
for (auto UI = V->use_begin(), E = V->use_end(); UI != E;) {
210+
void
211+
swift::collectUsesOfValue(SILValue V, llvm::DenseSet<SILInstruction *> &Insts) {
212+
for (auto UI = V->use_begin(), E = V->use_end(); UI != E; UI++) {
212213
auto *User = UI->getUser();
213-
UI++;
214-
215-
// If the instruction itself has any uses, recursively zap them so that
216-
// nothing uses this instruction.
217-
eraseUsesOfValue(User);
214+
// Instruction has been processed.
215+
if (Insts.find(User) != Insts.end())
216+
continue;
218217

219-
// Walk through the operand list and delete any random instructions that
220-
// will become trivially dead when this instruction is removed.
221-
for (auto &Op : User->getAllOperands()) {
222-
if (auto *OpI = dyn_cast<SILInstruction>(Op.get())) {
223-
// Don't recursively delete the pointer we're getting in.
224-
if (Op.get() != V) {
225-
Op.drop();
226-
recursivelyDeleteTriviallyDeadInstructions(OpI, false,
227-
[](SILInstruction *){});
228-
}
229-
}
230-
}
218+
// Collect the users of this instruction.
219+
Insts.insert(User);
220+
collectUsesOfValue(User, Insts);
221+
}
222+
}
231223

232-
User->eraseFromParent();
224+
void swift::eraseUsesOfValue(SILValue V) {
225+
llvm::DenseSet<SILInstruction *> Insts;
226+
// Collect the uses.
227+
collectUsesOfValue(V, Insts);
228+
// Erase the uses, we can have instructions that become dead because
229+
// of the removal of these instructions, leave to DCE to cleanup.
230+
// Its not safe to do recursively delete here as some of the SILInstruction
231+
// maybe tracked by this set.
232+
for (auto I : Insts) {
233+
I->replaceAllUsesWithUndef();
234+
I->eraseFromParent();
233235
}
234236
}
235237

0 commit comments

Comments
 (0)