Skip to content

Commit 5b6daed

Browse files
committed
Update DCE for @guaranteed forwarding phi support
1 parent e0f0cd0 commit 5b6daed

File tree

2 files changed

+93
-35
lines changed

2 files changed

+93
-35
lines changed

lib/SILOptimizer/Transforms/DeadCodeElimination.cpp

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@ static bool seemsUseful(SILInstruction *I) {
5050
// side-effects, they can be DCE'ed if they do not have useful
5151
// dependencies/reverse dependencies
5252
if (isa<BeginAccessInst>(I) || isa<CopyValueInst>(I) ||
53-
isa<DestroyValueInst>(I) || isa<EndLifetimeInst>(I))
53+
isa<DestroyValueInst>(I) || isa<EndLifetimeInst>(I) ||
54+
isa<EndBorrowInst>(I))
5455
return false;
5556

5657
// A load [copy] is okay to be DCE'ed if there are no useful dependencies
@@ -125,13 +126,12 @@ class DCE {
125126
llvm::DenseMap<SILValue, SmallPtrSet<SILInstruction *, 4>>
126127
ReverseDependencies;
127128

128-
// reborrowDependencies tracks the dependency of a reborrowed phiArg with its
129-
// renamed base value.
130-
// A reborrowed phiArg may have a new base value, if it's original base value
131-
// was also passed as a branch operand. The renamed base value should then be
132-
// live if the reborrow phiArg was also live.
129+
// guaranteedPhiDependencies tracks the dependency of a reborrowed phiArg with
130+
// its renamed base value. A reborrowed phiArg may have a new base value, if
131+
// it's original base value was also passed as a branch operand. The renamed
132+
// base value should then be live if the reborrow phiArg was also live.
133133
using BaseValueSet = SmallPtrSet<SILValue, 8>;
134-
llvm::DenseMap<SILPhiArgument *, BaseValueSet> reborrowDependencies;
134+
llvm::DenseMap<SILPhiArgument *, BaseValueSet> guaranteedPhiDependencies;
135135

136136
/// Tracks if the pass changed branches.
137137
bool BranchesChanged = false;
@@ -145,7 +145,7 @@ class DCE {
145145
void addReverseDependency(SILValue from, SILInstruction *to);
146146
/// Starting from \p borrowInst find all reborrow dependency of its reborrows
147147
/// with their renamed base values.
148-
void findReborrowDependencies(BeginBorrowInst *borrowInst);
148+
void findGuaranteedPhiDependencies(BeginBorrowInst *borrowInst);
149149
bool removeDead();
150150

151151
void computeLevelNumbers(PostDomTreeNode *root);
@@ -288,7 +288,6 @@ void DCE::markLive() {
288288
auto *borrowInst = cast<BeginBorrowInst>(&I);
289289
if (borrowInst->getOperand()->getOwnershipKind() ==
290290
OwnershipKind::Guaranteed) {
291-
markInstructionLive(borrowInst);
292291
// Visit the end_borrows of all the borrow scopes that this
293292
// begin_borrow could be borrowing.
294293
SmallVector<SILValue, 4> roots;
@@ -301,8 +300,8 @@ void DCE::markLive() {
301300
}
302301
continue;
303302
}
304-
// Populate reborrowDependencies for this borrow
305-
findReborrowDependencies(borrowInst);
303+
// Populate guaranteedPhiDependencies for this borrow
304+
findGuaranteedPhiDependencies(borrowInst);
306305
// Don't optimize a borrow scope if it is lexical or has a pointer
307306
// escape.
308307
if (borrowInst->isLexical() ||
@@ -337,19 +336,20 @@ void DCE::addReverseDependency(SILValue from, SILInstruction *to) {
337336
ReverseDependencies[from].insert(to);
338337
}
339338

340-
void DCE::findReborrowDependencies(BeginBorrowInst *borrowInst) {
341-
LLVM_DEBUG(llvm::dbgs() << "Finding reborrow dependencies of " << borrowInst
342-
<< "\n");
339+
void DCE::findGuaranteedPhiDependencies(BeginBorrowInst *borrowInst) {
340+
LLVM_DEBUG(llvm::dbgs() << "Finding @guaranteed phi dependencies of "
341+
<< borrowInst << "\n");
343342
BorrowingOperand initialScopedOperand(&borrowInst->getOperandRef());
344-
auto visitReborrowBaseValuePair = [&](SILPhiArgument *phiArg,
345-
SILValue baseValue) {
346-
reborrowDependencies[phiArg].insert(baseValue);
343+
auto visitDependentPhiBaseValuePair = [&](SILPhiArgument *phiArg,
344+
SILValue baseValue) {
345+
guaranteedPhiDependencies[phiArg].insert(baseValue);
347346
};
348-
// Find all reborrow dependencies starting from \p borrowInst and populate
349-
// them in reborrowDependencies
350-
findTransitiveReborrowBaseValuePairs(initialScopedOperand,
351-
borrowInst->getOperand(),
352-
visitReborrowBaseValuePair);
347+
// Find all dependencies starting from \p borrowInst and populate
348+
// them in guaranteedPhiDependencies
349+
visitExtendedReborrowPhiBaseValuePairs(borrowInst,
350+
visitDependentPhiBaseValuePair);
351+
visitExtendedGuaranteedForwardingPhiBaseValuePairs(
352+
BorrowedValue(borrowInst), visitDependentPhiBaseValuePair);
353353
}
354354

355355
// Mark as live the terminator argument at index ArgIndex in Pred that
@@ -429,7 +429,7 @@ void DCE::propagateLiveBlockArgument(SILArgument *Arg) {
429429
}
430430

431431
if (auto *phi = dyn_cast<SILPhiArgument>(Arg)) {
432-
for (auto depVal : reborrowDependencies.lookup(phi)) {
432+
for (auto depVal : guaranteedPhiDependencies.lookup(phi)) {
433433
markValueLive(depVal);
434434
}
435435
}

test/SILOptimizer/dead_code_elimination_nontrivial_ossa.sil

Lines changed: 70 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,14 @@ case none
2323
case some(T)
2424
}
2525

26+
struct Wrapper1 {
27+
var val1: Wrapper2
28+
}
29+
30+
struct Wrapper2 {
31+
var val2: Klass
32+
}
33+
2634
sil [ossa] @$testtryapplyklassgen : $@convention(thin) () -> (@owned Klass, @error any Error)
2735
sil [ossa] @$use_klass1 : $@convention(thin) (@owned Klass) -> ()
2836
sil [ossa] @$use_klass2 : $@convention(thin) (@guaranteed Klass) -> ()
@@ -728,17 +736,10 @@ bb3(%original : @owned $Klass, %lifetime : @guaranteed $Klass):
728736

729737
// CHECK-LABEL: sil [ossa] @borrow_none : {{.*}} {
730738
// CHECK: {{bb[0-9]+}}:
731-
// CHECK: [[INSTANCE:%[^,]+]] = enum $FakeOptional<Klass>, #FakeOptional.none!enumelt
732-
// CHECK: switch_enum [[INSTANCE]] : $FakeOptional<Klass>, case #FakeOptional.some!enumelt: [[WORK:bb[0-9]+]], case #FakeOptional.none!enumelt: [[TO_EXIT:bb[0-9]+]], forwarding: @guaranteed
733-
// CHECK: [[TO_EXIT]]:
734-
// CHECK: br [[EXIT:bb[0-9]+]]
735-
// CHECK: [[WORK]]([[PAYLOAD:%[^,]+]] : @guaranteed $Klass):
736-
// CHECK: [[LIFETIME:%[^,]+]] = begin_borrow [[PAYLOAD]]
737-
// CHECK: end_borrow [[LIFETIME]]
738-
// CHECK: br [[EXIT]]
739+
// CHECK-NEXT: br [[EXIT:bb[0-9]+]]
739740
// CHECK: [[EXIT]]:
740-
// CHECK: [[RETVAL:%[^,]+]] = tuple ()
741-
// CHECK: return [[RETVAL]] : $()
741+
// CHECK-NEXT: [[RETVAL:%[^,]+]] = tuple ()
742+
// CHECK-NEXT: return [[RETVAL]] : $()
742743
// CHECK-LABEL: } // end sil function 'borrow_none'
743744
sil [ossa] @borrow_none : $@convention(thin) () -> () {
744745
entry:
@@ -810,8 +811,6 @@ exit(%outer_lifetime_3 : @guaranteed $Klass, %inner_lifetime_2 : @guaranteed $Kl
810811
// CHECK: [[BORROW_EITHER:%[^,]+]] = begin_borrow [[EITHER]]
811812
// CHECK: switch_enum [[BORROW_EITHER]] : $EitherNoneOrAnyObject, case #EitherNoneOrAnyObject.none!enumelt: [[NONE_BLOCK:bb[0-9]+]], case #EitherNoneOrAnyObject.any!enumelt: [[SOME_BLOCK:bb[0-9]+]]
812813
// CHECK: [[SOME_BLOCK]]([[PAYLOAD:%[^,]+]] : @guaranteed $AnyObject):
813-
// CHECK: [[LIFETIME:%[^,]+]] = begin_borrow [[PAYLOAD]]
814-
// CHECK: end_borrow [[LIFETIME]]
815814
// CHECK: end_borrow [[BORROW_EITHER]]
816815
// CHECK: destroy_value [[EITHER]]
817816
// CHECK: br [[EXIT:bb[0-9]+]]
@@ -845,6 +844,18 @@ exit:
845844
return %retval : $()
846845
}
847846

847+
sil [ossa] @reborrowed_guaranteed_phi3 : $@convention(thin) (@owned Klass) -> () {
848+
entry(%instance : @owned $Klass):
849+
%outer_lifetime_1 = begin_borrow %instance : $Klass
850+
%inner_lifetime_1 = begin_borrow %outer_lifetime_1 : $Klass
851+
br exit(%inner_lifetime_1 : $Klass)
852+
exit(%inner_lifetime_2 : @guaranteed $Klass):
853+
end_borrow %inner_lifetime_2 : $Klass
854+
end_borrow %outer_lifetime_1 : $Klass
855+
destroy_value %instance : $Klass
856+
%retval = tuple ()
857+
return %retval : $()
858+
}
848859
// CHECK-LABEL: sil [ossa] @reborrow_load_borrow : {{.*}} {
849860
// CHECK: {{bb[0-9]+}}([[INSTANCE:%[^,]+]] : $*Klass):
850861
// CHECK: [[LIFETIME:%[^,]+]] = load_borrow [[INSTANCE]]
@@ -998,3 +1009,50 @@ bb1(%21 : $@noescape @callee_guaranteed () -> (), %22 : @guaranteed $@callee_gua
9981009
%28 = tuple ()
9991010
return %28: $()
10001011
}
1012+
1013+
sil @use_klass : $@convention(thin) (@guaranteed Klass) -> ()
1014+
1015+
sil [ossa] @test_forwarded_phi4 : $@convention(thin) (@owned Wrapper1) -> () {
1016+
bb0(%0 : @owned $Wrapper1):
1017+
%outer = begin_borrow %0 : $Wrapper1
1018+
br bb1
1019+
1020+
bb1:
1021+
%ex1 = struct_extract %outer : $Wrapper1, #Wrapper1.val1
1022+
br bb2(%ex1 : $Wrapper2, %outer : $Wrapper1)
1023+
1024+
bb2(%phi1 : @guaranteed $Wrapper2, %phi2 : @guaranteed $Wrapper1):
1025+
%ex2 = struct_extract %phi1 : $Wrapper2, #Wrapper2.val2
1026+
br bb3(%ex2 : $Klass, %phi2 : $Wrapper1)
1027+
1028+
bb3(%phi3 : @guaranteed $Klass, %phi4 : @guaranteed $Wrapper1):
1029+
%f = function_ref @use_klass : $@convention(thin) (@guaranteed Klass) -> ()
1030+
apply %f(%phi3) : $@convention(thin) (@guaranteed Klass) -> ()
1031+
end_borrow %phi4 : $Wrapper1
1032+
destroy_value %0 : $Wrapper1
1033+
%9999 = tuple()
1034+
return %9999 : $()
1035+
}
1036+
1037+
sil [ossa] @test_loadborrow_dep : $@convention(thin) (@in Wrapper1) -> () {
1038+
bb0(%0 : $*Wrapper1):
1039+
%outer = load_borrow %0 : $*Wrapper1
1040+
br bb1
1041+
1042+
bb1:
1043+
%ex1 = struct_extract %outer : $Wrapper1, #Wrapper1.val1
1044+
br bb2(%ex1 : $Wrapper2, %outer : $Wrapper1)
1045+
1046+
bb2(%phi1 : @guaranteed $Wrapper2, %phi2 : @guaranteed $Wrapper1):
1047+
%ex2 = struct_extract %phi1 : $Wrapper2, #Wrapper2.val2
1048+
br bb3(%ex2 : $Klass, %phi2 : $Wrapper1)
1049+
1050+
bb3(%phi3 : @guaranteed $Klass, %phi4 : @guaranteed $Wrapper1):
1051+
%f = function_ref @use_klass : $@convention(thin) (@guaranteed Klass) -> ()
1052+
apply %f(%phi3) : $@convention(thin) (@guaranteed Klass) -> ()
1053+
end_borrow %phi4 : $Wrapper1
1054+
destroy_addr %0 : $*Wrapper1
1055+
%9999 = tuple()
1056+
return %9999 : $()
1057+
}
1058+

0 commit comments

Comments
 (0)