Skip to content

Commit 4481ba8

Browse files
committed
[SSADestroyHoisting] Barriers use callee analysis.
Pass a BasicCalleeAnalysis instance to isDeinitBarrier. This will enable SSADestroyHoisting to hoist destroy_addrs over applies of functions that are not themselves deinit barriers.
1 parent 4cf0580 commit 4481ba8

File tree

2 files changed

+46
-14
lines changed

2 files changed

+46
-14
lines changed

lib/SILOptimizer/Transforms/SSADestroyHoisting.cpp

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,8 @@ class DestroyReachability;
194194
/// Step #2: Perform backward dataflow from KnownStorageUses.originalDestroys to
195195
/// KnownStorageUses.storageUsers to find deinitialization barriers.
196196
class DeinitBarriers final {
197+
BasicCalleeAnalysis *calleeAnalysis;
198+
197199
public:
198200
// Instructions beyond which a destroy_addr cannot be hoisted, reachable from
199201
// a destroy_addr. Deinit barriers or storage uses.
@@ -219,8 +221,10 @@ class DeinitBarriers final {
219221

220222
explicit DeinitBarriers(bool ignoreDeinitBarriers,
221223
const KnownStorageUses &knownUses,
222-
SILFunction *function)
223-
: ignoreDeinitBarriers(ignoreDeinitBarriers), knownUses(knownUses) {
224+
SILFunction *function,
225+
BasicCalleeAnalysis *calleeAnalysis)
226+
: calleeAnalysis(calleeAnalysis),
227+
ignoreDeinitBarriers(ignoreDeinitBarriers), knownUses(knownUses) {
224228
auto rootValue = knownUses.getStorage().getRoot();
225229
assert(rootValue && "HoistDestroys requires a single storage root");
226230
// null for function args
@@ -341,7 +345,7 @@ DeinitBarriers::classifyInstruction(SILInstruction *inst) const {
341345
if (knownUses.storageUsers.contains(inst)) {
342346
return Classification::Barrier;
343347
}
344-
if (!ignoreDeinitBarriers && isDeinitBarrier(inst, nullptr)) {
348+
if (!ignoreDeinitBarriers && isDeinitBarrier(inst, calleeAnalysis)) {
345349
return Classification::Barrier;
346350
}
347351
if (auto *eai = dyn_cast<EndAccessInst>(inst)) {
@@ -403,6 +407,7 @@ class HoistDestroys {
403407
bool ignoreDeinitBarriers;
404408
SmallPtrSetImpl<SILInstruction *> &remainingDestroyAddrs;
405409
InstructionDeleter &deleter;
410+
BasicCalleeAnalysis *calleeAnalysis;
406411

407412
// Book-keeping for the rewriting stage.
408413
SmallPtrSet<SILInstruction *, 4> reusedDestroys;
@@ -412,12 +417,13 @@ class HoistDestroys {
412417
public:
413418
HoistDestroys(SILValue storageRoot, bool ignoreDeinitBarriers,
414419
SmallPtrSetImpl<SILInstruction *> &remainingDestroyAddrs,
415-
InstructionDeleter &deleter)
420+
InstructionDeleter &deleter,
421+
BasicCalleeAnalysis *calleeAnalysis)
416422
: storageRoot(storageRoot), function(storageRoot->getFunction()),
417423
module(function->getModule()), typeExpansionContext(*function),
418424
ignoreDeinitBarriers(ignoreDeinitBarriers),
419425
remainingDestroyAddrs(remainingDestroyAddrs), deleter(deleter),
420-
destroyMergeBlocks(getFunction()) {}
426+
calleeAnalysis(calleeAnalysis), destroyMergeBlocks(getFunction()) {}
421427

422428
bool perform();
423429

@@ -465,7 +471,8 @@ bool HoistDestroys::perform() {
465471
if (!knownUses.findUses())
466472
return false;
467473

468-
DeinitBarriers deinitBarriers(ignoreDeinitBarriers, knownUses, getFunction());
474+
DeinitBarriers deinitBarriers(ignoreDeinitBarriers, knownUses, getFunction(),
475+
calleeAnalysis);
469476
deinitBarriers.compute();
470477

471478
// No SIL changes happen before rewriting.
@@ -829,7 +836,8 @@ void HoistDestroys::mergeDestroys(SILBasicBlock *mergeBlock) {
829836

830837
bool hoistDestroys(SILValue root, bool ignoreDeinitBarriers,
831838
SmallPtrSetImpl<SILInstruction *> &remainingDestroyAddrs,
832-
InstructionDeleter &deleter) {
839+
InstructionDeleter &deleter,
840+
BasicCalleeAnalysis *calleeAnalysis) {
833841
LLVM_DEBUG(llvm::dbgs() << "Performing destroy hoisting on " << root);
834842

835843
SILFunction *function = root->getFunction();
@@ -846,7 +854,7 @@ bool hoistDestroys(SILValue root, bool ignoreDeinitBarriers,
846854
ignoreDeinitBarriers = ignoreDeinitBarriers || !enableLexicalLifetimes;
847855

848856
return HoistDestroys(root, ignoreDeinitBarriers, remainingDestroyAddrs,
849-
deleter)
857+
deleter, calleeAnalysis)
850858
.perform();
851859
}
852860

@@ -955,17 +963,20 @@ void SSADestroyHoisting::run() {
955963
++splitDestroys;
956964
}
957965

966+
auto *calleeAnalysis = getAnalysis<BasicCalleeAnalysis>();
967+
958968
// We assume that the function is in reverse post order so visiting the
959969
// blocks and pushing begin_access as we see them and then popping them off
960970
// the end will result in hoisting inner begin_access' destroy_addrs first.
961971
for (auto *bai : llvm::reverse(bais)) {
962972
changed |= hoistDestroys(bai, /*ignoreDeinitBarriers=*/true,
963-
remainingDestroyAddrs, deleter);
973+
remainingDestroyAddrs, deleter, calleeAnalysis);
964974
}
965975
// Alloc stacks always enclose their accesses.
966976
for (auto *asi : asis) {
967-
changed |= hoistDestroys(asi, /*ignoreDeinitBarriers=*/!asi->isLexical(),
968-
remainingDestroyAddrs, deleter);
977+
changed |= hoistDestroys(asi,
978+
/*ignoreDeinitBarriers=*/!asi->isLexical(),
979+
remainingDestroyAddrs, deleter, calleeAnalysis);
969980
}
970981
// Arguments enclose everything.
971982
for (auto *uncastArg : getFunction()->getArguments()) {
@@ -983,7 +994,7 @@ void SSADestroyHoisting::run() {
983994
auto lifetime = arg->getLifetime();
984995
bool ignoreDeinitBarriers = ignoredByConvention || lifetime.isEagerMove();
985996
changed |= hoistDestroys(arg, ignoreDeinitBarriers, remainingDestroyAddrs,
986-
deleter);
997+
deleter, calleeAnalysis);
987998
}
988999
}
9891000

test/SILOptimizer/hoist_destroy_addr.sil

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
// RUN: %target-sil-opt -opt-mode=none -enable-sil-verify-all %s -ssa-destroy-hoisting | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECKDEB --check-prefix=CHECK-DEB
2-
// RUN: %target-sil-opt -opt-mode=speed -enable-sil-verify-all %s -ssa-destroy-hoisting | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECKOPT --check-prefix=CHECK-OPT
1+
// RUN: %target-sil-opt -opt-mode=none -enable-sil-verify-all %s -compute-side-effects -ssa-destroy-hoisting | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECKDEB --check-prefix=CHECK-DEB
2+
// RUN: %target-sil-opt -opt-mode=speed -enable-sil-verify-all %s -compute-side-effects -ssa-destroy-hoisting | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECKOPT --check-prefix=CHECK-OPT
33
//
44
// TODO: migrate the remaining tests from destroy_hoisting.sil.
55

6+
// REQUIRES: swift_in_compiler
7+
68
sil_stage canonical
79

810
import Builtin
@@ -75,6 +77,12 @@ struct STXXITXXII {
7577
sil @unknown : $@convention(thin) () -> ()
7678
sil @use_S : $@convention(thin) (@in_guaranteed S) -> ()
7779

80+
// This function is not a synchronization point.
81+
sil @empty : $@convention(thin) () -> () {
82+
%retval = tuple ()
83+
return %retval : $()
84+
}
85+
7886
sil @f_out : $@convention(thin) <T> () -> @out T
7987
sil @f_bool : $@convention(thin) () -> Builtin.Int1
8088
sil [ossa] @take_trivial_struct : $@convention(thin) (TrivialStruct) -> ()
@@ -1064,3 +1072,16 @@ entry(%instance : @owned $AnyObject):
10641072
dealloc_stack %addr : $*AnyObject
10651073
return %cast : $X
10661074
}
1075+
1076+
// CHECK-LABEL: sil [ossa] @hoist_over_apply_of_non_barrier_fn : {{.*}} {
1077+
// CHECK: destroy_addr
1078+
// CHECK: apply
1079+
// CHECK-LABEL: } // end sil function 'hoist_over_apply_of_non_barrier_fn'
1080+
sil [ossa] @hoist_over_apply_of_non_barrier_fn : $@convention(thin) (@in X) -> () {
1081+
entry(%addr : $*X):
1082+
%empty = function_ref @empty : $@convention(thin) () -> ()
1083+
apply %empty() : $@convention(thin) () -> ()
1084+
destroy_addr %addr : $*X
1085+
%retval = tuple ()
1086+
return %retval : $()
1087+
}

0 commit comments

Comments
 (0)