Skip to content

Commit c0f4278

Browse files
Merge pull request #69925 from nate-chandler/cherrypick/release/5.10/bug/20231115/1/dce_instdeleter_loadtake
5.10: [DCE] Process instructions added during deletion.
2 parents 4b63624 + cc0430c commit c0f4278

File tree

4 files changed

+59
-14
lines changed

4 files changed

+59
-14
lines changed

include/swift/SILOptimizer/Utils/CFGOptUtils.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
#include "swift/SIL/SILBuilder.h"
2727
#include "swift/SIL/SILInstruction.h"
28+
#include "swift/SILOptimizer/Utils/InstModCallbacks.h"
2829
#include "swift/SILOptimizer/Utils/InstructionDeleter.h"
2930

3031
namespace llvm {
@@ -36,7 +37,6 @@ namespace swift {
3637
class DominanceInfo;
3738
class SILLoop;
3839
class SILLoopInfo;
39-
struct InstModCallbacks;
4040

4141
/// Adds a new argument to an edge between a branch and a destination
4242
/// block. Allows for user injected callbacks via \p callbacks.
@@ -65,14 +65,16 @@ TermInst *changeEdgeValue(TermInst *branch, SILBasicBlock *dest, size_t idx,
6565
/// specified index. Asserts internally that the argument along the edge does
6666
/// not have uses.
6767
TermInst *deleteEdgeValue(TermInst *branch, SILBasicBlock *destBlock,
68-
size_t argIndex, bool cleanupDeadPhiOp = true);
68+
size_t argIndex, bool cleanupDeadPhiOp = true,
69+
InstModCallbacks callbacks = InstModCallbacks());
6970

7071
/// Erase the \p argIndex phi argument from \p block. Asserts that the argument
7172
/// is a /real/ phi argument. Removes all incoming values for the argument from
7273
/// predecessor terminators. Asserts internally that it only ever is given
7374
/// "true" phi argument.
7475
void erasePhiArgument(SILBasicBlock *block, unsigned argIndex,
75-
bool cleanupDeadPhiOp = true);
76+
bool cleanupDeadPhiOp = true,
77+
InstModCallbacks callbacks = InstModCallbacks());
7678

7779
/// Check if the edge from the terminator is critical.
7880
bool isCriticalEdge(TermInst *t, unsigned edgeIdx);

lib/SILOptimizer/Transforms/DeadCodeElimination.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -657,7 +657,9 @@ bool DCE::removeDead() {
657657

658658
endLifetimeOfLiveValue(phiArg->getIncomingPhiValue(pred), insertPt);
659659
}
660-
erasePhiArgument(&BB, i);
660+
erasePhiArgument(&BB, i, /*cleanupDeadPhiOps=*/true,
661+
InstModCallbacks().onCreateNewInst(
662+
[&](auto *inst) { markInstructionLive(inst); }));
661663
Changed = true;
662664
BranchesChanged = true;
663665
}

lib/SILOptimizer/Utils/CFGOptUtils.cpp

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -74,21 +74,22 @@ TermInst *swift::addNewEdgeValueToBranch(TermInst *branch, SILBasicBlock *dest,
7474
return newBr;
7575
}
7676

