SlideShare ist ein Scribd-Unternehmen logo
1 von 94
Downloaden Sie, um offline zu lesen
SIL Optimizations
AllocBoxToStack
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
Hi, I'm Yusuke
@kitasuke
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
Why SIL? 
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
Why SIL?
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
Why SIL?
→ Better idea of Swift type system !
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
Why SIL?
→ Better idea of Swift type system !
→ Optimizations magic "✨
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
Why SIL?
→ Better idea of Swift type system !
→ Optimizations magic "✨
→ Just for fun $
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
SIL  
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
Swift
Intermediate
LanguageSIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
SIL is a language specific
Intermediate
Representation
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
Swift 
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
Swift Compiler
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
Swift Compiler
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
Swift Compiler
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
SIL
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
raw SIL
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
canonical SIL
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
Objective-C 
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
Clang   
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
Clang
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
SIL  
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
Optimizations
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
Optimization Passes
→ CapturePromotion
→ AllocBoxToStack
→ MandatoryInlining
→ DeadCodeElimination
→ Mem2Reg
...
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
AllocBoxToStack
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
Stack Promotion of
Box Objects
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
Stack vs Heap
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
Stack
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
Stack
→ Very fast
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
Stack
→ Very fast
→ No explicit memory management
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
Stack
→ Very fast
→ No explicit memory management
→ Size limits
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
Heap
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
Heap
→ Slow
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
Heap
→ Slow
→ Explicit memory management
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
Heap
→ Slow
→ Explicit memory management
→ No size limits
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
Stack vs Heap
Stack Heap
Value types Reference types
Pointers to reference
type
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
How AllocBoxToStack
works?
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
alloc_box ➡ alloc_stack
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
stack.swift
func number() -> Int {
var x: Int
x = 1
return x
}
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
raw SIL
$swiftc -emit-silgen stack.swift > stack.sil
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
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
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
canonical SIL
$swiftc -emit-sil stack.swift > stack.sil
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
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
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
alloc_box vs alloc_stack
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
alloc_box
alloc_box allocates a reference counted box on
heap.
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
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
Stack Promotion of
Box Objects
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
alloc_box ➡ alloc_stack
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
alloc_box ➡ alloc_box
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
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
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
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
raw SIL
$swiftc -emit-silgen box.swift > box.sil
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
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
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
canonical SIL
$swiftc -emit-sil box.swift > box.sil
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
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
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
How can promote
alloc_box?
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
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
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
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
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
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
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
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
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
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
Recap
→ Promotes @noescape values to stack
→ @escaping values with a reference count
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
Optimization Flags
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
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
canonical SIL with -O
$swiftc -emit-sil -O optimized.swift > optimized.sil
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
optimized.sil
%0 = integer_literal $Builtin.Int64, 10
%1 = struct $Int (%0 : $Builtin.Int64)
return %1 : $Int
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
No alloc_box or
alloc_stack
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
Mem2Reg
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
Register Promotion of
Stack Allocations
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
How can promote stack
allocation?
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
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
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
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
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
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
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
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
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
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
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
optimized.swift
func number() -> Int {
return 10
}
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
Optimization Flags
→ -Onone
→ -O
→ -Ounchecked
→ -Osize
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
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
Summary
→ Optimize, optimize and optimize !
→ Better ideas of how Swift Compiler works "
→ Definitely worth learning #
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
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
Thank you!
SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018

Weitere ähnliche Inhalte

Ähnlich wie SIL Optimizations - AllocBoxToStack

Compose로 Android:Desktop 멀티플랫폼 만들기.pdf
Compose로 Android:Desktop 멀티플랫폼 만들기.pdfCompose로 Android:Desktop 멀티플랫폼 만들기.pdf
Compose로 Android:Desktop 멀티플랫폼 만들기.pdf
ssuserb6c2641
 
Tips of CakePHP and MongoDB - Cakefest2011 ichikaway
Tips of CakePHP and MongoDB - Cakefest2011 ichikaway Tips of CakePHP and MongoDB - Cakefest2011 ichikaway
Tips of CakePHP and MongoDB - Cakefest2011 ichikaway
ichikaway
 
Dataiku - Paris JUG 2013 - Hadoop is a batch
Dataiku - Paris JUG 2013 - Hadoop is a batch Dataiku - Paris JUG 2013 - Hadoop is a batch
Dataiku - Paris JUG 2013 - Hadoop is a batch
Dataiku
 
