Skip to content

Commit c10e5ac

Browse files
aschwaighofertkremenek
authored andcommitted
UnsafeGuaranteedPeephole: Handle exception edges correctly (#3471)
* UnsafeGuaranteedPeephole: Handle exception edges correctly Exceptions can cause an exit before hitting the unsafeGuaranteedEnd instruction. Make sure that we check post dominance to find such cases. rdar://26890751 (cherry picked from commit 7cc447c) * Adopt test case for swift-3.0-preview-3-branch
1 parent f6a4d42 commit c10e5ac

File tree

2 files changed

+47
-2
lines changed

2 files changed

+47
-2
lines changed

lib/SILOptimizer/Transforms/UnsafeGuaranteedPeephole.cpp

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include "swift/SIL/SILInstruction.h"
3838
#include "swift/SIL/SILModule.h"
3939
#include "swift/SILOptimizer/Analysis/ARCAnalysis.h"
40+
#include "swift/SILOptimizer/Analysis/DominanceAnalysis.h"
4041
#include "swift/SILOptimizer/Analysis/RCIdentityAnalysis.h"
4142
#include "swift/SILOptimizer/PassManager/Transforms.h"
4243
#include "swift/SILOptimizer/Utils/Local.h"
@@ -46,9 +47,14 @@ using namespace swift;
4647
/// Remove retain/release pairs around builtin "unsafeGuaranteed" instruction
4748
/// sequences.
4849
static bool removeGuaranteedRetainReleasePairs(SILFunction &F,
49-
RCIdentityFunctionInfo &RCIA) {
50+
RCIdentityFunctionInfo &RCIA,
51+
PostDominanceAnalysis *PDA) {
5052
DEBUG(llvm::dbgs() << "Running on function " << F.getName() << "\n");
5153
bool Changed = false;
54+
55+
// Lazily compute post-dominance info only when we really need it.
56+
PostDominanceInfo *PDI = nullptr;
57+
5258
for (auto &BB : F) {
5359
auto It = BB.begin(), End = BB.end();
5460
llvm::DenseMap<SILValue, SILInstruction *> LastRetain;
@@ -119,6 +125,15 @@ static bool removeGuaranteedRetainReleasePairs(SILFunction &F,
119125
continue;
120126
}
121127

128+
if (!PDI)
129+
PDI = PDA->get(&F);
130+
131+
// It needs to post-dominated the end instruction, since we need to remove
132+
// the release along all paths to exit.
133+
if (!PDI->properlyDominates(UnsafeGuaranteedEndI, UnsafeGuaranteedI))
134+
continue;
135+
136+
122137
// Find the release to match with the unsafeGuaranteedValue.
123138
auto &UnsafeGuaranteedEndBB = *UnsafeGuaranteedEndI->getParent();
124139
auto LastRelease = findReleaseToMatchUnsafeGuaranteedValue(
@@ -165,7 +180,8 @@ class UnsafeGuaranteedPeephole : public swift::SILFunctionTransform {
165180

166181
void run() override {
167182
auto &RCIA = *getAnalysis<RCIdentityAnalysis>()->get(getFunction());
168-
if (removeGuaranteedRetainReleasePairs(*getFunction(), RCIA))
183+
auto *PostDominance = getAnalysis<PostDominanceAnalysis>();
184+
if (removeGuaranteedRetainReleasePairs(*getFunction(), RCIA, PostDominance))
169185
invalidateAnalysis(SILAnalysis::InvalidationKind::Instructions);
170186
}
171187

test/SILOptimizer/unsafe_guaranteed_peephole.sil

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ public class Foo : Base {
1414

1515
sil @beep : $@convention(thin) () -> ()
1616
sil @beep2 : $@convention(thin) (@owned Foo) -> ()
17+
sil @beep_or_throw : $@convention(thin) () -> @error ErrorProtocol
1718

1819
// CHECK-LABEL: sil @testUnsafeGuaranteed_simple
1920
// CHECK: bb0([[P:%.*]] : $Foo):
@@ -513,3 +514,31 @@ bb0(%0 : $AnyObject, %1: $Builtin.Int32):
513514
%17 = tuple ()
514515
return %17 : $()
515516
}
517+
518+
// CHECK-LABEL: sil @testUnsafeGuaranteed_throw
519+
// CHECK:bb0
520+
// CHECK: unsafeGuaranteed
521+
// CHECK:bb1
522+
// CHECK: unsafeGuaranteedEnd
523+
// CHECK: return
524+
// CHECK:bb2
525+
// CHECK: throw
526+
sil @testUnsafeGuaranteed_throw : $@convention(method) (@guaranteed Foo) -> @error ErrorProtocol {
527+
bb0(%0 : $Foo):
528+
strong_retain %0 : $Foo
529+
%4 = builtin "unsafeGuaranteed"<Foo>(%0 : $Foo) : $(Foo, Builtin.Int8)
530+
%5 = tuple_extract %4 : $(Foo, Builtin.Int8), 0
531+
%6 = tuple_extract %4 : $(Foo, Builtin.Int8), 1
532+
%7 = function_ref @beep_or_throw : $@convention(thin) () -> @error ErrorProtocol
533+
%8 = try_apply %7() : $@convention(thin) () -> @error ErrorProtocol, normal bb1, error bb2
534+
535+
bb1(%15: $()):
536+
strong_release %5 : $Foo
537+
%16 = builtin "unsafeGuaranteedEnd"(%6 : $Builtin.Int8) : $()
538+
%17 = tuple ()
539+
return %17 : $()
540+
541+
bb2(%9: $ErrorProtocol):
542+
strong_release %5 : $Foo
543+
throw %9: $ErrorProtocol
544+
}

0 commit comments

Comments
 (0)