Skip to content

Commit 27e2ed1

Browse files
authored
Merge pull request swiftlang#74078 from atrick/60-fix-silcombine-dead-code
[6.0] Fix SILCombine to delete dead end_access instructions.
2 parents f39041d + 6986a9c commit 27e2ed1

File tree

4 files changed

+61
-3
lines changed

4 files changed

+61
-3
lines changed

include/swift/SIL/InstructionUtils.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,16 @@ SILValue stripBorrow(SILValue V);
107107
/// type may be changed by a cast.
108108
SingleValueInstruction *getSingleValueCopyOrCast(SILInstruction *I);
109109

110+
// Return true if this instruction begins a SIL-level scope. If so, it must have
111+
// a single result. That result must have an isEndOfScopeMarker direct use on
112+
// all reachable paths. This instruction along with its scope-ending
113+
// instructions are considered a single operation. They must be inserted and
114+
// deleted together.
115+
bool isBeginScopeMarker(SILInstruction *user);
116+
110117
/// Return true if this instruction terminates a SIL-level scope. Scope end
111-
/// instructions do not produce a result.
118+
/// instructions do not produce a result. Their single operand must be an
119+
/// isBeginScopeMarker and cannot be 'undef'.
112120
bool isEndOfScopeMarker(SILInstruction *user);
113121

114122
/// Return true if the given instruction has no effect on it's operand values

lib/SIL/Utils/InstructionUtils.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,16 @@ SingleValueInstruction *swift::getSingleValueCopyOrCast(SILInstruction *I) {
295295
}
296296
}
297297

298-
// Does this instruction terminate a SIL-level scope?
298+
bool swift::isBeginScopeMarker(SILInstruction *user) {
299+
switch (user->getKind()) {
300+
default:
301+
return false;
302+
case SILInstructionKind::BeginAccessInst:
303+
case SILInstructionKind::BeginBorrowInst:
304+
return true;
305+
}
306+
}
307+
299308
bool swift::isEndOfScopeMarker(SILInstruction *user) {
300309
switch (user->getKind()) {
301310
default:

lib/SILOptimizer/SILCombiner/SILCombinerMiscVisitors.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -844,6 +844,15 @@ SILInstruction *SILCombiner::visitCondFailInst(CondFailInst *CFI) {
844844
ValueSet DefinedValues(CFI->getFunction());
845845
for (auto Iter = std::next(CFI->getIterator());
846846
Iter != CFI->getParent()->end(); ++Iter) {
847+
848+
if (isBeginScopeMarker(&*Iter)) {
849+
for (auto *scopeUse : cast<SingleValueInstruction>(&*Iter)->getUses()) {
850+
auto *scopeEnd = scopeUse->getUser();
851+
if (isEndOfScopeMarker(scopeEnd)) {
852+
ToRemove.push_back(scopeEnd);
853+
}
854+
}
855+
}
847856
if (!CFI->getFunction()->hasOwnership()) {
848857
ToRemove.push_back(&*Iter);
849858
continue;
@@ -870,6 +879,9 @@ SILInstruction *SILCombiner::visitCondFailInst(CondFailInst *CFI) {
870879
return nullptr;
871880

872881
for (auto *Inst : ToRemove) {
882+
if (Inst->isDeleted())
883+
continue;
884+
873885
// Replace any still-remaining uses with undef and erase.
874886
Inst->replaceAllUsesOfAllResultsWithUndef();
875887
eraseInstFromFunction(*Inst);

test/SILOptimizer/sil_combine.sil

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -587,6 +587,35 @@ bb0(%0 : $Builtin.Int1):
587587
return %2 : $()
588588
}
589589

590+
// rdar://121599876 (SILCombine should delete instructions in blocks dominated by cond_fail -1)
591+
// CHECK-LABEL: sil @cond_fail_end_scope : $@convention(thin) (@inout Builtin.Int32, Builtin.Int1) -> () {
592+
// CHECK: cond_fail
593+
// CHECK-NEXT: unreachable
594+
// CHECK: bb1:
595+
// CHECK-NEXT: br bb3
596+
// CHECK: bb2:
597+
// CHECK-NEXT: br bb3
598+
// CHECK-LABEL: } // end sil function 'cond_fail_end_scope'
599+
sil @cond_fail_end_scope : $@convention(thin) (@inout Builtin.Int32, Builtin.Int1) -> () {
600+
entry(%0 : $*Builtin.Int32, %1 : $Builtin.Int1):
601+
%true = integer_literal $Builtin.Int1, -1
602+
cond_fail %true : $Builtin.Int1
603+
%access = begin_access [read] [static] %0 : $*Builtin.Int32
604+
cond_br %1, left, right
605+
606+
left:
607+
end_access %access : $*Builtin.Int32
608+
br end
609+
610+
right:
611+
end_access %access : $*Builtin.Int32
612+
br end
613+
614+
end:
615+
%99 = tuple ()
616+
return %99 : $()
617+
}
618+
590619
// CHECK-LABEL: sil @release_then_retain_peephole
591620
// CHECK: bb0
592621
// CHECK-NOT: strong_release
@@ -3688,7 +3717,7 @@ bb3(%16 : $Int32): // Preds: bb1 bb2
36883717
return %16 : $Int32 // id: %17
36893718
}
36903719

3691-
protocol Prot0 : class {
3720+
protocol Prot0 : AnyObject {
36923721
static func newWithConfig() throws -> Builtin.Int32
36933722
}
36943723

0 commit comments

Comments
 (0)