Accelerating distributed joins in Apache Hive: Runtime filtering enhancements
Accelerating distributed joins in Apache Hive: Runtime filtering enhancementsAccelerating distributed joins in Apache Hive: Runtime filtering enhancements
Accelerating distributed joins in Apache Hive: Runtime filtering enhancements
Panagiotis Garefalakis
 

Ähnlich wie SIL Optimizations - AllocBoxToStack (20)

Brand New JavaScript - ECMAScript 2015
Brand New JavaScript - ECMAScript 2015Brand New JavaScript - ECMAScript 2015
Brand New JavaScript - ECMAScript 2015
 
Firebase & SwiftUI Workshop
Firebase & SwiftUI WorkshopFirebase & SwiftUI Workshop
Firebase & SwiftUI Workshop
 
I phone勉強会 (2011.11.23)
I phone勉強会 (2011.11.23)I phone勉強会 (2011.11.23)
I phone勉強会 (2011.11.23)
 
SIL for the first time
SIL for the first timeSIL for the first time
SIL for the first time
 
Compose로 Android:Desktop 멀티플랫폼 만들기.pdf
Compose로 Android:Desktop 멀티플랫폼 만들기.pdfCompose로 Android:Desktop 멀티플랫폼 만들기.pdf
Compose로 Android:Desktop 멀티플랫폼 만들기.pdf
 
Tips of CakePHP and MongoDB - Cakefest2011 ichikaway
Tips of CakePHP and MongoDB - Cakefest2011 ichikaway Tips of CakePHP and MongoDB - Cakefest2011 ichikaway
Tips of CakePHP and MongoDB - Cakefest2011 ichikaway
 
My Adventures In Objective-C (A Rubyists Perspective)
My Adventures In Objective-C (A Rubyists Perspective)My Adventures In Objective-C (A Rubyists Perspective)
My Adventures In Objective-C (A Rubyists Perspective)
 
Integrating dialog flow (api.ai) into qiscus sdk chat application
Integrating dialog flow (api.ai) into qiscus sdk chat applicationIntegrating dialog flow (api.ai) into qiscus sdk chat application
Integrating dialog flow (api.ai) into qiscus sdk chat application
 
Adopting 3D Touch in your apps
Adopting 3D Touch in your appsAdopting 3D Touch in your apps
Adopting 3D Touch in your apps
 
Neatly Hashing a Tree: FP tree-fold in Perl5 & Perl6
Neatly Hashing a Tree: FP tree-fold in Perl5 & Perl6Neatly Hashing a Tree: FP tree-fold in Perl5 & Perl6
Neatly Hashing a Tree: FP tree-fold in Perl5 & Perl6
 
Dataiku - Paris JUG 2013 - Hadoop is a batch
Dataiku - Paris JUG 2013 - Hadoop is a batch Dataiku - Paris JUG 2013 - Hadoop is a batch
Dataiku - Paris JUG 2013 - Hadoop is a batch
 
Java 8: the good parts!
Java 8: the good parts!Java 8: the good parts!
Java 8: the good parts!
 
JavaOne 2013: Java 8 - The Good Parts
JavaOne 2013: Java 8 - The Good PartsJavaOne 2013: Java 8 - The Good Parts
JavaOne 2013: Java 8 - The Good Parts
 
Accelerating distributed joins in Apache Hive: Runtime filtering enhancements
Accelerating distributed joins in Apache Hive: Runtime filtering enhancementsAccelerating distributed joins in Apache Hive: Runtime filtering enhancements
Accelerating distributed joins in Apache Hive: Runtime filtering enhancements
 
A tour through Swift attributes
A tour through Swift attributesA tour through Swift attributes
A tour through Swift attributes
 
ioS Einstieg und Ausblick - Mobile DevCon Hamburg 2011 - OPITZ CONSULTING - S...
ioS Einstieg und Ausblick - Mobile DevCon Hamburg 2011 - OPITZ CONSULTING - S...ioS Einstieg und Ausblick - Mobile DevCon Hamburg 2011 - OPITZ CONSULTING - S...
ioS Einstieg und Ausblick - Mobile DevCon Hamburg 2011 - OPITZ CONSULTING - S...
 
Map Reduce: Which Way To Go?
Map Reduce: Which Way To Go?Map Reduce: Which Way To Go?
Map Reduce: Which Way To Go?
 
