SlideShare uses cookies to improve functionality and performance, and to provide you with relevant advertising. If you continue browsing the site, you agree to the use of cookies on this website. See our User Agreement and Privacy Policy.
SlideShare uses cookies to improve functionality and performance, and to provide you with relevant advertising. If you continue browsing the site, you agree to the use of cookies on this website. See our Privacy Policy and User Agreement for details.
Successfully reported this slideshow.
Activate your 14 day free trial to unlock unlimited reading.
1.
SIL Optimizations
AllocBoxToStack
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
2.
Hi, I'm Yusuke
@kitasuke
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
3.
Why SIL?
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
4.
Why SIL?
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
5.
Why SIL?
→ Better idea of Swift type system !
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
6.
Why SIL?
→ Better idea of Swift type system !
→ Optimizations magic "✨
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
7.
Why SIL?
→ Better idea of Swift type system !
→ Optimizations magic "✨
→ Just for fun $
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
8.
SIL
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
9.
Swift
Intermediate
LanguageSIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
10.
SIL is a language specific
Intermediate
Representation
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
11.
Swift
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
12.
Swift Compiler
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
13.
Swift Compiler
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
14.
Swift Compiler
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
15.
SIL
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
16.
raw SIL
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
17.
canonical SIL
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
18.
Objective-C
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
19.
Clang
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
20.
Clang
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
21.
SIL
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
22.
Optimizations
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
24.
AllocBoxToStack
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
25.
Stack Promotion of
Box Objects
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
26.
Stack vs Heap
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
27.
Stack
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
28.
Stack
→ Very fast
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
29.
Stack
→ Very fast
→ No explicit memory management
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
30.
Stack
→ Very fast
→ No explicit memory management
→ Size limits
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
31.
Heap
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
32.
Heap
→ Slow
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
33.
Heap
→ Slow
→ Explicit memory management
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
34.
Heap
→ Slow
→ Explicit memory management
→ No size limits
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
35.
Stack vs Heap
Stack Heap
Value types Reference types
Pointers to reference
type
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
36.
How AllocBoxToStack
works?
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
37.
alloc_box ➡ alloc_stack
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
38.
stack.swift
func number() -> Int {
var x: Int
x = 1
return x
}
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
39.
raw SIL
$swiftc -emit-silgen stack.swift > stack.sil
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
40.
stack.sil
%0 = alloc_box ${ var Int }, var, name "x"
%1 = mark_uninitialized [var] %0 : ${ var Int }
%2 = project_box %1 : ${ var Int }, 0
...
%10 = begin_access [read] [unknown] %2 : $*Int
%11 = load [trivial] %10 : $*Int
end_access %10 : $*Int
destroy_value %1 : ${ var Int }
return %11 : $Int
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
41.
stack.sil
%0 = alloc_box ${ var Int }, var, name "x"
%1 = mark_uninitialized [var] %0 : ${ var Int }
%2 = project_box %1 : ${ var Int }, 0
...
%10 = begin_access [read] [unknown] %2 : $*Int
%11 = load [trivial] %10 : $*Int
end_access %10 : $*Int
destroy_value %1 : ${ var Int }
return %11 : $Int
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
42.
canonical SIL
$swiftc -emit-sil stack.swift > stack.sil
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
43.
stack.sil
%0 = alloc_stack $Int, var, name "x"
%1 = integer_literal $Builtin.Int64, 1
%2 = struct $Int (%1 : $Builtin.Int64)
...
return %2 : $Int
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
44.
stack.sil
%0 = alloc_stack $Int, var, name "x"
%1 = integer_literal $Builtin.Int64, 1
%2 = struct $Int (%1 : $Builtin.Int64)
...
return %2 : $Int
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
45.
alloc_box vs alloc_stack
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
46.
alloc_box
alloc_box allocates a reference counted box on
heap.
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
47.
alloc_stack
alloc_stack allocates a value on stack. All
allocations must be deallocated prior to returning
from a function.
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
48.
Stack Promotion of
Box Objects
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
49.
alloc_box ➡ alloc_stack
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
50.
alloc_box ➡ alloc_box
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
51.
box.swift
func closure(_ completion: @escaping () -> Void) {
completion()
}
func number() -> Int {
var i: Int
i = 0
closure { i = 10 }
return i
}
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
52.
box.swift
func closure(_ completion: @escaping () -> Void) {
completion()
}
func number() -> Int {
var i: Int
i = 0
closure { i = 10 }
return i
}
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
53.
box.swift
func closure(_ completion: @escaping () -> Void) {
completion()
}
func number() -> Int {
var i: Int
i = 0
closure { i = 10 }
return i
}
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
54.
raw SIL
$swiftc -emit-silgen box.swift > box.sil
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
55.
box.sil
%0 = alloc_box ${ var Int }, var, name "i"
%1 = mark_uninitialized [var] %0 : ${ var Int }
%2 = project_box %1 : ${ var Int }, 0
...
%16 = begin_access [read] [unknown] %2 : $*Int
%17 = load [trivial] %16 : $*Int
end_access %16 : $*Int
destroy_value %1 : ${ var Int }
return %17 : $Int
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
56.
box.sil
%0 = alloc_box ${ var Int }, var, name "i"
%1 = mark_uninitialized [var] %0 : ${ var Int }
%2 = project_box %1 : ${ var Int }, 0
...
%16 = begin_access [read] [unknown] %2 : $*Int
%17 = load [trivial] %16 : $*Int
end_access %16 : $*Int
destroy_value %1 : ${ var Int }
return %17 : $Int
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
57.
canonical SIL
$swiftc -emit-sil box.swift > box.sil
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
58.
box.sil
%0 = alloc_box ${ var Int }, var, name "i"
%1 = project_box %0 : ${ var Int }, 0
%2 = integer_literal $Builtin.Int64, 0
%3 = struct $Int (%2 : $Builtin.Int64)
...
%12 = begin_access [read] [dynamic] %1 : $*Int
%13 = load %12 : $*Int
end_access %12 : $*Int
strong_release %0 : ${ var Int }
return %13 : $Int
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
59.
box.sil
%0 = alloc_box ${ var Int }, var, name "i"
%1 = project_box %0 : ${ var Int }, 0
%2 = integer_literal $Builtin.Int64, 0
%3 = struct $Int (%2 : $Builtin.Int64)
...
%12 = begin_access [read] [dynamic] %1 : $*Int
%13 = load %12 : $*Int
end_access %12 : $*Int
strong_release %0 : ${ var Int }
return %13 : $Int
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
60.
How can promote
alloc_box?
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
61.
class AllocBoxToStack : public SILFunctionTransform {
void run() override {
...
AllocBoxToStackState pass(this);
for (auto &BB : *getFunction()) {
for (auto &I : BB)
if (auto *ABI = dyn_cast<AllocBoxInst>(&I))
if (canPromoteAllocBox(ABI, pass.PromotedOperands))
pass.Promotable.push_back(ABI);
}
if (!pass.Promotable.empty()) {
auto Count = rewritePromotedBoxes(pass);
...
}
...
}
};
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
62.
class AllocBoxToStack : public SILFunctionTransform {
void run() override {
...
AllocBoxToStackState pass(this);
for (auto &BB : *getFunction()) {
for (auto &I : BB)
if (auto *ABI = dyn_cast<AllocBoxInst>(&I))
if (canPromoteAllocBox(ABI, pass.PromotedOperands))
pass.Promotable.push_back(ABI);
}
if (!pass.Promotable.empty()) {
auto Count = rewritePromotedBoxes(pass);
...
}
...
}
};
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
63.
class AllocBoxToStack : public SILFunctionTransform {
void run() override {
...
AllocBoxToStackState pass(this);
for (auto &BB : *getFunction()) {
for (auto &I : BB)
if (auto *ABI = dyn_cast<AllocBoxInst>(&I))
if (canPromoteAllocBox(ABI, pass.PromotedOperands))
pass.Promotable.push_back(ABI);
}
if (!pass.Promotable.empty()) {
auto Count = rewritePromotedBoxes(pass);
...
}
...
}
};
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
64.
class AllocBoxToStack : public SILFunctionTransform {
void run() override {
...
AllocBoxToStackState pass(this);
for (auto &BB : *getFunction()) {
for (auto &I : BB)
if (auto *ABI = dyn_cast<AllocBoxInst>(&I))
if (canPromoteAllocBox(ABI, pass.PromotedOperands))
pass.Promotable.push_back(ABI);
}
if (!pass.Promotable.empty()) {
auto Count = rewritePromotedBoxes(pass);
...
}
...
}
};
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
65.
static SILInstruction * findUnexpectedBoxUse(SILValue Box, bool examinePartialApply,
bool inAppliedFunction, llvm::SmallVectorImpl<Operand *> &PromotedOperands) {
llvm::SmallVector<Operand *, 4> LocalPromotedOperands;
llvm::SmallVector<Operand *, 32> Worklist(Box->use_begin(), Box->use_end());
while (!Worklist.empty()) {
auto *Op = Worklist.pop_back_val();
auto *User = Op->getUser();
if (isa<StrongRetainInst>(User) || isa<StrongReleaseInst>(User) ||
isa<ProjectBoxInst>(User) || isa<DestroyValueInst>(User) ||
(!inAppliedFunction && isa<DeallocBoxInst>(User)))
continue;
if (isa<MarkUninitializedInst>(User) || isa<CopyValueInst>(User)) {
copy(cast<SingleValueInstruction>(User)->getUses(), std::back_inserter(Worklist));
continue;
}
if (auto *PAI = dyn_cast<PartialApplyInst>(User))
if (examinePartialApply && checkPartialApplyBody(Op) &&
!partialApplyEscapes(PAI, /* examineApply = */ true)) {
LocalPromotedOperands.push_back(Op);
continue;
}
return User;
}
...
}
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
66.
static SILInstruction * findUnexpectedBoxUse(SILValue Box, bool examinePartialApply,
bool inAppliedFunction, llvm::SmallVectorImpl<Operand *> &PromotedOperands) {
llvm::SmallVector<Operand *, 4> LocalPromotedOperands;
llvm::SmallVector<Operand *, 32> Worklist(Box->use_begin(), Box->use_end());
while (!Worklist.empty()) {
auto *Op = Worklist.pop_back_val();
auto *User = Op->getUser();
if (isa<StrongRetainInst>(User) || isa<StrongReleaseInst>(User) ||
isa<ProjectBoxInst>(User) || isa<DestroyValueInst>(User) ||
(!inAppliedFunction && isa<DeallocBoxInst>(User)))
continue;
if (isa<MarkUninitializedInst>(User) || isa<CopyValueInst>(User)) {
copy(cast<SingleValueInstruction>(User)->getUses(), std::back_inserter(Worklist));
continue;
}
if (auto *PAI = dyn_cast<PartialApplyInst>(User))
if (examinePartialApply && checkPartialApplyBody(Op) &&
!partialApplyEscapes(PAI, /* examineApply = */ true)) {
LocalPromotedOperands.push_back(Op);
continue;
}
return User;
}
...
}
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
67.
static SILInstruction * findUnexpectedBoxUse(SILValue Box, bool examinePartialApply,
bool inAppliedFunction, llvm::SmallVectorImpl<Operand *> &PromotedOperands) {
llvm::SmallVector<Operand *, 4> LocalPromotedOperands;
llvm::SmallVector<Operand *, 32> Worklist(Box->use_begin(), Box->use_end());
while (!Worklist.empty()) {
auto *Op = Worklist.pop_back_val();
auto *User = Op->getUser();
if (isa<StrongRetainInst>(User) || isa<StrongReleaseInst>(User) ||
isa<ProjectBoxInst>(User) || isa<DestroyValueInst>(User) ||
(!inAppliedFunction && isa<DeallocBoxInst>(User)))
continue;
if (isa<MarkUninitializedInst>(User) || isa<CopyValueInst>(User)) {
copy(cast<SingleValueInstruction>(User)->getUses(), std::back_inserter(Worklist));
continue;
}
if (auto *PAI = dyn_cast<PartialApplyInst>(User))
if (examinePartialApply && checkPartialApplyBody(Op) &&
!partialApplyEscapes(PAI, /* examineApply = */ true)) {
LocalPromotedOperands.push_back(Op);
continue;
}
return User;
}
...
}
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
68.
static SILInstruction * findUnexpectedBoxUse(SILValue Box, bool examinePartialApply,
bool inAppliedFunction, llvm::SmallVectorImpl<Operand *> &PromotedOperands) {
llvm::SmallVector<Operand *, 4> LocalPromotedOperands;
llvm::SmallVector<Operand *, 32> Worklist(Box->use_begin(), Box->use_end());
while (!Worklist.empty()) {
auto *Op = Worklist.pop_back_val();
auto *User = Op->getUser();
if (isa<StrongRetainInst>(User) || isa<StrongReleaseInst>(User) ||
isa<ProjectBoxInst>(User) || isa<DestroyValueInst>(User) ||
(!inAppliedFunction && isa<DeallocBoxInst>(User)))
continue;
if (isa<MarkUninitializedInst>(User) || isa<CopyValueInst>(User)) {
copy(cast<SingleValueInstruction>(User)->getUses(), std::back_inserter(Worklist));
continue;
}
if (auto *PAI = dyn_cast<PartialApplyInst>(User))
if (examinePartialApply && checkPartialApplyBody(Op) &&
!partialApplyEscapes(PAI, /* examineApply = */ true)) {
LocalPromotedOperands.push_back(Op);
continue;
}
return User;
}
...
}
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
69.
static SILInstruction * findUnexpectedBoxUse(SILValue Box, bool examinePartialApply,
bool inAppliedFunction, llvm::SmallVectorImpl<Operand *> &PromotedOperands) {
llvm::SmallVector<Operand *, 4> LocalPromotedOperands;
llvm::SmallVector<Operand *, 32> Worklist(Box->use_begin(), Box->use_end());
while (!Worklist.empty()) {
auto *Op = Worklist.pop_back_val();
auto *User = Op->getUser();
if (isa<StrongRetainInst>(User) || isa<StrongReleaseInst>(User) ||
isa<ProjectBoxInst>(User) || isa<DestroyValueInst>(User) ||
(!inAppliedFunction && isa<DeallocBoxInst>(User)))
continue;
if (isa<MarkUninitializedInst>(User) || isa<CopyValueInst>(User)) {
copy(cast<SingleValueInstruction>(User)->getUses(), std::back_inserter(Worklist));
continue;
}
if (auto *PAI = dyn_cast<PartialApplyInst>(User))
if (examinePartialApply && checkPartialApplyBody(Op) &&
!partialApplyEscapes(PAI, /* examineApply = */ true)) {
LocalPromotedOperands.push_back(Op);
continue;
}
return User;
}
...
}
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
70.
Recap
→ Promotes @noescape values to stack
→ @escaping values with a reference count
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
71.
Optimization Flags
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
72.
optimized.swift
func closure(_ completion: @escaping () -> Void) {
completion()
}
func number() -> Int {
var i: Int
i = 0
closure { i = 10 }
return i
}
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
73.
canonical SIL with -O
$swiftc -emit-sil -O optimized.swift > optimized.sil
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
75.
No alloc_box or
alloc_stack
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
76.
Mem2Reg
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
77.
Register Promotion of
Stack Allocations
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
78.
How can promote stack
allocation?
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
79.
class SILMem2Reg : public SILFunctionTransform {
void run() override {
SILFunction *F = getFunction();
DominanceAnalysis* DA = PM->getAnalysis<DominanceAnalysis>();
bool Changed = MemoryToRegisters(*F, DA->get(F)).run();
...
}
};
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
80.
class SILMem2Reg : public SILFunctionTransform {
void run() override {
SILFunction *F = getFunction();
DominanceAnalysis* DA = PM->getAnalysis<DominanceAnalysis>();
bool Changed = MemoryToRegisters(*F, DA->get(F)).run();
...
}
};
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
81.
class SILMem2Reg : public SILFunctionTransform {
void run() override {
SILFunction *F = getFunction();
DominanceAnalysis* DA = PM->getAnalysis<DominanceAnalysis>();
bool Changed = MemoryToRegisters(*F, DA->get(F)).run();
...
}
};
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
82.
class SILMem2Reg : public SILFunctionTransform {
void run() override {
SILFunction *F = getFunction();
DominanceAnalysis* DA = PM->getAnalysis<DominanceAnalysis>();
bool Changed = MemoryToRegisters(*F, DA->get(F)).run();
...
}
};
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
83.
bool MemoryToRegisters::promoteSingleAllocation(AllocStackInst *alloc, DomTreeLevelMap &DomTreeLevels){
NumAllocStackFound++;
bool inSingleBlock = false;
if (isCaptured(alloc, inSingleBlock)) {
NumAllocStackCaptured++;
return false;
}
if (isWriteOnlyAllocation(alloc)) {
eraseUsesOfInstruction(alloc);
return true;
}
if (inSingleBlock) {
removeSingleBlockAllocation(alloc);
if (!alloc->use_empty()) {
B.setInsertionPoint(std::next(alloc->getIterator()));
B.createDeallocStack(alloc->getLoc(), alloc);
}
return true;
}
StackAllocationPromoter(alloc, DT, DomTreeLevels, B).run();
eraseUsesOfInstruction(alloc);
return true;
}
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
84.
bool MemoryToRegisters::promoteSingleAllocation(AllocStackInst *alloc, DomTreeLevelMap &DomTreeLevels){
NumAllocStackFound++;
bool inSingleBlock = false;
if (isCaptured(alloc, inSingleBlock)) {
NumAllocStackCaptured++;
return false;
}
if (isWriteOnlyAllocation(alloc)) {
eraseUsesOfInstruction(alloc);
return true;
}
if (inSingleBlock) {
removeSingleBlockAllocation(alloc);
if (!alloc->use_empty()) {
B.setInsertionPoint(std::next(alloc->getIterator()));
B.createDeallocStack(alloc->getLoc(), alloc);
}
return true;
}
StackAllocationPromoter(alloc, DT, DomTreeLevels, B).run();
eraseUsesOfInstruction(alloc);
return true;
}
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
85.
bool MemoryToRegisters::promoteSingleAllocation(AllocStackInst *alloc, DomTreeLevelMap &DomTreeLevels){
NumAllocStackFound++;
bool inSingleBlock = false;
if (isCaptured(alloc, inSingleBlock)) {
NumAllocStackCaptured++;
return false;
}
if (isWriteOnlyAllocation(alloc)) {
eraseUsesOfInstruction(alloc);
return true;
}
if (inSingleBlock) {
removeSingleBlockAllocation(alloc);
if (!alloc->use_empty()) {
B.setInsertionPoint(std::next(alloc->getIterator()));
B.createDeallocStack(alloc->getLoc(), alloc);
}
return true;
}
StackAllocationPromoter(alloc, DT, DomTreeLevels, B).run();
eraseUsesOfInstruction(alloc);
return true;
}
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
86.
bool MemoryToRegisters::promoteSingleAllocation(AllocStackInst *alloc, DomTreeLevelMap &DomTreeLevels){
NumAllocStackFound++;
bool inSingleBlock = false;
if (isCaptured(alloc, inSingleBlock)) {
NumAllocStackCaptured++;
return false;
}
if (isWriteOnlyAllocation(alloc)) {
eraseUsesOfInstruction(alloc);
return true;
}
if (inSingleBlock) {
removeSingleBlockAllocation(alloc);
if (!alloc->use_empty()) {
B.setInsertionPoint(std::next(alloc->getIterator()));
B.createDeallocStack(alloc->getLoc(), alloc);
}
return true;
}
StackAllocationPromoter(alloc, DT, DomTreeLevels, B).run();
eraseUsesOfInstruction(alloc);
return true;
}
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
87.
bool MemoryToRegisters::promoteSingleAllocation(AllocStackInst *alloc, DomTreeLevelMap &DomTreeLevels){
NumAllocStackFound++;
bool inSingleBlock = false;
if (isCaptured(alloc, inSingleBlock)) {
NumAllocStackCaptured++;
return false;
}
if (isWriteOnlyAllocation(alloc)) {
eraseUsesOfInstruction(alloc);
return true;
}
if (inSingleBlock) {
removeSingleBlockAllocation(alloc);
if (!alloc->use_empty()) {
B.setInsertionPoint(std::next(alloc->getIterator()));
B.createDeallocStack(alloc->getLoc(), alloc);
}
return true;
}
StackAllocationPromoter(alloc, DT, DomTreeLevels, B).run();
eraseUsesOfInstruction(alloc);
return true;
}
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
88.
optimized.swift
func closure(_ completion: @escaping () -> Void) {
completion()
}
func number() -> Int {
var i: Int
i = 0
closure { i = 10 }
return i
}
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
89.
optimized.swift
func number() -> Int {
return 10
}
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
90.
Optimization Flags
→ -Onone
→ -O
→ -Ounchecked
→ -Osize
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
91.
Tips for Debug
→ -Xllvm -sil-print-all
→ -Xllvm -sil-print-only-functions
→ -Xllvm -sil-print-before/after/around
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
92.
Summary
→ Optimize, optimize and optimize !
→ Better ideas of how Swift Compiler works "
→ Definitely worth learning #
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
93.
References
→ var vs let in SIL
→ swift/docs/SIL.rst
→ Debugging the Swift Compiler
→ Swift's High-Level IR: A Case Study of
Complementing LLVM IR with Language-Specific
Optimization
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
94.
Thank you!
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018