77-
static void
78-
deleteTriviallyDeadOperandsOfDeadArgument(MutableArrayRef<Operand> termOperands,
79-
unsigned deadArgIndex) {
77+
static void deleteTriviallyDeadOperandsOfDeadArgument(
78+
MutableArrayRef<Operand> termOperands, unsigned deadArgIndex,
79+
InstModCallbacks callbacks = InstModCallbacks()) {
8080
Operand &op = termOperands[deadArgIndex];
8181
auto *i = op.get()->getDefiningInstruction();
8282
if (!i)
8383
return;
8484
op.set(SILUndef::get(op.get()->getType(), *i->getFunction()));
85-
eliminateDeadInstruction(i);
85+
eliminateDeadInstruction(i, callbacks);
8686
}
8787

8888
// Our implementation assumes that our caller is attempting to remove a dead
8989
// SILPhiArgument from a SILBasicBlock and has already RAUWed the argument.
9090
TermInst *swift::deleteEdgeValue(TermInst *branch, SILBasicBlock *destBlock,
91-
size_t argIndex, bool cleanupDeadPhiOps) {
91+
size_t argIndex, bool cleanupDeadPhiOps,
92+
InstModCallbacks callbacks) {
9293
if (auto *cbi = dyn_cast<CondBranchInst>(branch)) {
9394
SmallVector<SILValue, 8> trueArgs;
9495
SmallVector<SILValue, 8> falseArgs;
@@ -99,15 +100,15 @@ TermInst *swift::deleteEdgeValue(TermInst *branch, SILBasicBlock *destBlock,
99100
if (destBlock == cbi->getTrueBB()) {
100101
if (cleanupDeadPhiOps) {
101102
deleteTriviallyDeadOperandsOfDeadArgument(cbi->getTrueOperands(),
102-
argIndex);
103+
argIndex, callbacks);
103104
}
104105
trueArgs.erase(trueArgs.begin() + argIndex);
105106
}
106107

107108
if (destBlock == cbi->getFalseBB()) {
108109
if (cleanupDeadPhiOps) {
109110
deleteTriviallyDeadOperandsOfDeadArgument(cbi->getFalseOperands(),
110-
argIndex);
111+
argIndex, callbacks);
111112
}
112113
falseArgs.erase(falseArgs.begin() + argIndex);
113114
}
@@ -125,7 +126,8 @@ TermInst *swift::deleteEdgeValue(TermInst *branch, SILBasicBlock *destBlock,
125126
SmallVector<SILValue, 8> args;
126127
llvm::copy(bi->getArgs(), std::back_inserter(args));
127128
if (cleanupDeadPhiOps) {
128-
deleteTriviallyDeadOperandsOfDeadArgument(bi->getAllOperands(), argIndex);
129+
deleteTriviallyDeadOperandsOfDeadArgument(bi->getAllOperands(), argIndex,
130+
callbacks);
129131
}
130132
args.erase(args.begin() + argIndex);
131133
auto *result = SILBuilderWithScope(bi).createBranch(bi->getLoc(),
@@ -138,7 +140,8 @@ TermInst *swift::deleteEdgeValue(TermInst *branch, SILBasicBlock *destBlock,
138140
}
139141

140142
void swift::erasePhiArgument(SILBasicBlock *block, unsigned argIndex,
141-
bool cleanupDeadPhiOps) {
143+
bool cleanupDeadPhiOps,
144+
InstModCallbacks callbacks) {
142145
assert(block->getArgument(argIndex)->isPhi()
143146
&& "Only should be used on phi arguments");
144147
block->eraseArgument(argIndex);
@@ -155,7 +158,8 @@ void swift::erasePhiArgument(SILBasicBlock *block, unsigned argIndex,
155158
predBlocks.insert(pred);
156159

157160
for (auto *pred : predBlocks)
158-
deleteEdgeValue(pred->getTerminator(), block, argIndex, cleanupDeadPhiOps);
161+
deleteEdgeValue(pred->getTerminator(), block, argIndex, cleanupDeadPhiOps,
162+
callbacks);
159163
}
160164

161165
/// Changes the edge value between a branch and destination basic block

test/SILOptimizer/dead_code_elimination_ossa.sil

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,3 +432,40 @@ bb0(%0 : @owned $MO):
432432
%63 = tuple ()
433433
return %63 : $()
434434
}
435+
436+
// The InstructionDeleter will delete the `load [take]` and insert a
437+
// `destroy_addr`. Observe the creation of the new destroy_addr instruction
438+
// that occurs when deleting the `load [take]` and mark it live. Prevents a
439+
// leak.
440+
// CHECK-LABEL: sil [ossa] @keep_new_destroy_addr : {{.*}} {
441+
// CHECK: destroy_addr
442+
// CHECK-LABEL: } // end sil function 'keep_new_destroy_addr'
443+
sil [ossa] @keep_new_destroy_addr : $@convention(thin) () -> () {
444+
bb0:
445+
try_apply undef() : $@convention(thin) () -> @error any Error, normal bb1, error bb5
446+
447+
bb1(%4 : $()):
448+
%err = alloc_stack $any Error
449+
try_apply undef<any Error>(%err) : $@convention(method) <τ_1_1 where τ_1_1 : Error> () -> (@out τ_1_1, @error any Error), normal bb2, error bb6
450+
451+
bb6(%e : @owned $any Error):
452+
destroy_value %e : $any Error
453+
dealloc_stack %err : $*any Error
454+
br bb3
455+
456+
bb4(%24 : @owned $any Error):
457+
destroy_value %24 : $any Error
458+
br bb3
459+
460+
bb5(%30 : @owned $any Error):
461+
br bb4(%30 : $any Error)
462+
463+
bb2(%15 : $()):
464+
%33 = load [take] %err : $*any Error
465+
dealloc_stack %err : $*any Error
466+
br bb4(%33 : $any Error)
467+
468+
bb3:
469+
%22 = tuple ()
470+
return %22 : $()
471+
}

0 commit comments

Comments
 (0)