BlueHat Seattle 2019 || Modern Binary Analysis with ILs
BlueHat Seattle 2019 || Modern Binary Analysis with ILsBlueHat Seattle 2019 || Modern Binary Analysis with ILs
BlueHat Seattle 2019 || Modern Binary Analysis with ILs
 
Swift on Raspberry Pi
Swift on Raspberry PiSwift on Raspberry Pi
Swift on Raspberry Pi
 
Pragmatic sbt
Pragmatic sbtPragmatic sbt
Pragmatic sbt
 

Mehr von Yusuke Kita

Integrating libSyntax into the compiler pipeline
Integrating libSyntax into the compiler pipelineIntegrating libSyntax into the compiler pipeline
Integrating libSyntax into the compiler pipeline
Yusuke Kita
 

Mehr von Yusuke Kita (20)

Integrating libSyntax into the compiler pipeline
Integrating libSyntax into the compiler pipelineIntegrating libSyntax into the compiler pipeline
Integrating libSyntax into the compiler pipeline
 
Making your own tool using SwiftSyntax
Making your own tool using SwiftSyntaxMaking your own tool using SwiftSyntax
Making your own tool using SwiftSyntax
 
[Deprecated] Integrating libSyntax into the compiler pipeline
[Deprecated] Integrating libSyntax into the compiler pipeline[Deprecated] Integrating libSyntax into the compiler pipeline
[Deprecated] Integrating libSyntax into the compiler pipeline
 
Creating your own Bitrise step
Creating your own Bitrise stepCreating your own Bitrise step
Creating your own Bitrise step
 
Introducing swift-format
Introducing swift-formatIntroducing swift-format
Introducing swift-format
 
Unidirectional Data Flow Through SwiftUI
Unidirectional Data Flow Through SwiftUIUnidirectional Data Flow Through SwiftUI
Unidirectional Data Flow Through SwiftUI
 
Open Source Swift Workshop
Open Source Swift WorkshopOpen Source Swift Workshop
Open Source Swift Workshop
 
Contributing to Swift Compiler
Contributing to Swift CompilerContributing to Swift Compiler
Contributing to Swift Compiler
 
Writing a compiler in go
Writing a compiler in goWriting a compiler in go
Writing a compiler in go
 
Writing an interpreter in swift
Writing an interpreter in swiftWriting an interpreter in swift
Writing an interpreter in swift
 
var, let in SIL
var, let in SILvar, let in SIL
var, let in SIL
 
How to try! Swift
How to try! SwiftHow to try! Swift
How to try! Swift
 
Introducing protobuf in Swift
Introducing protobuf in SwiftIntroducing protobuf in Swift
Introducing protobuf in Swift
 
Type-safe Web APIs with Protocol Buffers in Swift at AltConf
Type-safe Web APIs with Protocol Buffers in Swift at AltConfType-safe Web APIs with Protocol Buffers in Swift at AltConf
Type-safe Web APIs with Protocol Buffers in Swift at AltConf
 
Type-safe Web APIs with Protocol Buffers in Swift at iOSCon
Type-safe Web APIs with Protocol Buffers in Swift at iOSConType-safe Web APIs with Protocol Buffers in Swift at iOSCon
Type-safe Web APIs with Protocol Buffers in Swift at iOSCon
 
Swift core
Swift coreSwift core
Swift core
 
SwiftCoreとFoundationを読んでみた
SwiftCoreとFoundationを読んでみたSwiftCoreとFoundationを読んでみた
SwiftCoreとFoundationを読んでみた
 
Search APIs & Universal Links
Search APIs & Universal LinksSearch APIs & Universal Links
Search APIs & Universal Links
 
Introducing Cardio
Introducing CardioIntroducing Cardio
Introducing Cardio
 
Command Line Tool in swift
Command Line Tool in swiftCommand Line Tool in swift
Command Line Tool in swift
 

Kürzlich hochgeladen

Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
Joaquim Jorge
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
?#DUbAI#??##{{(☎️+971_581248768%)**%*]'#abortion pills for sale in dubai@
 

Kürzlich hochgeladen (20)

HTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation StrategiesHTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation Strategies
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : Uncertainty
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsTop 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 

SIL Optimizations - AllocBoxToStack

  • 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
  • 23. Optimization Passes → CapturePromotion → AllocBoxToStack → MandatoryInlining → DeadCodeElimination → Mem2Reg ... 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
  • 74. optimized.sil %0 = integer_literal $Builtin.Int64, 10 %1 = struct $Int (%0 : $Builtin.Int64) return %1 : $Int 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