Successfully reported this slideshow.

SIL Optimizations - AllocBoxToStack

3

Share

Upcoming SlideShare
PHP tips and tricks
PHP tips and tricks
Loading in …3
×
1 of 94
1 of 94

More Related Content

Related Books

Free with a 14 day trial from Scribd

See all

Related Audiobooks

Free with a 14 day trial from Scribd

See all

SIL Optimizations - AllocBoxToStack

  1. 1. SIL Optimizations AllocBoxToStack SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
  2. 2. Hi, I'm Yusuke @kitasuke SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
  3. 3. Why SIL?  SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
  4. 4. Why SIL? SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
  5. 5. Why SIL? → Better idea of Swift type system ! SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
  6. 6. Why SIL? → Better idea of Swift type system ! → Optimizations magic "✨ SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
  7. 7. Why SIL? → Better idea of Swift type system ! → Optimizations magic "✨ → Just for fun $ SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
  8. 8. SIL   SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
  9. 9. Swift Intermediate LanguageSIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
  10. 10. SIL is a language specific Intermediate Representation SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
  11. 11. Swift  SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
  12. 12. Swift Compiler SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
  13. 13. Swift Compiler SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
  14. 14. Swift Compiler SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
  15. 15. SIL SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
  16. 16. raw SIL SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
  17. 17. canonical SIL SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
  18. 18. Objective-C  SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
  19. 19. Clang    SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
  20. 20. Clang SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
  21. 21. SIL   SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
  22. 22. Optimizations SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
  23. 23. Optimization Passes → CapturePromotion → AllocBoxToStack → MandatoryInlining → DeadCodeElimination → Mem2Reg ... SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
  24. 24. AllocBoxToStack SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
  25. 25. Stack Promotion of Box Objects SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
  26. 26. Stack vs Heap SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
  27. 27. Stack SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
  28. 28. Stack → Very fast SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
  29. 29. Stack → Very fast → No explicit memory management SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
  30. 30. Stack → Very fast → No explicit memory management → Size limits SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
  31. 31. Heap SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
  32. 32. Heap → Slow SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
  33. 33. Heap → Slow → Explicit memory management SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
  34. 34. Heap → Slow → Explicit memory management → No size limits SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
  35. 35. Stack vs Heap Stack Heap Value types Reference types Pointers to reference type SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
  36. 36. How AllocBoxToStack works? SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
  37. 37. alloc_box ➡ alloc_stack SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
  38. 38. stack.swift func number() -> Int { var x: Int x = 1 return x } SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
  39. 39. raw SIL $swiftc -emit-silgen stack.swift > stack.sil SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
  40. 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. 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. 42. canonical SIL $swiftc -emit-sil stack.swift > stack.sil SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
  43. 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. 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. 45. alloc_box vs alloc_stack SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
  46. 46. alloc_box alloc_box allocates a reference counted box on heap. SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
  47. 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. 48. Stack Promotion of Box Objects SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
  49. 49. alloc_box ➡ alloc_stack SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
  50. 50. alloc_box ➡ alloc_box SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
  51. 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. 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. 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. 54. raw SIL $swiftc -emit-silgen box.swift > box.sil SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
  55. 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. 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. 57. canonical SIL $swiftc -emit-sil box.swift > box.sil SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
  58. 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. 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. 60. How can promote alloc_box? SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
  61. 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. 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. 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. 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. 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. 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. 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. 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. 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. 70. Recap → Promotes @noescape values to stack → @escaping values with a reference count SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
  71. 71. Optimization Flags SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
  72. 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. 73. canonical SIL with -O $swiftc -emit-sil -O optimized.swift > optimized.sil SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
  74. 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. 75. No alloc_box or alloc_stack SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
  76. 76. Mem2Reg SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
  77. 77. Register Promotion of Stack Allocations SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
  78. 78. How can promote stack allocation? SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
  79. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 89. optimized.swift func number() -> Int { return 10 } SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
  90. 90. Optimization Flags → -Onone → -O → -Ounchecked → -Osize SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018
  91. 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. 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. 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. 94. Thank you! SIL Optimizations - AllocBoxToStack, Yusuke Kita (@kitasuke), iOSDC 2018

×