Skip to content

Commit 85ef0b2

Browse files
committed
[ownership] Once we strip ownership ignoring transparent functions from our module, strip ownership as we serialize.
1 parent aa4d406 commit 85ef0b2

File tree

4 files changed

+125
-29
lines changed

4 files changed

+125
-29
lines changed

lib/SILOptimizer/Transforms/OwnershipModelEliminator.cpp

Lines changed: 71 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,58 @@ bool OwnershipModelEliminatorVisitor::visitDestructureTupleInst(
284284
// Top Level Entry Point
285285
//===----------------------------------------------------------------------===//
286286

287+
static bool stripOwnership(SILFunction &F) {
288+
// If F is an external declaration, do not process it.
289+
if (F.isExternalDeclaration())
290+
return false;
291+
292+
// Set F to have unqualified ownership.
293+
F.setOwnershipEliminated();
294+
295+
bool MadeChange = false;
296+
SILBuilder B(F);
297+
OwnershipModelEliminatorVisitor Visitor(B);
298+
299+
for (auto &BB : F) {
300+
// Change all arguments to have ValueOwnershipKind::Any.
301+
for (auto *Arg : BB.getArguments()) {
302+
Arg->setOwnershipKind(ValueOwnershipKind::Any);
303+
}
304+
305+
for (auto II = BB.begin(), IE = BB.end(); II != IE;) {
306+
// Since we are going to be potentially removing instructions, we need
307+
// to make sure to increment our iterator before we perform any
308+
// visits.
309+
SILInstruction *I = &*II;
310+
++II;
311+
312+
MadeChange |= Visitor.visit(I);
313+
}
314+
}
315+
return MadeChange;
316+
}
317+
318+
static void prepareNonTransparentSILFunctionForOptimization(ModuleDecl *,
319+
SILFunction *F) {
320+
if (!F->hasOwnership() || F->isTransparent())
321+
return;
322+
323+
LLVM_DEBUG(llvm::dbgs() << "After deserialization, stripping ownership in:"
324+
<< F->getName() << "\n");
325+
326+
stripOwnership(*F);
327+
}
328+
329+
static void prepareSILFunctionForOptimization(ModuleDecl *, SILFunction *F) {
330+
if (!F->hasOwnership())
331+
return;
332+
333+
LLVM_DEBUG(llvm::dbgs() << "After deserialization, stripping ownership in:"
334+
<< F->getName() << "\n");
335+
336+
stripOwnership(*F);
337+
}
338+
287339
namespace {
288340

289341
struct OwnershipModelEliminator : SILModuleTransform {
@@ -297,48 +349,38 @@ struct OwnershipModelEliminator : SILModuleTransform {
297349
getModule()->dump(DumpBefore.c_str());
298350
}
299351

300-
for (auto &F : *getModule()) {
352+
auto &Mod = *getModule();
353+
for (auto &F : Mod) {
301354
// If F does not have ownership, skip it. We have no further work to do.
302355
if (!F.hasOwnership())
303356
continue;
304357

305-
// If we were asked to not strip ownership from transparent functions,
306-
// continue.
358+
// If we were asked to not strip ownership from transparent functions in
359+
// /our/ module, continue.
307360
if (SkipTransparent && F.isTransparent())
308361
continue;
309362

310-
// Set F to have unqualified ownership.
311-
F.setOwnershipEliminated();
312-
313-
bool MadeChange = false;
314-
SILBuilder B(F);
315-
OwnershipModelEliminatorVisitor Visitor(B);
316-
317-
for (auto &BB : F) {
318-
// Change all arguments to have ValueOwnershipKind::Any.
319-
for (auto *Arg : BB.getArguments()) {
320-
Arg->setOwnershipKind(ValueOwnershipKind::Any);
321-
}
322-
323-
for (auto II = BB.begin(), IE = BB.end(); II != IE;) {
324-
// Since we are going to be potentially removing instructions, we need
325-
// to make sure to increment our iterator before we perform any
326-
// visits.
327-
SILInstruction *I = &*II;
328-
++II;
329-
330-
MadeChange |= Visitor.visit(I);
331-
}
332-
}
333-
334-
if (MadeChange) {
363+
if (stripOwnership(F)) {
335364
auto InvalidKind =
336365
SILAnalysis::InvalidationKind::BranchesAndInstructions;
337366
invalidateAnalysis(&F, InvalidKind);
338367
}
339368
}
340-
}
341369

370+
// If we were asked to strip transparent, we are at the beginning of the
371+
// performance pipeline. In such a case, we register a handler so that all
372+
// future things we deserialize have ownership stripped.
373+
using NotificationHandlerTy =
374+
FunctionBodyDeserializationNotificationHandler;
375+
std::unique_ptr<DeserializationNotificationHandler> ptr;
376+
if (SkipTransparent) {
377+
ptr.reset(new NotificationHandlerTy(
378+
prepareNonTransparentSILFunctionForOptimization));
379+
} else {
380+
ptr.reset(new NotificationHandlerTy(prepareSILFunctionForOptimization));
381+
}
382+
Mod.registerDeserializationNotificationHandler(std::move(ptr));
383+
}
342384
};
343385

344386
} // end anonymous namespace
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
2+
sil_stage canonical
3+
4+
sil public [serialized] [ossa] @bar : $@convention(thin) () -> () {
5+
bb0:
6+
%9999 = tuple()
7+
return %9999 : $()
8+
}
9+
10+
sil public [serialized] [transparent] [ossa] @transparent_bar : $@convention(thin) () -> () {
11+
bb0:
12+
%9999 = tuple()
13+
return %9999 : $()
14+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend -parse-sil -module-name OMEStripDeserializationInput %S/Inputs/ome_strip_deserialize_input.sil -emit-module -o %t/OMEStripDeserializationInput.swiftmodule
3+
// RUN: %target-sil-opt -enable-sil-ownership -non-transparent-func-ownership-model-eliminator -performance-linker -I %t %s | %FileCheck %s
4+
// RUN: %target-sil-opt -enable-sil-ownership -ownership-model-eliminator -performance-linker -I %t %s | %FileCheck --check-prefix=CHECK-STRIP-ALL %s
5+
6+
sil_stage canonical
7+
8+
import OMEStripDeserializationInput
9+
10+
// Make sure that we properly set the deserialization call back for stripping
11+
// ownership SIL.
12+
13+
// CHECK-LABEL: sil public_external [serialized] @bar : $@convention(thin) () -> ()
14+
// CHECK: } // end sil function 'bar'
15+
16+
// CHECK-STRIP-ALL-LABEL: sil public_external [serialized] @bar : $@convention(thin) () -> ()
17+
// CHECK-STRIP-ALL: } // end sil function 'bar'
18+
sil [ossa] @bar : $@convention(thin) () -> ()
19+
20+
// CHECK-LABEL: sil public_external [transparent] [serialized] [ossa] @transparent_bar : $@convention(thin) () -> ()
21+
// CHECK: } // end sil function 'transparent_bar'
22+
23+
// CHECK-STRIP-ALL-LABEL: sil public_external [transparent] [serialized] @transparent_bar : $@convention(thin) () -> ()
24+
// CHECK-STRIP-ALL: } // end sil function 'transparent_bar'
25+
26+
sil [transparent] [ossa] @transparent_bar : $@convention(thin) () -> ()
27+
28+
// CHECK-LABEL: sil @foo : $@convention(thin) () -> () {
29+
// CHECK: } // end sil function 'foo'
30+
sil [ossa] @foo : $@convention(thin) () -> () {
31+
bb0:
32+
%0 = function_ref @bar : $@convention(thin) () -> ()
33+
apply %0() : $@convention(thin) () -> ()
34+
35+
%1 = function_ref @transparent_bar : $@convention(thin) () -> ()
36+
apply %1() : $@convention(thin) () -> ()
37+
38+
%9999 = tuple()
39+
return %9999 : $()
40+
}

0 commit comments

Comments
 (0)