Skip to content

Commit 7ba396a

Browse files
Merge pull request swiftlang#64005 from nate-chandler/cse/partial-apply-stack-discipline
[CSE] Stack nest at OSSA lowering after inlining.
2 parents 02ad286 + 1a2b781 commit 7ba396a

File tree

2 files changed

+70
-3
lines changed

2 files changed

+70
-3
lines changed

lib/SILOptimizer/Transforms/CSE.cpp

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include "swift/SILOptimizer/Utils/OwnershipOptUtils.h"
3838
#include "swift/SILOptimizer/Utils/SILInliner.h"
3939
#include "swift/SILOptimizer/Utils/SILOptFunctionBuilder.h"
40+
#include "swift/SILOptimizer/Utils/StackNesting.h"
4041
#include "llvm/ADT/Hashing.h"
4142
#include "llvm/ADT/STLExtras.h"
4243
#include "llvm/ADT/ScopedHashTable.h"
@@ -665,7 +666,7 @@ class CSE {
665666

666667
bool processFunction(SILFunction &F, DominanceInfo *DT);
667668

668-
bool processLazyPropertyGetters();
669+
bool processLazyPropertyGetters(SILFunction &F);
669670

670671
bool canHandle(SILInstruction *Inst);
671672

@@ -779,8 +780,9 @@ bool CSE::processFunction(SILFunction &Fm, DominanceInfo *DT) {
779780

780781
/// Replace lazy property getters (which are dominated by the same getter)
781782
/// by a direct load of the value.
782-
bool CSE::processLazyPropertyGetters() {
783+
bool CSE::processLazyPropertyGetters(SILFunction &F) {
783784
bool changed = false;
785+
bool invalidatedStackNesting = false;
784786
for (ApplyInst *ai : lazyPropertyGetters) {
785787
SILFunction *getter = ai->getReferencedFunctionOrNull();
786788
assert(getter && getter->isLazyPropertyGetter());
@@ -807,9 +809,19 @@ bool CSE::processLazyPropertyGetters() {
807809
builder.createUncheckedEnumData(sei->getLoc(), enumVal, someDecl, ty);
808810
builder.createBranch(sei->getLoc(), someDest, { ued });
809811
sei->eraseFromParent();
812+
// When inlining an OSSA function into a non-OSSA function, ownership of
813+
// nonescaping closures is lowered. At that point, they are recognized as
814+
// stack users. Since they weren't recognized as such before, they may not
815+
// satisfy stack discipline. Fix that up now.
816+
if (getter->hasOwnership() && !ai->getFunction()->hasOwnership()) {
817+
invalidatedStackNesting = true;
818+
}
810819
changed = true;
811820
++NumCSE;
812821
}
822+
if (invalidatedStackNesting) {
823+
StackNesting::fixNesting(&F);
824+
}
813825
return changed;
814826
}
815827

@@ -1475,7 +1487,7 @@ class SILCSE : public SILFunctionTransform {
14751487

14761488
// Handle calls to lazy property getters, which are collected in
14771489
// processFunction().
1478-
if (C.processLazyPropertyGetters()) {
1490+
if (C.processLazyPropertyGetters(*Fn)) {
14791491
// Cleanup the dead blocks from the inlined lazy property getters.
14801492
removeUnreachableBlocks(*Fn);
14811493
invalidateAnalysis(SILAnalysis::InvalidationKind::FunctionBody);

test/SILOptimizer/cse.sil

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1356,3 +1356,58 @@ bb0:
13561356
%22 = tuple ()
13571357
return %22 : $()
13581358
}
1359+
1360+
sil @paable : $@convention(thin) (Builtin.Int64) -> ()
1361+
1362+
final class FC {
1363+
@_hasStorage @_hasInitialValue final var storage: Optional<Builtin.Int64>
1364+
}
1365+
1366+
sil @consume_int64 : $@convention(thin) (Builtin.Int64) -> ()
1367+
1368+
sil [lazy_getter] [ossa] @partial_apply_on_stack_nesting_violator : $@convention(method) (@guaranteed FC) -> Builtin.Int64 {
1369+
entry(%instance : @guaranteed $FC):
1370+
%storage_addr = ref_element_addr %instance : $FC, #FC.storage
1371+
%optional = load [trivial] %storage_addr : $*Optional<Builtin.Int64>
1372+
switch_enum %optional : $Optional<Builtin.Int64>, case #Optional.some!enumelt: some, case #Optional.none!enumelt: none
1373+
none:
1374+
%one = integer_literal $Builtin.Int64, 1
1375+
%optone = enum $Optional<Builtin.Int64>, #Optional.some!enumelt, %one : $Builtin.Int64
1376+
store %optone to [trivial] %storage_addr : $*Optional<Builtin.Int64>
1377+
br exit(%one : $Builtin.Int64)
1378+
1379+
some(%value : $Builtin.Int64):
1380+
%paable = function_ref @paable : $@convention(thin) (Builtin.Int64) -> ()
1381+
%first = partial_apply [callee_guaranteed] [on_stack] %paable(%value) : $@convention(thin) (Builtin.Int64) -> ()
1382+
%second = partial_apply [callee_guaranteed] [on_stack] %paable(%value) : $@convention(thin) (Builtin.Int64) -> ()
1383+
// Note that the destroy_values do not occur in an order which coincides
1384+
// with stack disciplined dealloc_stacks.
1385+
destroy_value %first : $@noescape @callee_guaranteed () -> ()
1386+
destroy_value %second : $@noescape @callee_guaranteed () -> ()
1387+
br exit(%value : $Builtin.Int64)
1388+
1389+
exit(%retval : $Builtin.Int64):
1390+
return %retval : $Builtin.Int64
1391+
}
1392+
1393+
// Verify that when inlining partial_apply_on_stack_nesting_violator, the stack
1394+
// nesting of the on_stack closures is fixed.
1395+
// CHECK-LABEL: sil @test_inline_stack_violating_ossa_func : {{.*}} {
1396+
// CHECK: [[PAABLE:%[^,]+]] = function_ref @paable
1397+
// CHECK: [[FIRST:%[^,]+]] = partial_apply [callee_guaranteed] [on_stack] [[PAABLE]]
1398+
// CHECK: [[SECOND:%[^,]+]] = partial_apply [callee_guaranteed] [on_stack] [[PAABLE]]
1399+
// CHECK: dealloc_stack [[SECOND]]
1400+
// CHECK: dealloc_stack [[FIRST]]
1401+
// CHECK-LABEL: } // end sil function 'test_inline_stack_violating_ossa_func'
1402+
sil @test_inline_stack_violating_ossa_func : $@convention(thin) (FC) -> () {
1403+
entry(%instance : $FC):
1404+
%callee = function_ref @partial_apply_on_stack_nesting_violator : $@convention(method) (@guaranteed FC) -> Builtin.Int64
1405+
%consume = function_ref @consume_int64 : $@convention(thin) (Builtin.Int64) -> ()
1406+
%first = apply %callee(%instance) : $@convention(method) (@guaranteed FC) -> Builtin.Int64
1407+
apply %consume(%first) : $@convention(thin) (Builtin.Int64) -> ()
1408+
%second = apply %callee(%instance) : $@convention(method) (@guaranteed FC) -> Builtin.Int64
1409+
apply %consume(%second) : $@convention(thin) (Builtin.Int64) -> ()
1410+
%retval = tuple ()
1411+
return %retval : $()
1412+
}
1413+

0 commit comments

Comments
 (0)