SlideShare une entreprise Scribd logo
1  sur  94
Télécharger pour lire hors ligne
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

Contenu connexe

Similaire à SIL Optimizations - AllocBoxToStack

Brand New JavaScript - ECMAScript 2015
Brand New JavaScript - ECMAScript 2015Brand New JavaScript - ECMAScript 2015
Brand New JavaScript - ECMAScript 2015Gil Fink
 
Firebase & SwiftUI Workshop
Firebase & SwiftUI WorkshopFirebase & SwiftUI Workshop
Firebase & SwiftUI WorkshopPeter Friese
 
I phone勉強会 (2011.11.23)
I phone勉強会 (2011.11.23)I phone勉強会 (2011.11.23)
I phone勉強会 (2011.11.23)Katsumi Kishikawa
 
SIL for the first time
SIL for the first timeSIL for the first time
SIL for the first timeYusuke Kita
 
Compose로 Android:Desktop 멀티플랫폼 만들기.pdf
Compose로 Android:Desktop 멀티플랫폼 만들기.pdfCompose로 Android:Desktop 멀티플랫폼 만들기.pdf
Compose로 Android:Desktop 멀티플랫폼 만들기.pdfssuserb6c2641
 
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
 
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)abdels
 
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 applicationErick Ranes Akbar Mawuntu
 
Adopting 3D Touch in your apps
Adopting 3D Touch in your appsAdopting 3D Touch in your apps
Adopting 3D Touch in your appsJuan C Catalan
 
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 & Perl6Workhorse Computing
 
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
 
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 PartsKonrad Malawski
 
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 enhancementsPanagiotis Garefalakis
 
A tour through Swift attributes
A tour through Swift attributesA tour through Swift attributes
A tour through Swift attributesMarco Eidinger
 
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...OPITZ CONSULTING Deutschland
 
Map Reduce: Which Way To Go?
Map Reduce: Which Way To Go?Map Reduce: Which Way To Go?
Map Reduce: Which Way To Go?Ozren Gulan
 
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 ILsBlueHat Security Conference
 
Swift on Raspberry Pi
Swift on Raspberry PiSwift on Raspberry Pi
Swift on Raspberry PiSally Shepard
 

Similaire à 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
 

Plus de Yusuke Kita

Integrating libSyntax into the compiler pipeline
Integrating libSyntax into the compiler pipelineIntegrating libSyntax into the compiler pipeline
Integrating libSyntax into the compiler pipelineYusuke Kita
 
Making your own tool using SwiftSyntax
Making your own tool using SwiftSyntaxMaking your own tool using SwiftSyntax
Making your own tool using SwiftSyntaxYusuke Kita
 
[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 pipelineYusuke Kita
 
Creating your own Bitrise step
Creating your own Bitrise stepCreating your own Bitrise step
Creating your own Bitrise stepYusuke Kita
 
Introducing swift-format
Introducing swift-formatIntroducing swift-format
Introducing swift-formatYusuke Kita
 
Unidirectional Data Flow Through SwiftUI
Unidirectional Data Flow Through SwiftUIUnidirectional Data Flow Through SwiftUI
Unidirectional Data Flow Through SwiftUIYusuke Kita
 
Open Source Swift Workshop
Open Source Swift WorkshopOpen Source Swift Workshop
Open Source Swift WorkshopYusuke Kita
 
Contributing to Swift Compiler
Contributing to Swift CompilerContributing to Swift Compiler
Contributing to Swift CompilerYusuke Kita
 
Writing a compiler in go
Writing a compiler in goWriting a compiler in go
Writing a compiler in goYusuke Kita
 
Writing an interpreter in swift
Writing an interpreter in swiftWriting an interpreter in swift
Writing an interpreter in swiftYusuke Kita
 
How to try! Swift
How to try! SwiftHow to try! Swift
How to try! SwiftYusuke Kita
 
Introducing protobuf in Swift
Introducing protobuf in SwiftIntroducing protobuf in Swift
Introducing protobuf in SwiftYusuke Kita
 
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 AltConfYusuke Kita
 
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 iOSConYusuke Kita
 
SwiftCoreとFoundationを読んでみた
SwiftCoreとFoundationを読んでみたSwiftCoreとFoundationを読んでみた
SwiftCoreとFoundationを読んでみたYusuke Kita
 
Search APIs & Universal Links
Search APIs & Universal LinksSearch APIs & Universal Links
Search APIs & Universal LinksYusuke Kita
 
Introducing Cardio
Introducing CardioIntroducing Cardio
Introducing CardioYusuke Kita
 
Command Line Tool in swift
Command Line Tool in swiftCommand Line Tool in swift
Command Line Tool in swiftYusuke Kita
 

Plus de 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
 

Dernier

2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...Martijn de Jong
 
MS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsMS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsNanddeep Nachan
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoffsammart93
 
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 educationjfdjdjcjdnsjd
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processorsdebabhi2
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FMESafe Software
 
Cyberprint. Dark Pink Apt Group [EN].pdf
Cyberprint. Dark Pink Apt Group [EN].pdfCyberprint. Dark Pink Apt Group [EN].pdf
Cyberprint. Dark Pink Apt Group [EN].pdfOverkill Security
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingEdi Saputra
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDropbox
 
Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024The Digital Insurer
 
[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdfSandro Moreira
 
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...Angeliki Cooney
 
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 FresherRemote DBA Services
 
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 WoodJuan lago vázquez
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MIND CTI
 
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...Zilliz
 
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 DiscoveryTrustArc
 
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWEREMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWERMadyBayot
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...DianaGray10
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businesspanagenda
 

Dernier (20)

2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
MS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsMS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectors
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
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
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
Cyberprint. Dark Pink Apt Group [EN].pdf
Cyberprint. Dark Pink Apt Group [EN].pdfCyberprint. Dark Pink Apt Group [EN].pdf
Cyberprint. Dark Pink Apt Group [EN].pdf
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor Presentation
 
Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024
 
[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf
 
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
 
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
 
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
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
 
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
 
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWEREMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
 

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