Skip to content

Commit 797c1d8

Browse files
committed
Update DCE for @guaranteed forwarding phi support
1 parent 69ba7e1 commit 797c1d8

File tree

2 files changed

+113
-56
lines changed

2 files changed

+113
-56
lines changed

lib/SILOptimizer/Transforms/DeadCodeElimination.cpp

Lines changed: 34 additions & 26 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,13 @@ 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 reborrows and
130+
// @guaranteed forwarding phis with its base value.
131+
// If the base value is also passed along as a phi operand with the reborrow operand/@guaranteed
132+
// forwarding phi operand, we will have a new base value for the reborrow
133+
// phi/@guaranteed forwarding phi.
133134
using BaseValueSet = SmallPtrSet<SILValue, 8>;
134-
llvm::DenseMap<SILPhiArgument *, BaseValueSet> reborrowDependencies;
135+
llvm::DenseMap<SILPhiArgument *, BaseValueSet> guaranteedPhiDependencies;
135136

136137
/// Tracks if the pass changed branches.
137138
bool BranchesChanged = false;
@@ -143,9 +144,9 @@ class DCE {
143144
/// Record a reverse dependency from \p from to \p to meaning \p to is live
144145
/// if \p from is also live.
145146
void addReverseDependency(SILValue from, SILInstruction *to);
146-
/// Starting from \p borrowInst find all reborrow dependency of its reborrows
147-
/// with their renamed base values.
148-
void findReborrowDependencies(BeginBorrowInst *borrowInst);
147+
/// Starting from \p borrow find all reborrow and guaranteed phi dependencies
148+
/// along with their base values.
149+
void findGuaranteedPhiDependencies(BorrowedValue borrow);
149150
bool removeDead();
150151

151152
void computeLevelNumbers(PostDomTreeNode *root);
@@ -288,7 +289,6 @@ void DCE::markLive() {
288289
auto *borrowInst = cast<BeginBorrowInst>(&I);
289290
if (borrowInst->getOperand()->getOwnershipKind() ==
290291
OwnershipKind::Guaranteed) {
291-
markInstructionLive(borrowInst);
292292
// Visit the end_borrows of all the borrow scopes that this
293293
// begin_borrow could be borrowing.
294294
SmallVector<SILValue, 4> roots;
@@ -301,8 +301,8 @@ void DCE::markLive() {
301301
}
302302
continue;
303303
}
304-
// Populate reborrowDependencies for this borrow
305-
findReborrowDependencies(borrowInst);
304+
// Populate guaranteedPhiDependencies for this borrow
305+
findGuaranteedPhiDependencies(BorrowedValue(borrowInst));
306306
// Don't optimize a borrow scope if it is lexical or has a pointer
307307
// escape.
308308
if (borrowInst->isLexical() ||
@@ -315,6 +315,10 @@ void DCE::markLive() {
315315
}
316316
break;
317317
}
318+
case SILInstructionKind::LoadBorrowInst: {
319+
findGuaranteedPhiDependencies(BorrowedValue(cast<LoadBorrowInst>(&I)));
320+
break;
321+
}
318322
default:
319323
if (seemsUseful(&I))
320324
markInstructionLive(&I);
@@ -337,19 +341,23 @@ void DCE::addReverseDependency(SILValue from, SILInstruction *to) {
337341
ReverseDependencies[from].insert(to);
338342
}
339343

340-
void DCE::findReborrowDependencies(BeginBorrowInst *borrowInst) {
341-
LLVM_DEBUG(llvm::dbgs() << "Finding reborrow dependencies of " << borrowInst
342-
<< "\n");
343-
BorrowingOperand initialScopedOperand(&borrowInst->getOperandRef());
344-
auto visitReborrowBaseValuePair = [&](SILPhiArgument *phiArg,
345-
SILValue baseValue) {
346-
reborrowDependencies[phiArg].insert(baseValue);
344+
void DCE::findGuaranteedPhiDependencies(BorrowedValue borrow) {
345+
assert(borrow.kind == BorrowedValueKind::BeginBorrow ||
346+
borrow.kind == BorrowedValueKind::LoadBorrow);
347+
LLVM_DEBUG(llvm::dbgs() << "Finding @guaranteed phi dependencies of "
348+
<< borrow << "\n");
349+
auto visitDependentPhiBaseValuePair = [&](SILPhiArgument *phiArg,
350+
SILValue baseValue) {
351+
guaranteedPhiDependencies[phiArg].insert(baseValue);
347352
};
348-
// Find all reborrow dependencies starting from \p borrowInst and populate
349-
// them in reborrowDependencies
350-
findTransitiveReborrowBaseValuePairs(initialScopedOperand,
351-
borrowInst->getOperand(),
352-
visitReborrowBaseValuePair);
353+
// Find all dependencies starting from \p borrowInst and populate
354+
// them in guaranteedPhiDependencies
355+
if (borrow.kind == BorrowedValueKind::BeginBorrow) {
356+
visitExtendedReborrowPhiBaseValuePairs(cast<BeginBorrowInst>(borrow.value),
357+
visitDependentPhiBaseValuePair);
358+
}
359+
visitExtendedGuaranteedForwardingPhiBaseValuePairs(
360+
borrow, visitDependentPhiBaseValuePair);
353361
}
354362

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

431439
if (auto *phi = dyn_cast<SILPhiArgument>(Arg)) {
432-
for (auto depVal : reborrowDependencies.lookup(phi)) {
440+
for (auto depVal : guaranteedPhiDependencies.lookup(phi)) {
433441
markValueLive(depVal);
434442
}
435443
}

test/SILOptimizer/dead_code_elimination_nontrivial_ossa.sil

Lines changed: 79 additions & 30 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,23 @@ exit:
845844
return %retval : $()
846845
}
847846

847+
// CHECK-LABEL: sil [ossa] @reborrowed_guaranteed_phi3 :
848+
// CHECK: begin_borrow
849+
// CHECK-NOT: begin_borrow
850+
// CHECK-LABEL: } // end sil function 'reborrowed_guaranteed_phi3'
851+
sil [ossa] @reborrowed_guaranteed_phi3 : $@convention(thin) (@owned Klass) -> () {
852+
entry(%instance : @owned $Klass):
853+
%outer_lifetime_1 = begin_borrow %instance : $Klass
854+
%inner_lifetime_1 = begin_borrow %outer_lifetime_1 : $Klass
855+
br exit(%inner_lifetime_1 : $Klass)
856+
exit(%inner_lifetime_2 : @guaranteed $Klass):
857+
end_borrow %inner_lifetime_2 : $Klass
858+
end_borrow %outer_lifetime_1 : $Klass
859+
destroy_value %instance : $Klass
860+
%retval = tuple ()
861+
return %retval : $()
862+
}
863+
848864
// CHECK-LABEL: sil [ossa] @reborrow_load_borrow : {{.*}} {
849865
// CHECK: {{bb[0-9]+}}([[INSTANCE:%[^,]+]] : $*Klass):
850866
// CHECK: [[LIFETIME:%[^,]+]] = load_borrow [[INSTANCE]]
@@ -890,13 +906,7 @@ bb1(%4 : @guaranteed $Klass, %5 : @guaranteed $Klass):
890906

891907
// CHECK-LABEL: sil [ossa] @borrow_guaranteed_tuple : {{.*}} {
892908
// CHECK: {{bb[0-9]+}}([[INSTANCE_1:%[^,]+]] : @owned $Klass, [[INSTANCE_2:%[^,]+]] : @owned $Klass):
893-
// CHECK: [[LIFETIME_1_1:%[^,]+]] = begin_borrow [[INSTANCE_1]]
894-
// CHECK: [[LIFETIME_2_1:%[^,]+]] = begin_borrow [[INSTANCE_2]]
895-
// CHECK: br [[EXIT:bb[0-9]+]]([[LIFETIME_1_1]] : $Klass, [[LIFETIME_2_1]] : $Klass)
896-
// CHECK: [[EXIT]]([[LIFETIME_1_2:%[^,]+]] : @guaranteed $Klass, [[LIFETIME_2_2:%[^,]+]] : @guaranteed $Klass):
897-
// CHECK: end_borrow [[LIFETIME_2_2]]
898909
// CHECK: destroy_value [[INSTANCE_2]]
899-
// CHECK: end_borrow [[LIFETIME_1_2]]
900910
// CHECK: destroy_value [[INSTANCE_1]]
901911
// CHECK: [[RETVAL:%[^,]+]] = tuple ()
902912
// CHECK: return [[RETVAL]] : $()
@@ -906,10 +916,8 @@ entry(%instance_1 : @owned $Klass, %instance_2 : @owned $Klass):
906916
%lifetime_1_1 = begin_borrow %instance_1 : $Klass
907917
%lifetime_2_1 = begin_borrow %instance_2 : $Klass
908918
%tuple = tuple $(Klass, Klass) (%lifetime_1_1, %lifetime_2_1)
909-
%tuple_lifetime_1 = begin_borrow %tuple : $(Klass, Klass)
910-
br exit(%lifetime_1_1 : $Klass, %lifetime_2_1 : $Klass, %tuple_lifetime_1 : $(Klass, Klass))
911-
exit(%lifetime_1_2 : @guaranteed $Klass, %lifetime_2_2 : @guaranteed $Klass, %tuple_lifetime_2 : @guaranteed $(Klass, Klass)):
912-
end_borrow %tuple_lifetime_2 : $(Klass, Klass)
919+
br exit(%lifetime_1_1 : $Klass, %lifetime_2_1 : $Klass, %tuple : $(Klass, Klass))
920+
exit(%lifetime_1_2 : @guaranteed $Klass, %lifetime_2_2 : @guaranteed $Klass, %tuple_2 : @guaranteed $(Klass, Klass)):
913921
end_borrow %lifetime_2_2 : $Klass
914922
destroy_value %instance_2 : $Klass
915923
end_borrow %lifetime_1_2 : $Klass
@@ -920,10 +928,6 @@ exit(%lifetime_1_2 : @guaranteed $Klass, %lifetime_2_2 : @guaranteed $Klass, %tu
920928

921929
// CHECK-LABEL: sil [ossa] @borrow_guaranteed_struct : {{.*}} {
922930
// CHECK: {{bb[0-9]+}}([[INSTANCE:%[^,]+]] : @owned $Klass):
923-
// CHECK: [[LIFETIME:%[^,]+]] = begin_borrow [[INSTANCE]]
924-
// CHECK: br bb1([[LIFETIME]] : $Klass)
925-
// CHECK: bb1([[LIFETIME_2:%[^,]+]] : @guaranteed $Klass):
926-
// CHECK: end_borrow [[LIFETIME_2]]
927931
// CHECK: destroy_value [[INSTANCE]]
928932
// CHECK: [[RETVAL:%[^,]+]] = tuple ()
929933
// CHECK: return [[RETVAL]] : $()
@@ -932,10 +936,8 @@ sil [ossa] @borrow_guaranteed_struct : $@convention(thin) (@owned Klass) -> () {
932936
entry(%instance_1 : @owned $Klass):
933937
%lifetime_1 = begin_borrow %instance_1 : $Klass
934938
%struct = struct $NonTrivialStruct (%lifetime_1 : $Klass)
935-
%struct_lifetime_1 = begin_borrow %struct : $NonTrivialStruct
936-
br exit(%lifetime_1 : $Klass, %struct_lifetime_1 : $NonTrivialStruct)
937-
exit(%lifetime_2 : @guaranteed $Klass, %struct_lifetime_2 : @guaranteed $NonTrivialStruct):
938-
end_borrow %struct_lifetime_2 : $NonTrivialStruct
939+
br exit(%lifetime_1 : $Klass, %struct : $NonTrivialStruct)
940+
exit(%lifetime_2 : @guaranteed $Klass, %struct_2 : @guaranteed $NonTrivialStruct):
939941
end_borrow %lifetime_2 : $Klass
940942
destroy_value %instance_1 : $Klass
941943
%retval = tuple ()
@@ -998,3 +1000,50 @@ bb1(%21 : $@noescape @callee_guaranteed () -> (), %22 : @guaranteed $@callee_gua
9981000
%28 = tuple ()
9991001
return %28: $()
10001002
}
1003+
1004+
sil @use_klass : $@convention(thin) (@guaranteed Klass) -> ()
1005+
1006+
sil [ossa] @test_forwarded_phi4 : $@convention(thin) (@owned Wrapper1) -> () {
1007+
bb0(%0 : @owned $Wrapper1):
1008+
%outer = begin_borrow %0 : $Wrapper1
1009+
br bb1
1010+
1011+
bb1:
1012+
%ex1 = struct_extract %outer : $Wrapper1, #Wrapper1.val1
1013+
br bb2(%ex1 : $Wrapper2, %outer : $Wrapper1)
1014+
1015+
bb2(%phi1 : @guaranteed $Wrapper2, %phi2 : @guaranteed $Wrapper1):
1016+
%ex2 = struct_extract %phi1 : $Wrapper2, #Wrapper2.val2
1017+
br bb3(%ex2 : $Klass, %phi2 : $Wrapper1)
1018+
1019+
bb3(%phi3 : @guaranteed $Klass, %phi4 : @guaranteed $Wrapper1):
1020+
%f = function_ref @use_klass : $@convention(thin) (@guaranteed Klass) -> ()
1021+
apply %f(%phi3) : $@convention(thin) (@guaranteed Klass) -> ()
1022+
end_borrow %phi4 : $Wrapper1
1023+
destroy_value %0 : $Wrapper1
1024+
%9999 = tuple()
1025+
return %9999 : $()
1026+
}
1027+
1028+
sil [ossa] @test_loadborrow_dep : $@convention(thin) (@in Wrapper1) -> () {
1029+
bb0(%0 : $*Wrapper1):
1030+
%outer = load_borrow %0 : $*Wrapper1
1031+
br bb1
1032+
1033+
bb1:
1034+
%ex1 = struct_extract %outer : $Wrapper1, #Wrapper1.val1
1035+
br bb2(%ex1 : $Wrapper2, %outer : $Wrapper1)
1036+
1037+
bb2(%phi1 : @guaranteed $Wrapper2, %phi2 : @guaranteed $Wrapper1):
1038+
%ex2 = struct_extract %phi1 : $Wrapper2, #Wrapper2.val2
1039+
br bb3(%ex2 : $Klass, %phi2 : $Wrapper1)
1040+
1041+
bb3(%phi3 : @guaranteed $Klass, %phi4 : @guaranteed $Wrapper1):
1042+
%f = function_ref @use_klass : $@convention(thin) (@guaranteed Klass) -> ()
1043+
apply %f(%phi3) : $@convention(thin) (@guaranteed Klass) -> ()
1044+
end_borrow %phi4 : $Wrapper1
1045+
destroy_addr %0 : $*Wrapper1
1046+
%9999 = tuple()
1047+
return %9999 : $()
1048+
}
1049+

0 commit comments

Comments
 (0)