Swift Optimizing at Compiler World

Swift Optimizing at Compiler World

@NSSpain 2020 Remote Edition

1405a601755e5fcbfdc93a2560368bb1?s=128

freddi(Yuki Aki)

November 20, 2020
Tweet

Transcript

  1. Swift Optimizing at Compiler World NSSpain 2020: Remote Edition, November

    20th 2020 Yuki Aki from LINE Fukuoka
  2. About Me Yuki Aki (freddi) iOS Engineer at LINE Fukuoka

  3. Activity & Community Developing LINE Creators Studio at LINE Fukuoka

  4. Activity & Community Writing Swift for 2 years Swift Compiler,

    XcodeGen etc … Contributed to OSS Projects As a Speaker at many conferences
  5. About Me Yuki Aki (freddi) iOS Engineer at LINE Fukuoka

  6. Swift Optimizing at Compiler World

  7. Agenda Why need to learn Swift Compiler (Optimizer)? Basis of

    Swift Compiler Swift Intermediate Language (SIL) SIL Optimizer
  8. Agenda Why need to learn Swift Compiler (Optimizer)? Basis of

    Swift Compiler Swift Intermediate Language (SIL) SIL Optimizer
  9. Agenda Why need to learn Swift Compiler (Optimizer)? Basis of

    Swift Compiler Swift Intermediate Language (SIL) SIL Optimizer
  10. Agenda Why need to learn Swift Compiler (Optimizer)? Basis of

    Swift Compiler Swift Intermediate Language (SIL) SIL Optimizer
  11. Agenda Why need to learn Swift Compiler (Optimizer)? Basis of

    Swift Compiler Swift Intermediate Language (SIL) SIL Optimizer
  12. Swift Compiler

  13. Why need to learn Swift Compiler (Optimizer)?

  14. Why learn about Swift Compiler? Increase ways to solve difficult

    problems in Swift Coding Compiling Time, Compiler Bugs, Effective Code … Start Contributing to Swift Language So Fun
  15. Why learn about Optimizer? Easy to learn! Helpful to know

    what happened on Compiling for Product And how to try to solve problems related to Optimizer
  16. Agenda Why need to learn Swift Compiler (Optimizer)? Basis of

    Swift Compiler Swift Intermediate Language SIL Optimizer
  17. Basis of Swift Compiler

  18. Basis of Swift Compiler Looks Difficult? Don’t be afraid! I’ll

    describe Complier easily!
  19. Flow of Compiling Swift Code App

  20. AST AST (Typed) SIL IR (LLVM) App Flow of Compiling

    Swift Code
  21. AST AST (Typed) SIL IR (LLVM) App Flow of Compiling

    Swift Code
  22. AST Flow of Compiling Swift Code Convert to Abstract Syntax

    Tree by grammar rule of Swift Syntax Tree is a format for compiler to understand Code easy Parser
  23. AST AST (Typed) Flow of Compiling Swift Code AST to

    Typed AST Checking Type of the Code by generated AST or Type-Error Sema
  24. AST (Typed) SIL Flow of Compiling Swift Code SILGen Typed

    AST to Swift Intermediate Language(SIL) IR (Intermediate Representation)
  25. SIL IR (LLVM) Flow of Compiling Swift Code IRGen Swift

    Intermediate Language Code to LLVM IR LLVM is a backend of Swift
  26. IR (LLVM) App Flow of Compiling Swift Code Convert to

    executable, like iOS App, Command Line Tools … Other compiler phases like Linker are here (not touch today)
  27. AST AST (Typed) SIL IR (LLVM) App Flow of Compiling

    Swift Code
  28. AST AST (Typed) SIL IR (LLVM) App Flow of Compiling

    Swift Code
  29. SIL SIL is one of topic of talk topic! Let’s

    focus on SIL!
  30. Agenda Why need to learn Swift Compiler (Optimizer)? Basis of

    Swift Compiler Swift Intermediate Language SIL Optimizer
  31. Swift Intermediate Language

  32. AST AST (Typed) SIL IR (LLVM) App Swift Intermediate Language

  33. SIL Swift Intermediate Language Intermediate Representation(IR) of Swift Used for

    specialized optimization for Swift
  34. SIL Swift Intermediate Language LLVM IR is also optimized later

    IR (LLVM) Some effective optimization cannot be run on LLVM IR
  35. Swift Intermediate Language Let’s convert this code to SIL! print("Hello,

    World") hello.swift
  36. SIL Two kinds of SIL

  37. Two kinds of SIL

  38. Two kinds of SIL raw SIL canonical SIL

  39. raw SIL canonical SIL Two kinds of SIL raw SIL

    is generated by SILGen (from AST) canonical SIL is optimized raw SIL by SIL Optimizer
  40. Swift Intermediate Language raw SIL print("Hello, World") hello.swift

  41. None
  42. sil_stage raw import Builtin import Swift import SwiftShims // main

    sil [ossa] @main : $@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>) -> Int32 { bb0(%0 : $Int32, %1 : $UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>): %2 = integer_literal $Builtin.Word, 1 // user: %4 // function_ref _allocateUninitializedArray<A>(_:) %3 = function_ref @$ss27_allocateUninitializedArrayySayxG_BptBwlF : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned Array<τ_0_0>, Builtin.RawPointer) // user: %4 %4 = apply %3<Any>(%2) : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned Array<τ_0_0>, Builtin.RawPointer) // user: %5 (%5, %6) = destructure_tuple %4 : $(Array<Any>, Builtin.RawPointer) // users: %24, %21, %7 %7 = pointer_to_address %6 : $Builtin.RawPointer to [strict] $*Any // user: %14 %8 = string_literal utf8 "Hello, World" // user: %13 %9 = integer_literal $Builtin.Word, 12 // user: %13 %10 = integer_literal $Builtin.Int1, -1 // user: %13 %11 = metatype $@thin String.Type // user: %13 // function_ref String.init(_builtinStringLiteral:utf8CodeUnitCount:isASCII:) %12 = function_ref @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // user: %13 %13 = apply %12(%8, %9, %10, %11) : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // user: %15 %14 = init_existential_addr %7 : $*Any, $String // user: %15 store %13 to [init] %14 : $*String // id: %15 // function_ref default argument 1 of print(_:separator:terminator:) %16 = function_ref @$ss5print_9separator10terminatoryypd_S2StFfA0_ : $@convention(thin) () -> @owned String // user: %17 %17 = apply %16() : $@convention(thin) () -> @owned String // users: %23, %21 // function_ref default argument 2 of print(_:separator:terminator:) %18 = function_ref @$ss5print_9separator10terminatoryypd_S2StFfA1_ : $@convention(thin) () -> @owned String // user: %19 %19 = apply %18() : $@convention(thin) () -> @owned String // users: %22, %21 // function_ref print(_:separator:terminator:) %20 = function_ref @$ss5print_9separator10terminatoryypd_S2StF : $@convention(thin) (@guaranteed Array<Any>, @guaranteed String, @guaranteed String) -> () // user: %21 %21 = apply %20(%5, %17, %19) : $@convention(thin) (@guaranteed Array<Any>, @guaranteed String, @guaranteed String) -> () destroy_value %19 : $String // id: %22 destroy_value %17 : $String // id: %23 destroy_value %5 : $Array<Any> // id: %24 %25 = integer_literal $Builtin.Int32, 0 // user: %26 %26 = struct $Int32 (%25 : $Builtin.Int32) // user: %27 return %26 : $Int32 // id: %27 } // end sil function 'main' // _allocateUninitializedArray<A>(_:) sil [serialized] [always_inline] [_semantics "array.uninitialized_intrinsic"] @$ss27_allocateUninitializedArrayySayxG_BptBwlF : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned Array<τ_0_0>, Builtin.RawPointer) // String.init(_builtinStringLiteral:utf8CodeUnitCount:isASCII:) sil [serialized] [always_inline] [readonly] [_semantics "string.makeUTF8"] @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // default argument 1 of print(_:separator:terminator:) sil hidden_external [serialized] @$ss5print_9separator10terminatoryypd_S2StFfA0_ : $@convention(thin) () -> @owned String // default argument 2 of print(_:separator:terminator:) sil hidden_external [serialized] @$ss5print_9separator10terminatoryypd_S2StFfA1_ : $@convention(thin) () -> @owned String // print(_:separator:terminator:) sil @$ss5print_9separator10terminatoryypd_S2StF : $@convention(thin) (@guaranteed Array<Any>, @guaranteed String, @guaranteed String) -> ()
  43. sil_stage raw import Builtin import Swift import SwiftShims // main

    sil [ossa] @main : $@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>) -> Int32 { bb0(%0 : $Int32, %1 : $UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>): %2 = integer_literal $Builtin.Word, 1 // user: %4 // function_ref _allocateUninitializedArray<A>(_:) %3 = function_ref @$ss27_allocateUninitializedArrayySayxG_BptBwlF : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned Array<τ_0_0>, Builtin.RawPointer) // user: %4 %4 = apply %3<Any>(%2) : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned Array<τ_0_0>, Builtin.RawPointer) // user: %5 (%5, %6) = destructure_tuple %4 : $(Array<Any>, Builtin.RawPointer) // users: %24, %21, %7 %7 = pointer_to_address %6 : $Builtin.RawPointer to [strict] $*Any // user: %14 %8 = string_literal utf8 "Hello, World" // user: %13 %9 = integer_literal $Builtin.Word, 12 // user: %13 %10 = integer_literal $Builtin.Int1, -1 // user: %13 %11 = metatype $@thin String.Type // user: %13 // function_ref String.init(_builtinStringLiteral:utf8CodeUnitCount:isASCII:) %12 = function_ref @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // user: %13 %13 = apply %12(%8, %9, %10, %11) : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // user: %15 %14 = init_existential_addr %7 : $*Any, $String // user: %15 store %13 to [init] %14 : $*String // id: %15 // function_ref default argument 1 of print(_:separator:terminator:) %16 = function_ref @$ss5print_9separator10terminatoryypd_S2StFfA0_ : $@convention(thin) () -> @owned String // user: %17 %17 = apply %16() : $@convention(thin) () -> @owned String // users: %23, %21 // function_ref default argument 2 of print(_:separator:terminator:) %18 = function_ref @$ss5print_9separator10terminatoryypd_S2StFfA1_ : $@convention(thin) () -> @owned String // user: %19 %19 = apply %18() : $@convention(thin) () -> @owned String // users: %22, %21 // function_ref print(_:separator:terminator:) %20 = function_ref @$ss5print_9separator10terminatoryypd_S2StF : $@convention(thin) (@guaranteed Array<Any>, @guaranteed String, @guaranteed String) -> () // user: %21 %21 = apply %20(%5, %17, %19) : $@convention(thin) (@guaranteed Array<Any>, @guaranteed String, @guaranteed String) -> () destroy_value %19 : $String // id: %22 destroy_value %17 : $String // id: %23 destroy_value %5 : $Array<Any> // id: %24 %25 = integer_literal $Builtin.Int32, 0 // user: %26 %26 = struct $Int32 (%25 : $Builtin.Int32) // user: %27 return %26 : $Int32 // id: %27 } // end sil function 'main' // _allocateUninitializedArray<A>(_:) sil [serialized] [always_inline] [_semantics "array.uninitialized_intrinsic"] @$ss27_allocateUninitializedArrayySayxG_BptBwlF : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned Array<τ_0_0>, Builtin.RawPointer) // String.init(_builtinStringLiteral:utf8CodeUnitCount:isASCII:) sil [serialized] [always_inline] [readonly] [_semantics "string.makeUTF8"] @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // default argument 1 of print(_:separator:terminator:) sil hidden_external [serialized] @$ss5print_9separator10terminatoryypd_S2StFfA0_ : $@convention(thin) () -> @owned String // default argument 2 of print(_:separator:terminator:) sil hidden_external [serialized] @$ss5print_9separator10terminatoryypd_S2StFfA1_ : $@convention(thin) () -> @owned String // print(_:separator:terminator:) sil @$ss5print_9separator10terminatoryypd_S2StF : $@convention(thin) (@guaranteed Array<Any>, @guaranteed String, @guaranteed String) -> ()
  44. Structure of SIL Code SIL Module Generated from Swift Source

    File
  45. Structure of SIL Code SIL Module Meta information (Imported libraries,

    Function signature, Witness Table …)
  46. Structure of SIL Code SIL Module SIL Function SIL Function

    SIL Function Meta information (Imported libraries, Function signature, Witness Table …)
  47. sil_stage raw import Builtin import Swift import SwiftShims // main

    sil [ossa] @main : $@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>) -> Int32 { bb0(%0 : $Int32, %1 : $UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>): %2 = integer_literal $Builtin.Word, 1 // user: %4 // function_ref _allocateUninitializedArray<A>(_:) %3 = function_ref @$ss27_allocateUninitializedArrayySayxG_BptBwlF : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned Array<τ_0_0>, Builtin.RawPointer) // user: %4 %4 = apply %3<Any>(%2) : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned Array<τ_0_0>, Builtin.RawPointer) // user: %5 (%5, %6) = destructure_tuple %4 : $(Array<Any>, Builtin.RawPointer) // users: %24, %21, %7 %7 = pointer_to_address %6 : $Builtin.RawPointer to [strict] $*Any // user: %14 %8 = string_literal utf8 "Hello, World" // user: %13 %9 = integer_literal $Builtin.Word, 12 // user: %13 %10 = integer_literal $Builtin.Int1, -1 // user: %13 %11 = metatype $@thin String.Type // user: %13 // function_ref String.init(_builtinStringLiteral:utf8CodeUnitCount:isASCII:) %12 = function_ref @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // user: %13 %13 = apply %12(%8, %9, %10, %11) : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // user: %15 %14 = init_existential_addr %7 : $*Any, $String // user: %15 store %13 to [init] %14 : $*String // id: %15 // function_ref default argument 1 of print(_:separator:terminator:) %16 = function_ref @$ss5print_9separator10terminatoryypd_S2StFfA0_ : $@convention(thin) () -> @owned String // user: %17 %17 = apply %16() : $@convention(thin) () -> @owned String // users: %23, %21 // function_ref default argument 2 of print(_:separator:terminator:) %18 = function_ref @$ss5print_9separator10terminatoryypd_S2StFfA1_ : $@convention(thin) () -> @owned String // user: %19 %19 = apply %18() : $@convention(thin) () -> @owned String // users: %22, %21 // function_ref print(_:separator:terminator:) %20 = function_ref @$ss5print_9separator10terminatoryypd_S2StF : $@convention(thin) (@guaranteed Array<Any>, @guaranteed String, @guaranteed String) -> () // user: %21 %21 = apply %20(%5, %17, %19) : $@convention(thin) (@guaranteed Array<Any>, @guaranteed String, @guaranteed String) -> () destroy_value %19 : $String // id: %22 destroy_value %17 : $String // id: %23 destroy_value %5 : $Array<Any> // id: %24 %25 = integer_literal $Builtin.Int32, 0 // user: %26 %26 = struct $Int32 (%25 : $Builtin.Int32) // user: %27 return %26 : $Int32 // id: %27 } // end sil function 'main' // _allocateUninitializedArray<A>(_:) sil [serialized] [always_inline] [_semantics "array.uninitialized_intrinsic"] @$ss27_allocateUninitializedArrayySayxG_BptBwlF : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned Array<τ_0_0>, Builtin.RawPointer) // String.init(_builtinStringLiteral:utf8CodeUnitCount:isASCII:) sil [serialized] [always_inline] [readonly] [_semantics "string.makeUTF8"] @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // default argument 1 of print(_:separator:terminator:) sil hidden_external [serialized] @$ss5print_9separator10terminatoryypd_S2StFfA0_ : $@convention(thin) () -> @owned String // default argument 2 of print(_:separator:terminator:) sil hidden_external [serialized] @$ss5print_9separator10terminatoryypd_S2StFfA1_ : $@convention(thin) () -> @owned String // print(_:separator:terminator:) sil @$ss5print_9separator10terminatoryypd_S2StF : $@convention(thin) (@guaranteed Array<Any>, @guaranteed String, @guaranteed String) -> () import Builtin import Swift import SwiftShims sil_stage raw
  48. sil_stage raw import Builtin import Swift import SwiftShims // main

    sil [ossa] @main : $@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>) -> Int32 { bb0(%0 : $Int32, %1 : $UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>): %2 = integer_literal $Builtin.Word, 1 // user: %4 // function_ref _allocateUninitializedArray<A>(_:) %3 = function_ref @$ss27_allocateUninitializedArrayySayxG_BptBwlF : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned Array<τ_0_0>, Builtin.RawPointer) // user: %4 %4 = apply %3<Any>(%2) : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned Array<τ_0_0>, Builtin.RawPointer) // user: %5 (%5, %6) = destructure_tuple %4 : $(Array<Any>, Builtin.RawPointer) // users: %24, %21, %7 %7 = pointer_to_address %6 : $Builtin.RawPointer to [strict] $*Any // user: %14 %8 = string_literal utf8 "Hello, World" // user: %13 %9 = integer_literal $Builtin.Word, 12 // user: %13 %10 = integer_literal $Builtin.Int1, -1 // user: %13 %11 = metatype $@thin String.Type // user: %13 // function_ref String.init(_builtinStringLiteral:utf8CodeUnitCount:isASCII:) %12 = function_ref @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // user: %13 %13 = apply %12(%8, %9, %10, %11) : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // user: %15 %14 = init_existential_addr %7 : $*Any, $String // user: %15 store %13 to [init] %14 : $*String // id: %15 // function_ref default argument 1 of print(_:separator:terminator:) %16 = function_ref @$ss5print_9separator10terminatoryypd_S2StFfA0_ : $@convention(thin) () -> @owned String // user: %17 %17 = apply %16() : $@convention(thin) () -> @owned String // users: %23, %21 // function_ref default argument 2 of print(_:separator:terminator:) %18 = function_ref @$ss5print_9separator10terminatoryypd_S2StFfA1_ : $@convention(thin) () -> @owned String // user: %19 %19 = apply %18() : $@convention(thin) () -> @owned String // users: %22, %21 // function_ref print(_:separator:terminator:) %20 = function_ref @$ss5print_9separator10terminatoryypd_S2StF : $@convention(thin) (@guaranteed Array<Any>, @guaranteed String, @guaranteed String) -> () // user: %21 %21 = apply %20(%5, %17, %19) : $@convention(thin) (@guaranteed Array<Any>, @guaranteed String, @guaranteed String) -> () destroy_value %19 : $String // id: %22 destroy_value %17 : $String // id: %23 destroy_value %5 : $Array<Any> // id: %24 %25 = integer_literal $Builtin.Int32, 0 // user: %26 %26 = struct $Int32 (%25 : $Builtin.Int32) // user: %27 return %26 : $Int32 // id: %27 } // end sil function 'main' // _allocateUninitializedArray<A>(_:) sil [serialized] [always_inline] [_semantics "array.uninitialized_intrinsic"] @$ss27_allocateUninitializedArrayySayxG_BptBwlF : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned Array<τ_0_0>, Builtin.RawPointer) // String.init(_builtinStringLiteral:utf8CodeUnitCount:isASCII:) sil [serialized] [always_inline] [readonly] [_semantics "string.makeUTF8"] @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // default argument 1 of print(_:separator:terminator:) sil hidden_external [serialized] @$ss5print_9separator10terminatoryypd_S2StFfA0_ : $@convention(thin) () -> @owned String // default argument 2 of print(_:separator:terminator:) sil hidden_external [serialized] @$ss5print_9separator10terminatoryypd_S2StFfA1_ : $@convention(thin) () -> @owned String // print(_:separator:terminator:) sil @$ss5print_9separator10terminatoryypd_S2StF : $@convention(thin) (@guaranteed Array<Any>, @guaranteed String, @guaranteed String) -> () sil_stage raw raw or canonical
  49. sil_stage raw import Builtin import Swift import SwiftShims // main

    sil [ossa] @main : $@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>) -> Int32 { bb0(%0 : $Int32, %1 : $UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>): %2 = integer_literal $Builtin.Word, 1 // user: %4 // function_ref _allocateUninitializedArray<A>(_:) %3 = function_ref @$ss27_allocateUninitializedArrayySayxG_BptBwlF : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned Array<τ_0_0>, Builtin.RawPointer) // user: %4 %4 = apply %3<Any>(%2) : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned Array<τ_0_0>, Builtin.RawPointer) // user: %5 (%5, %6) = destructure_tuple %4 : $(Array<Any>, Builtin.RawPointer) // users: %24, %21, %7 %7 = pointer_to_address %6 : $Builtin.RawPointer to [strict] $*Any // user: %14 %8 = string_literal utf8 "Hello, World" // user: %13 %9 = integer_literal $Builtin.Word, 12 // user: %13 %10 = integer_literal $Builtin.Int1, -1 // user: %13 %11 = metatype $@thin String.Type // user: %13 // function_ref String.init(_builtinStringLiteral:utf8CodeUnitCount:isASCII:) %12 = function_ref @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // user: %13 %13 = apply %12(%8, %9, %10, %11) : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // user: %15 %14 = init_existential_addr %7 : $*Any, $String // user: %15 store %13 to [init] %14 : $*String // id: %15 // function_ref default argument 1 of print(_:separator:terminator:) %16 = function_ref @$ss5print_9separator10terminatoryypd_S2StFfA0_ : $@convention(thin) () -> @owned String // user: %17 %17 = apply %16() : $@convention(thin) () -> @owned String // users: %23, %21 // function_ref default argument 2 of print(_:separator:terminator:) %18 = function_ref @$ss5print_9separator10terminatoryypd_S2StFfA1_ : $@convention(thin) () -> @owned String // user: %19 %19 = apply %18() : $@convention(thin) () -> @owned String // users: %22, %21 // function_ref print(_:separator:terminator:) %20 = function_ref @$ss5print_9separator10terminatoryypd_S2StF : $@convention(thin) (@guaranteed Array<Any>, @guaranteed String, @guaranteed String) -> () // user: %21 %21 = apply %20(%5, %17, %19) : $@convention(thin) (@guaranteed Array<Any>, @guaranteed String, @guaranteed String) -> () destroy_value %19 : $String // id: %22 destroy_value %17 : $String // id: %23 destroy_value %5 : $Array<Any> // id: %24 %25 = integer_literal $Builtin.Int32, 0 // user: %26 %26 = struct $Int32 (%25 : $Builtin.Int32) // user: %27 return %26 : $Int32 // id: %27 } // end sil function 'main' // _allocateUninitializedArray<A>(_:) sil [serialized] [always_inline] [_semantics "array.uninitialized_intrinsic"] @$ss27_allocateUninitializedArrayySayxG_BptBwlF : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned Array<τ_0_0>, Builtin.RawPointer) // String.init(_builtinStringLiteral:utf8CodeUnitCount:isASCII:) sil [serialized] [always_inline] [readonly] [_semantics "string.makeUTF8"] @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // default argument 1 of print(_:separator:terminator:) sil hidden_external [serialized] @$ss5print_9separator10terminatoryypd_S2StFfA0_ : $@convention(thin) () -> @owned String // default argument 2 of print(_:separator:terminator:) sil hidden_external [serialized] @$ss5print_9separator10terminatoryypd_S2StFfA1_ : $@convention(thin) () -> @owned String // print(_:separator:terminator:) sil @$ss5print_9separator10terminatoryypd_S2StF : $@convention(thin) (@guaranteed Array<Any>, @guaranteed String, @guaranteed String) -> () import Builtin import Swift import SwiftShims
  50. sil_stage raw import Builtin import Swift import SwiftShims // main

    sil [ossa] @main : $@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>) -> Int32 { bb0(%0 : $Int32, %1 : $UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>): %2 = integer_literal $Builtin.Word, 1 // user: %4 // function_ref _allocateUninitializedArray<A>(_:) %3 = function_ref @$ss27_allocateUninitializedArrayySayxG_BptBwlF : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned Array<τ_0_0>, Builtin.RawPointer) // user: %4 %4 = apply %3<Any>(%2) : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned Array<τ_0_0>, Builtin.RawPointer) // user: %5 (%5, %6) = destructure_tuple %4 : $(Array<Any>, Builtin.RawPointer) // users: %24, %21, %7 %7 = pointer_to_address %6 : $Builtin.RawPointer to [strict] $*Any // user: %14 %8 = string_literal utf8 "Hello, World" // user: %13 %9 = integer_literal $Builtin.Word, 12 // user: %13 %10 = integer_literal $Builtin.Int1, -1 // user: %13 %11 = metatype $@thin String.Type // user: %13 // function_ref String.init(_builtinStringLiteral:utf8CodeUnitCount:isASCII:) %12 = function_ref @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // user: %13 %13 = apply %12(%8, %9, %10, %11) : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // user: %15 %14 = init_existential_addr %7 : $*Any, $String // user: %15 store %13 to [init] %14 : $*String // id: %15 // function_ref default argument 1 of print(_:separator:terminator:) %16 = function_ref @$ss5print_9separator10terminatoryypd_S2StFfA0_ : $@convention(thin) () -> @owned String // user: %17 %17 = apply %16() : $@convention(thin) () -> @owned String // users: %23, %21 // function_ref default argument 2 of print(_:separator:terminator:) %18 = function_ref @$ss5print_9separator10terminatoryypd_S2StFfA1_ : $@convention(thin) () -> @owned String // user: %19 %19 = apply %18() : $@convention(thin) () -> @owned String // users: %22, %21 // function_ref print(_:separator:terminator:) %20 = function_ref @$ss5print_9separator10terminatoryypd_S2StF : $@convention(thin) (@guaranteed Array<Any>, @guaranteed String, @guaranteed String) -> () // user: %21 %21 = apply %20(%5, %17, %19) : $@convention(thin) (@guaranteed Array<Any>, @guaranteed String, @guaranteed String) -> () destroy_value %19 : $String // id: %22 destroy_value %17 : $String // id: %23 destroy_value %5 : $Array<Any> // id: %24 %25 = integer_literal $Builtin.Int32, 0 // user: %26 %26 = struct $Int32 (%25 : $Builtin.Int32) // user: %27 return %26 : $Int32 // id: %27 } // end sil function 'main' // _allocateUninitializedArray<A>(_:) sil [serialized] [always_inline] [_semantics "array.uninitialized_intrinsic"] @$ss27_allocateUninitializedArrayySayxG_BptBwlF : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned Array<τ_0_0>, Builtin.RawPointer) // String.init(_builtinStringLiteral:utf8CodeUnitCount:isASCII:) sil [serialized] [always_inline] [readonly] [_semantics "string.makeUTF8"] @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // default argument 1 of print(_:separator:terminator:) sil hidden_external [serialized] @$ss5print_9separator10terminatoryypd_S2StFfA0_ : $@convention(thin) () -> @owned String // default argument 2 of print(_:separator:terminator:) sil hidden_external [serialized] @$ss5print_9separator10terminatoryypd_S2StFfA1_ : $@convention(thin) () -> @owned String // print(_:separator:terminator:) sil @$ss5print_9separator10terminatoryypd_S2StF : $@convention(thin) (@guaranteed Array<Any>, @guaranteed String, @guaranteed String) -> () import Builtin import Swift import SwiftShims
  51. sil_stage raw import Builtin import Swift import SwiftShims // main

    sil [ossa] @main : $@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>) -> Int32 { bb0(%0 : $Int32, %1 : $UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>): %2 = integer_literal $Builtin.Word, 1 // user: %4 // function_ref _allocateUninitializedArray<A>(_:) %3 = function_ref @$ss27_allocateUninitializedArrayySayxG_BptBwlF : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned Array<τ_0_0>, Builtin.RawPointer) // user: %4 %4 = apply %3<Any>(%2) : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned Array<τ_0_0>, Builtin.RawPointer) // user: %5 (%5, %6) = destructure_tuple %4 : $(Array<Any>, Builtin.RawPointer) // users: %24, %21, %7 %7 = pointer_to_address %6 : $Builtin.RawPointer to [strict] $*Any // user: %14 %8 = string_literal utf8 "Hello, World" // user: %13 %9 = integer_literal $Builtin.Word, 12 // user: %13 %10 = integer_literal $Builtin.Int1, -1 // user: %13 %11 = metatype $@thin String.Type // user: %13 // function_ref String.init(_builtinStringLiteral:utf8CodeUnitCount:isASCII:) %12 = function_ref @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // user: %13 %13 = apply %12(%8, %9, %10, %11) : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // user: %15 %14 = init_existential_addr %7 : $*Any, $String // user: %15 store %13 to [init] %14 : $*String // id: %15 // function_ref default argument 1 of print(_:separator:terminator:) %16 = function_ref @$ss5print_9separator10terminatoryypd_S2StFfA0_ : $@convention(thin) () -> @owned String // user: %17 %17 = apply %16() : $@convention(thin) () -> @owned String // users: %23, %21 // function_ref default argument 2 of print(_:separator:terminator:) %18 = function_ref @$ss5print_9separator10terminatoryypd_S2StFfA1_ : $@convention(thin) () -> @owned String // user: %19 %19 = apply %18() : $@convention(thin) () -> @owned String // users: %22, %21 // function_ref print(_:separator:terminator:) %20 = function_ref @$ss5print_9separator10terminatoryypd_S2StF : $@convention(thin) (@guaranteed Array<Any>, @guaranteed String, @guaranteed String) -> () // user: %21 %21 = apply %20(%5, %17, %19) : $@convention(thin) (@guaranteed Array<Any>, @guaranteed String, @guaranteed String) -> () destroy_value %19 : $String // id: %22 destroy_value %17 : $String // id: %23 destroy_value %5 : $Array<Any> // id: %24 %25 = integer_literal $Builtin.Int32, 0 // user: %26 %26 = struct $Int32 (%25 : $Builtin.Int32) // user: %27 return %26 : $Int32 // id: %27 } // end sil function 'main' // _allocateUninitializedArray<A>(_:) sil [serialized] [always_inline] [_semantics "array.uninitialized_intrinsic"] @$ss27_allocateUninitializedArrayySayxG_BptBwlF : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned Array<τ_0_0>, Builtin.RawPointer) // String.init(_builtinStringLiteral:utf8CodeUnitCount:isASCII:) sil [serialized] [always_inline] [readonly] [_semantics "string.makeUTF8"] @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // default argument 1 of print(_:separator:terminator:) sil hidden_external [serialized] @$ss5print_9separator10terminatoryypd_S2StFfA0_ : $@convention(thin) () -> @owned String // default argument 2 of print(_:separator:terminator:) sil hidden_external [serialized] @$ss5print_9separator10terminatoryypd_S2StFfA1_ : $@convention(thin) () -> @owned String // print(_:separator:terminator:) sil @$ss5print_9separator10terminatoryypd_S2StF : $@convention(thin) (@guaranteed Array<Any>, @guaranteed String, @guaranteed String) -> () import Builtin import Swift import SwiftShims $Builtin.Int
  52. sil_stage raw import Builtin import Swift import SwiftShims // main

    sil [ossa] @main : $@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>) -> Int32 { bb0(%0 : $Int32, %1 : $UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>): %2 = integer_literal $Builtin.Word, 1 // user: %4 // function_ref _allocateUninitializedArray<A>(_:) %3 = function_ref @$ss27_allocateUninitializedArrayySayxG_BptBwlF : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned Array<τ_0_0>, Builtin.RawPointer) // user: %4 %4 = apply %3<Any>(%2) : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned Array<τ_0_0>, Builtin.RawPointer) // user: %5 (%5, %6) = destructure_tuple %4 : $(Array<Any>, Builtin.RawPointer) // users: %24, %21, %7 %7 = pointer_to_address %6 : $Builtin.RawPointer to [strict] $*Any // user: %14 %8 = string_literal utf8 "Hello, World" // user: %13 %9 = integer_literal $Builtin.Word, 12 // user: %13 %10 = integer_literal $Builtin.Int1, -1 // user: %13 %11 = metatype $@thin String.Type // user: %13 // function_ref String.init(_builtinStringLiteral:utf8CodeUnitCount:isASCII:) %12 = function_ref @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // user: %13 %13 = apply %12(%8, %9, %10, %11) : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // user: %15 %14 = init_existential_addr %7 : $*Any, $String // user: %15 store %13 to [init] %14 : $*String // id: %15 // function_ref default argument 1 of print(_:separator:terminator:) %16 = function_ref @$ss5print_9separator10terminatoryypd_S2StFfA0_ : $@convention(thin) () -> @owned String // user: %17 %17 = apply %16() : $@convention(thin) () -> @owned String // users: %23, %21 // function_ref default argument 2 of print(_:separator:terminator:) %18 = function_ref @$ss5print_9separator10terminatoryypd_S2StFfA1_ : $@convention(thin) () -> @owned String // user: %19 %19 = apply %18() : $@convention(thin) () -> @owned String // users: %22, %21 // function_ref print(_:separator:terminator:) %20 = function_ref @$ss5print_9separator10terminatoryypd_S2StF : $@convention(thin) (@guaranteed Array<Any>, @guaranteed String, @guaranteed String) -> () // user: %21 %21 = apply %20(%5, %17, %19) : $@convention(thin) (@guaranteed Array<Any>, @guaranteed String, @guaranteed String) -> () destroy_value %19 : $String // id: %22 destroy_value %17 : $String // id: %23 destroy_value %5 : $Array<Any> // id: %24 %25 = integer_literal $Builtin.Int32, 0 // user: %26 %26 = struct $Int32 (%25 : $Builtin.Int32) // user: %27 return %26 : $Int32 // id: %27 } // end sil function 'main' // _allocateUninitializedArray<A>(_:) sil [serialized] [always_inline] [_semantics "array.uninitialized_intrinsic"] @$ss27_allocateUninitializedArrayySayxG_BptBwlF : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned Array<τ_0_0>, Builtin.RawPointer) // String.init(_builtinStringLiteral:utf8CodeUnitCount:isASCII:) sil [serialized] [always_inline] [readonly] [_semantics "string.makeUTF8"] @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // default argument 1 of print(_:separator:terminator:) sil hidden_external [serialized] @$ss5print_9separator10terminatoryypd_S2StFfA0_ : $@convention(thin) () -> @owned String // default argument 2 of print(_:separator:terminator:) sil hidden_external [serialized] @$ss5print_9separator10terminatoryypd_S2StFfA1_ : $@convention(thin) () -> @owned String // print(_:separator:terminator:) sil @$ss5print_9separator10terminatoryypd_S2StF : $@convention(thin) (@guaranteed Array<Any>, @guaranteed String, @guaranteed String) -> () import Builtin import Swift import SwiftShims $Builtin.Int
  53. sil_stage raw import Builtin import Swift import SwiftShims // main

    sil [ossa] @main : $@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>) -> Int32 { bb0(%0 : $Int32, %1 : $UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>): %2 = integer_literal $Builtin.Word, 1 // user: %4 // function_ref _allocateUninitializedArray<A>(_:) %3 = function_ref @$ss27_allocateUninitializedArrayySayxG_BptBwlF : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned Array<τ_0_0>, Builtin.RawPointer) // user: %4 %4 = apply %3<Any>(%2) : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned Array<τ_0_0>, Builtin.RawPointer) // user: %5 (%5, %6) = destructure_tuple %4 : $(Array<Any>, Builtin.RawPointer) // users: %24, %21, %7 %7 = pointer_to_address %6 : $Builtin.RawPointer to [strict] $*Any // user: %14 %8 = string_literal utf8 "Hello, World" // user: %13 %9 = integer_literal $Builtin.Word, 12 // user: %13 %10 = integer_literal $Builtin.Int1, -1 // user: %13 %11 = metatype $@thin String.Type // user: %13 // function_ref String.init(_builtinStringLiteral:utf8CodeUnitCount:isASCII:) %12 = function_ref @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // user: %13 %13 = apply %12(%8, %9, %10, %11) : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // user: %15 %14 = init_existential_addr %7 : $*Any, $String // user: %15 store %13 to [init] %14 : $*String // id: %15 // function_ref default argument 1 of print(_:separator:terminator:) %16 = function_ref @$ss5print_9separator10terminatoryypd_S2StFfA0_ : $@convention(thin) () -> @owned String // user: %17 %17 = apply %16() : $@convention(thin) () -> @owned String // users: %23, %21 // function_ref default argument 2 of print(_:separator:terminator:) %18 = function_ref @$ss5print_9separator10terminatoryypd_S2StFfA1_ : $@convention(thin) () -> @owned String // user: %19 %19 = apply %18() : $@convention(thin) () -> @owned String // users: %22, %21 // function_ref print(_:separator:terminator:) %20 = function_ref @$ss5print_9separator10terminatoryypd_S2StF : $@convention(thin) (@guaranteed Array<Any>, @guaranteed String, @guaranteed String) -> () // user: %21 %21 = apply %20(%5, %17, %19) : $@convention(thin) (@guaranteed Array<Any>, @guaranteed String, @guaranteed String) -> () destroy_value %19 : $String // id: %22 destroy_value %17 : $String // id: %23 destroy_value %5 : $Array<Any> // id: %24 %25 = integer_literal $Builtin.Int32, 0 // user: %26 %26 = struct $Int32 (%25 : $Builtin.Int32) // user: %27 return %26 : $Int32 // id: %27 } // end sil function 'main' // _allocateUninitializedArray<A>(_:) sil [serialized] [always_inline] [_semantics "array.uninitialized_intrinsic"] @$ss27_allocateUninitializedArrayySayxG_BptBwlF : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned Array<τ_0_0>, Builtin.RawPointer) // String.init(_builtinStringLiteral:utf8CodeUnitCount:isASCII:) sil [serialized] [always_inline] [readonly] [_semantics "string.makeUTF8"] @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // default argument 1 of print(_:separator:terminator:) sil hidden_external [serialized] @$ss5print_9separator10terminatoryypd_S2StFfA0_ : $@convention(thin) () -> @owned String // default argument 2 of print(_:separator:terminator:) sil hidden_external [serialized] @$ss5print_9separator10terminatoryypd_S2StFfA1_ : $@convention(thin) () -> @owned String // print(_:separator:terminator:) sil @$ss5print_9separator10terminatoryypd_S2StF : $@convention(thin) (@guaranteed Array<Any>, @guaranteed String, @guaranteed String) -> () import Builtin import Swift import SwiftShims $Builtin.Int My Builtin Literal talk is avalible on YouTube
  54. sil_stage raw import Builtin import Swift import SwiftShims // main

    sil [ossa] @main : $@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>) -> Int32 { bb0(%0 : $Int32, %1 : $UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>): %2 = integer_literal $Builtin.Word, 1 // user: %4 // function_ref _allocateUninitializedArray<A>(_:) %3 = function_ref @$ss27_allocateUninitializedArrayySayxG_BptBwlF : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned Array<τ_0_0>, Builtin.RawPointer) // user: %4 %4 = apply %3<Any>(%2) : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned Array<τ_0_0>, Builtin.RawPointer) // user: %5 (%5, %6) = destructure_tuple %4 : $(Array<Any>, Builtin.RawPointer) // users: %24, %21, %7 %7 = pointer_to_address %6 : $Builtin.RawPointer to [strict] $*Any // user: %14 %8 = string_literal utf8 "Hello, World" // user: %13 %9 = integer_literal $Builtin.Word, 12 // user: %13 %10 = integer_literal $Builtin.Int1, -1 // user: %13 %11 = metatype $@thin String.Type // user: %13 // function_ref String.init(_builtinStringLiteral:utf8CodeUnitCount:isASCII:) %12 = function_ref @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // user: %13 %13 = apply %12(%8, %9, %10, %11) : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // user: %15 %14 = init_existential_addr %7 : $*Any, $String // user: %15 store %13 to [init] %14 : $*String // id: %15 // function_ref default argument 1 of print(_:separator:terminator:) %16 = function_ref @$ss5print_9separator10terminatoryypd_S2StFfA0_ : $@convention(thin) () -> @owned String // user: %17 %17 = apply %16() : $@convention(thin) () -> @owned String // users: %23, %21 // function_ref default argument 2 of print(_:separator:terminator:) %18 = function_ref @$ss5print_9separator10terminatoryypd_S2StFfA1_ : $@convention(thin) () -> @owned String // user: %19 %19 = apply %18() : $@convention(thin) () -> @owned String // users: %22, %21 // function_ref print(_:separator:terminator:) %20 = function_ref @$ss5print_9separator10terminatoryypd_S2StF : $@convention(thin) (@guaranteed Array<Any>, @guaranteed String, @guaranteed String) -> () // user: %21 %21 = apply %20(%5, %17, %19) : $@convention(thin) (@guaranteed Array<Any>, @guaranteed String, @guaranteed String) -> () destroy_value %19 : $String // id: %22 destroy_value %17 : $String // id: %23 destroy_value %5 : $Array<Any> // id: %24 %25 = integer_literal $Builtin.Int32, 0 // user: %26 %26 = struct $Int32 (%25 : $Builtin.Int32) // user: %27 return %26 : $Int32 // id: %27 } // end sil function 'main' // _allocateUninitializedArray<A>(_:) sil [serialized] [always_inline] [_semantics "array.uninitialized_intrinsic"] @$ss27_allocateUninitializedArrayySayxG_BptBwlF : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned Array<τ_0_0>, Builtin.RawPointer) // String.init(_builtinStringLiteral:utf8CodeUnitCount:isASCII:) sil [serialized] [always_inline] [readonly] [_semantics "string.makeUTF8"] @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // default argument 1 of print(_:separator:terminator:) sil hidden_external [serialized] @$ss5print_9separator10terminatoryypd_S2StFfA0_ : $@convention(thin) () -> @owned String // default argument 2 of print(_:separator:terminator:) sil hidden_external [serialized] @$ss5print_9separator10terminatoryypd_S2StFfA1_ : $@convention(thin) () -> @owned String // print(_:separator:terminator:) sil @$ss5print_9separator10terminatoryypd_S2StF : $@convention(thin) (@guaranteed Array<Any>, @guaranteed String, @guaranteed String) -> () import Builtin import Swift import SwiftShims sil [ossa] @main : $@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>) -> Int32 {
  55. sil_stage raw import Builtin import Swift import SwiftShims // main

    sil [ossa] @main : $@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>) -> Int32 { bb0(%0 : $Int32, %1 : $UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>): %2 = integer_literal $Builtin.Word, 1 // user: %4 // function_ref _allocateUninitializedArray<A>(_:) %3 = function_ref @$ss27_allocateUninitializedArrayySayxG_BptBwlF : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned Array<τ_0_0>, Builtin.RawPointer) // user: %4 %4 = apply %3<Any>(%2) : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned Array<τ_0_0>, Builtin.RawPointer) // user: %5 (%5, %6) = destructure_tuple %4 : $(Array<Any>, Builtin.RawPointer) // users: %24, %21, %7 %7 = pointer_to_address %6 : $Builtin.RawPointer to [strict] $*Any // user: %14 %8 = string_literal utf8 "Hello, World" // user: %13 %9 = integer_literal $Builtin.Word, 12 // user: %13 %10 = integer_literal $Builtin.Int1, -1 // user: %13 %11 = metatype $@thin String.Type // user: %13 // function_ref String.init(_builtinStringLiteral:utf8CodeUnitCount:isASCII:) %12 = function_ref @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // user: %13 %13 = apply %12(%8, %9, %10, %11) : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // user: %15 %14 = init_existential_addr %7 : $*Any, $String // user: %15 store %13 to [init] %14 : $*String // id: %15 // function_ref default argument 1 of print(_:separator:terminator:) %16 = function_ref @$ss5print_9separator10terminatoryypd_S2StFfA0_ : $@convention(thin) () -> @owned String // user: %17 %17 = apply %16() : $@convention(thin) () -> @owned String // users: %23, %21 // function_ref default argument 2 of print(_:separator:terminator:) %18 = function_ref @$ss5print_9separator10terminatoryypd_S2StFfA1_ : $@convention(thin) () -> @owned String // user: %19 %19 = apply %18() : $@convention(thin) () -> @owned String // users: %22, %21 // function_ref print(_:separator:terminator:) %20 = function_ref @$ss5print_9separator10terminatoryypd_S2StF : $@convention(thin) (@guaranteed Array<Any>, @guaranteed String, @guaranteed String) -> () // user: %21 %21 = apply %20(%5, %17, %19) : $@convention(thin) (@guaranteed Array<Any>, @guaranteed String, @guaranteed String) -> () destroy_value %19 : $String // id: %22 destroy_value %17 : $String // id: %23 destroy_value %5 : $Array<Any> // id: %24 %25 = integer_literal $Builtin.Int32, 0 // user: %26 %26 = struct $Int32 (%25 : $Builtin.Int32) // user: %27 return %26 : $Int32 // id: %27 } // end sil function 'main' // _allocateUninitializedArray<A>(_:) sil [serialized] [always_inline] [_semantics "array.uninitialized_intrinsic"] @$ss27_allocateUninitializedArrayySayxG_BptBwlF : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned Array<τ_0_0>, Builtin.RawPointer) // String.init(_builtinStringLiteral:utf8CodeUnitCount:isASCII:) sil [serialized] [always_inline] [readonly] [_semantics "string.makeUTF8"] @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // default argument 1 of print(_:separator:terminator:) sil hidden_external [serialized] @$ss5print_9separator10terminatoryypd_S2StFfA0_ : $@convention(thin) () -> @owned String // default argument 2 of print(_:separator:terminator:) sil hidden_external [serialized] @$ss5print_9separator10terminatoryypd_S2StFfA1_ : $@convention(thin) () -> @owned String // print(_:separator:terminator:) sil @$ss5print_9separator10terminatoryypd_S2StF : $@convention(thin) (@guaranteed Array<Any>, @guaranteed String, @guaranteed String) -> ()
  56. sil_stage raw import Builtin import Swift import SwiftShims // main

    sil [ossa] @main : $@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>) -> Int32 { bb0(%0 : $Int32, %1 : $UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>): %2 = integer_literal $Builtin.Word, 1 // user: %4 // function_ref _allocateUninitializedArray<A>(_:) %3 = function_ref @$ss27_allocateUninitializedArrayySayxG_BptBwlF : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned Array<τ_0_0>, Builtin.RawPointer) // user: %4 %4 = apply %3<Any>(%2) : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned Array<τ_0_0>, Builtin.RawPointer) // user: %5 (%5, %6) = destructure_tuple %4 : $(Array<Any>, Builtin.RawPointer) // users: %24, %21, %7 %7 = pointer_to_address %6 : $Builtin.RawPointer to [strict] $*Any // user: %14 %8 = string_literal utf8 "Hello, World" // user: %13 %9 = integer_literal $Builtin.Word, 12 // user: %13 %10 = integer_literal $Builtin.Int1, -1 // user: %13 %11 = metatype $@thin String.Type // user: %13 // function_ref String.init(_builtinStringLiteral:utf8CodeUnitCount:isASCII:) %12 = function_ref @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // user: %13 %13 = apply %12(%8, %9, %10, %11) : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // user: %15 %14 = init_existential_addr %7 : $*Any, $String // user: %15 store %13 to [init] %14 : $*String // id: %15 // function_ref default argument 1 of print(_:separator:terminator:) %16 = function_ref @$ss5print_9separator10terminatoryypd_S2StFfA0_ : $@convention(thin) () -> @owned String // user: %17 %17 = apply %16() : $@convention(thin) () -> @owned String // users: %23, %21 // function_ref default argument 2 of print(_:separator:terminator:) %18 = function_ref @$ss5print_9separator10terminatoryypd_S2StFfA1_ : $@convention(thin) () -> @owned String // user: %19 %19 = apply %18() : $@convention(thin) () -> @owned String // users: %22, %21 // function_ref print(_:separator:terminator:) %20 = function_ref @$ss5print_9separator10terminatoryypd_S2StF : $@convention(thin) (@guaranteed Array<Any>, @guaranteed String, @guaranteed String) -> () // user: %21 %21 = apply %20(%5, %17, %19) : $@convention(thin) (@guaranteed Array<Any>, @guaranteed String, @guaranteed String) -> () destroy_value %19 : $String // id: %22 destroy_value %17 : $String // id: %23 destroy_value %5 : $Array<Any> // id: %24 %25 = integer_literal $Builtin.Int32, 0 // user: %26 %26 = struct $Int32 (%25 : $Builtin.Int32) // user: %27 return %26 : $Int32 // id: %27 } // end sil function 'main' // _allocateUninitializedArray<A>(_:) sil [serialized] [always_inline] [_semantics "array.uninitialized_intrinsic"] @$ss27_allocateUninitializedArrayySayxG_BptBwlF : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned Array<τ_0_0>, Builtin.RawPointer) // String.init(_builtinStringLiteral:utf8CodeUnitCount:isASCII:) sil [serialized] [always_inline] [readonly] [_semantics "string.makeUTF8"] @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // default argument 1 of print(_:separator:terminator:) sil hidden_external [serialized] @$ss5print_9separator10terminatoryypd_S2StFfA0_ : $@convention(thin) () -> @owned String // default argument 2 of print(_:separator:terminator:) sil hidden_external [serialized] @$ss5print_9separator10terminatoryypd_S2StFfA1_ : $@convention(thin) () -> @owned String // print(_:separator:terminator:) sil @$ss5print_9separator10terminatoryypd_S2StF : $@convention(thin) (@guaranteed Array<Any>, @guaranteed String, @guaranteed String) -> ()
  57. Structure of SIL Code SIL Module SIL Function SIL Function

    SIL Function Meta information (imported libraries, vtable, function signature,witness table …)
  58. Structure of SIL Code Converted from Swift Function SIL Function

  59. sil_stage raw import Builtin import Swift import SwiftShims %2 =

    integer_literal $Builtin.Word, 1 // user: %4 // function_ref _allocateUninitializedArray<A>(_:) %3 = function_ref @$ss27_allocateUninitializedArrayySayxG_BptBwlF : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned Array<τ_0_0>, Builtin.RawPointer) // user: %4 %4 = apply %3<Any>(%2) : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned Array<τ_0_0>, Builtin.RawPointer) // user: %5 (%5, %6) = destructure_tuple %4 : $(Array<Any>, Builtin.RawPointer) // users: %24, %21, %7 %7 = pointer_to_address %6 : $Builtin.RawPointer to [strict] $*Any // user: %14 %8 = string_literal utf8 "Hello, World" // user: %13 %9 = integer_literal $Builtin.Word, 12 // user: %13 %10 = integer_literal $Builtin.Int1, -1 // user: %13 %11 = metatype $@thin String.Type // user: %13 // function_ref String.init(_builtinStringLiteral:utf8CodeUnitCount:isASCII:) %12 = function_ref @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // user: %13 %13 = apply %12(%8, %9, %10, %11) : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // user: %15 %14 = init_existential_addr %7 : $*Any, $String // user: %15 store %13 to [init] %14 : $*String // id: %15 // function_ref default argument 1 of print(_:separator:terminator:) %16 = function_ref @$ss5print_9separator10terminatoryypd_S2StFfA0_ : $@convention(thin) () -> @owned String // user: %17 %17 = apply %16() : $@convention(thin) () -> @owned String // users: %23, %21 // function_ref default argument 2 of print(_:separator:terminator:) %18 = function_ref @$ss5print_9separator10terminatoryypd_S2StFfA1_ : $@convention(thin) () -> @owned String // user: %19 %19 = apply %18() : $@convention(thin) () -> @owned String // users: %22, %21 // function_ref print(_:separator:terminator:) %20 = function_ref @$ss5print_9separator10terminatoryypd_S2StF : $@convention(thin) (@guaranteed Array<Any>, @guaranteed String, @guaranteed String) -> () // user: %21 %21 = apply %20(%5, %17, %19) : $@convention(thin) (@guaranteed Array<Any>, @guaranteed String, @guaranteed String) -> () destroy_value %19 : $String // id: %22 destroy_value %17 : $String // id: %23 destroy_value %5 : $Array<Any> // id: %24 %25 = integer_literal $Builtin.Int32, 0 // user: %26 %26 = struct $Int32 (%25 : $Builtin.Int32) // user: %27 // _allocateUninitializedArray<A>(_:) sil [serialized] [always_inline] [_semantics "array.uninitialized_intrinsic"] @$ss27_allocateUninitializedArrayySayxG_BptBwlF : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned Array<τ_0_0>, Builtin.RawPointer) // String.init(_builtinStringLiteral:utf8CodeUnitCount:isASCII:) sil [serialized] [always_inline] [readonly] [_semantics "string.makeUTF8"] @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // default argument 1 of print(_:separator:terminator:) sil hidden_external [serialized] @$ss5print_9separator10terminatoryypd_S2StFfA0_ : $@convention(thin) () -> @owned String // default argument 2 of print(_:separator:terminator:) sil hidden_external [serialized] @$ss5print_9separator10terminatoryypd_S2StFfA1_ : $@convention(thin) () -> @owned String // print(_:separator:terminator:) sil @$ss5print_9separator10terminatoryypd_S2StF : $@convention(thin) (@guaranteed Array<Any>, @guaranteed String, @guaranteed String) -> () // main sil [ossa] @main : $@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>) -> Int32 { bb0(%0 : $Int32, %1 : $UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>): return %26 : $Int32 // id: %27 } // end sil function 'main'
  60. … // main sil [ossa] @main : $@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>)

    -> Int32 { bb0(%0 : $Int32, %1 : $UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>): return %26 : $Int32 // id: %27 } // end sil function 'main'
  61. “main” Function of Swift print("Hello, World") hello.swift Body code is

    surrounded by Main function Main function works as entry point like other languages
  62. Structure of SIL Code SIL Function SIL Basic Block SIL

    Basic Block SIL Basic Block SIL Basic Block SIL Basic Block
  63. Structure of SIL Code SIL Function SIL Basic Block SIL

    Basic Block SIL Basic Block SIL Basic Block SIL Basic Block
  64. Structure of SIL Code SIL Basic Block Basic Block is

    kind of Scope in Swift Function Increased as Conditional Branches of program
  65. … // main sil [ossa] @main : $@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>)

    -> Int32 { bb0(%0 : $Int32, %1 : $UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>): return %26 : $Int32 // id: %27 } // end sil function 'main'
  66. … // main sil [ossa] @main : $@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>)

    -> Int32 { bb0(%0 : $Int32, %1 : $UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>): return %26 : $Int32 // id: %27 } // end sil function 'main' bb represents Basic Block
  67. … // main sil [ossa] @main : $@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>)

    -> Int32 { bb0(%0 : $Int32, %1 : $UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>): return %26 : $Int32 // id: %27 } // end sil function 'main' Basic Block is increased as Conditional Branches bb1 …: … bb represents Basic Block if, while, switch, … in Swift
  68. Structure of SIL Code SIL Basic Block SIL Instruction SIL

    Instruction SIL Instruction SIL Instruction SIL Instruction
  69. Structure of SIL Code Converted from Swift Code SIL Instruction

  70. %2 = integer_literal $Builtin.Word, 1 // user: %4 // function_ref

    _allocateUninitializedArray<A>(_:) %3 = function_ref @$ss27_allocateUninitializedArrayySayxG_BptBwlF … %4 = apply %3<Any>(%2) : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned …) … // main sil [ossa] @main : $@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>) -> Int32 { bb0(%0 : $Int32, %1 : $UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>): return %26 : $Int32 // id: %27 } // end sil function 'main'
  71. %2 = integer_literal $Builtin.Word, 1 // user: %4 // function_ref

    _allocateUninitializedArray<A>(_:) %3 = function_ref @$ss27_allocateUninitializedArrayySayxG_BptBwlF … %4 = apply %3<Any>(%2) : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned …) … // main sil [ossa] @main : $@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>) -> Int32 { bb0(%0 : $Int32, %1 : $UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>): return %26 : $Int32 // id: %27 } // end sil function 'main'
  72. Structure of SIL Code Converted from Swift Code SIL Instruction

    Conformed to Static Single Assignment format
  73. Static Single Assignment (SSA) Each variable cannot be assigned value

    twice %2 = integer_literal $Builtin.Word, 1 %3 = function_ref @$ss27_allocateUninitializedArrayySayxG_BptBwlF … %4 = apply %3<Any>(%2) : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned …) A left value starts from % is variable Instruction with assigning is %n = instruction
  74. Why converting SSA? Very easy to track how code is

    using each variable /// Body of SIL Function // A: integer variable %2 = integer_literal %3 = function_ref Int.init(:) %4 = apply %3(%2) // B: integer variable %5 = integer_literal %6 = function_ref Int.init(:) %7 = apply %5(%6) return %7 // return B
  75. Why converting SSA? Very easy to track how code is

    using each variable /// Body of SIL Function // A: integer variable %2 = integer_literal %3 = function_ref Int.init(:) %4 = apply %3(%2) // B: integer variable %5 = integer_literal %6 = function_ref Int.init(:) %7 = apply %5(%6) return %7 // return B Removing Dead(not used) Code of Function
  76. Why converting SSA? Very easy to track how code is

    using each variable /// Body of SIL Function // A: integer variable %2 = integer_literal %3 = function_ref Int.init(:) %4 = apply %3(%2) // B: integer variable %5 = integer_literal %6 = function_ref Int.init(:) %7 = apply %5(%6) return %7 // return B ← return and %7 should be marked as Live (used) Code
  77. Why converting SSA? Very easy to track how code is

    using each variable /// Body of SIL Function // A: integer variable %2 = integer_literal %3 = function_ref Int.init(:) %4 = apply %3(%2) // B: integer variable %5 = integer_literal %6 = function_ref Int.init(:) %7 = apply %5(%6) return %7 // return B ← return and %7 should be marked as Live (used) Code
  78. Why converting SSA? Very easy to track how code is

    using each variable /// Body of SIL Function // A: integer variable %2 = integer_literal %3 = function_ref Int.init(:) %4 = apply %3(%2) // B: integer variable %5 = integer_literal %6 = function_ref Int.init(:) %7 = apply %5(%6) return %7 // return B ← return and %7 should be marked as Live (used) Code ← %5 and %6 should be marked as Live (used) Code
  79. Why converting SSA? Very easy to track how code is

    using each variable /// Body of SIL Function // A: integer variable %2 = integer_literal %3 = function_ref Int.init(:) %4 = apply %3(%2) // B: integer variable %5 = integer_literal %6 = function_ref Int.init(:) %7 = apply %5(%6) return %7 // return B ← return and %7 should be marked as Live (used) Code ← %5 and %6 should be marked as Live (used) Code
  80. Why converting SSA? Very easy to track how code is

    using each variable /// Body of SIL Function // A: integer variable %2 = integer_literal %3 = function_ref Int.init(:) %4 = apply %3(%2) // B: integer variable %5 = integer_literal %6 = function_ref Int.init(:) %7 = apply %5(%6) return %7 // return B ← return and %7 should be marked as Live (used) Code ← %5 and %6 should be marked as Live (used) Code ← Marked as Dead Code because referred by return
  81. Why converting SSA? Very easy to track how code is

    using each variable /// Body of SIL Function // A: integer variable %2 = integer_literal %3 = function_ref Int.init(:) %4 = apply %3(%2) // B: integer variable %5 = integer_literal %6 = function_ref Int.init(:) %7 = apply %5(%6) return %7 // return B Searching for variable proceeds by Unidirectional flow
  82. Dead Code Elimination Constant Propagation Why converting SSA? Very easy

    to track how code is using each variable
  83. Structure of SIL Code Converted from Swift Code SIL Instruction

    The Code Style is conformed to SSA Reference: docs/SIL.rst in apple/swift
  84. Recap of SIL raw SIL and canonical SIL SIL consists

    of Module, Function, Basic Block and Instruction SIL is conformed to Single Static Assignment Format
  85. Agenda Why need to learn Swift Compiler (Optimizer)? Basis of

    Swift Compiler Swift Intermediate Language (SIL) SIL Optimizer
  86. SIL Optimizer

  87. How SIL Optimizer works

  88. raw to canonical raw SIL canonical SIL

  89. raw to canonical raw SIL canonical SIL SIL Code Optimization

  90. raw to canonical raw SIL canonical SIL SIL Optimizer SIL

    Code Optimization
  91. Role of SIL Optimizer SIL Optimizer has two important roles

    on Compiler Phase Optimization SIL Code Diagnostic SIL Code
  92. Role of SIL Optimizer SIL Optimizer has two important roles

    on Compiler Phase SIL Code Diagnostic SIL Code Optimization
  93. by SIL Optimizer Optimization specialized for Swift Language Optimization Generic

    Specialization Witness and VTable Devirtualization etc
  94. Role of SIL Optimizer SIL Optimizer has two important roles

    on Compiler Phase SIL Code SIL Code Diagnostic Optimization
  95. by Compiler Each phase of Compiler diagnoses your Swift Code

    Checking Grammar on Parser Phase (to AST) Checking Type on Sema Phase (to typed AST) ??? on SIL Optimizer Phase (to canonical SIL) Compiler will show error if diagnostic fails Diagnostic
  96. func wrongReturnType() -> String { return 2020 } wrong-type.swift by

    Compiler Diagnostic
  97. AST AST (Typed) SIL IR (LLVM) App Diagnostic of Type

    Check
  98. AST AST (Typed) SIL IR (LLVM) App Diagnostic of Type

    Check OK NG error: cannot convert return expression of type 'Int' to return type 'String'
  99. func wrongReturnType() -> String { return 2020 } wrong-type.swift Diagnostic

    of return
  100. func wrongReturnType() -> String { } wrong-type.swift Diagnostic of return

  101. SIL AST AST (Typed) IR (LLVM) App OK OK OK

    Diagnostic of return
  102. raw SIL canonical SIL Diagnostic in SIL Optimizer NG error:

    missing return in a function expected to return 'String' SIL Code Optimization
  103. Diagnostic of return func wrongReturnType() -> String { } no-return.swift

    … // some code fatalError()
  104. AST AST (Typed) SIL IR (LLVM) App OK Diagnostic of

    return OK OK OK OK No error by fatalError
  105. Examples Diagnostic of Grammar by Parser Diagnostic of validation no-return

    by SIL Optimizer Diagnostic Diagnostic of Overflow by SIL Optimizer Diagnostic of Type (of return) by Sema etc
  106. Role of SIL Optimizer SIL Optimizer has two important role

    on Compiler Phase Optimizing SIL Code SIL Code Diagnostic Guaranteeing safety as other roles of each phase
  107. raw SIL raw SIL canonical SIL SIL Optimizer Optimizing

  108. raw SIL raw SIL canonical SIL Optimizing Many Passes optimize

    your code in order Pass Pass Pass Pass Each Pass has role for optimization and diagnostic
  109. Example of Pass in SIL Optimizer Dead Code Elimination Constant

    Propagation Memory Promotion Other Diagnostic etc
  110. Pass Pipeline has information that which Pass must be called

    Pass Pipeline Pass Pass Pass Pass SIL Optimizer calls only registered Pass on Pipeline is Pass Pipeline
  111. How Pass PipeLine is built Pass Pass Pass Pass Pipeline

    is built from optimization level of Compiler -Onone : Minimum optimization for debugging situation -O : Optimization for production code -Osize : Optimization for reducing size than performance
  112. Which Pass is called or not? lib/SILOptimizer/PassManager/PassPipeline.cpp https://github.com/apple/swift

  113. Which Pass is called or not? lib/SILOptimizer/PassManager/PassPipeline.cpp addMandatoryDiagnosticOptPipeline getOnonePassPipeline etc

  114. List of Passes include/swift/SILOptimizer/PassManager/Passes.def https://github.com/apple/swift

  115. Recap of SIL Optimizer SIL Optimizer’s roles are Optimization and

    Diagnostic raw SIL is optimized by Passes in SIL Optimizer Pipeline has information which Pass must be called Pass Pipeline is built by optimization level
  116. SIL Optimizer

  117. More Deeper Dive into SIL Optimizer

  118. Two kinds of Pass For SIL Module For SIL Function

    Run by each SIL Module Run by each SIL Function
  119. Two kinds of Pass For SIL Module For SIL Function

    Dead Function Elimination Global Variable Optimization Dead Code Elimination Alloc Box to Stack etc etc
  120. How to know what kind of Pass Passes are developed

    by C++ Class in Compiler Code Each Pass inherits two kinds of Bass Class SILModuleTransform SILFunctionTransform
  121. How to know what kind of Pass For SIL Module

    For SIL Function Dead Function Elimination Global Variable Optimization Dead Code Elimination Alloc Box to Stack etc etc
  122. How to know what kind of Pass Dead Function Elimination

    class SILDeadFuncElimination : public SILModuleTransform { … } lib/SILOptimizer/IPO/DeadFunctionElimination.cpp
  123. How to know what kind of Pass Dead Code Elimination

    class DCE : public SILFunctionTransform { … } lib/SILOptimizer/Transforms/DeadCodeElimination.cpp
  124. Pass’s implementation Making Class from SILModule(Function)Transform Implementing run() as Entry

    Point
  125. Reading Pass Code For example, let’s read AssumeSingleThreaded Pass The

    smallest Pass in Swift Compiler Optimizes program specialized for Single Thread
  126. lib/SILOptimizer/Transforms/AssumeSingleThreaded.cpp class AssumeSingleThreaded : public swift::SILFunctionTransform { /// The entry

    point to the transformation. void run() override { /// Checking option … for (auto &BB : *getFunction()) { for (auto &I : BB) { if (auto RCInst = dyn_cast<RefCountingInst>(&I)) RCInst->setNonAtomic(); } } /// Post treatment } };
  127. lib/SILOptimizer/Transforms/AssumeSingleThreaded.cpp class AssumeSingleThreaded : public swift::SILFunctionTransform { /// The entry

    point to the transformation. void run() override { /// Checking option … for (auto &BB : *getFunction()) { for (auto &I : BB) { if (auto RCInst = dyn_cast<RefCountingInst>(&I)) RCInst->setNonAtomic(); } } /// Post treatment } };
  128. lib/SILOptimizer/Transforms/AssumeSingleThreaded.cpp class AssumeSingleThreaded : public swift::SILFunctionTransform { /// The entry

    point to the transformation. void run() override { /// Checking option … for (auto &BB : *getFunction()) { for (auto &I : BB) { if (auto RCInst = dyn_cast<RefCountingInst>(&I)) RCInst->setNonAtomic(); } } /// Post treatment } };
  129. Reading Pass Code Easy to understand if we know structure

    of SIL Code SIL Module SIL Function SIL Basic Block SIL Instruction
  130. lib/SILOptimizer/Transforms/AssumeSingleThreaded.cpp class AssumeSingleThreaded : public swift::SILFunctionTransform { /// The entry

    point to the transformation. void run() override { /// Checking option … for (auto &BB : *getFunction()) { for (auto &I : BB) { if (auto RCInst = dyn_cast<RefCountingInst>(&I)) RCInst->setNonAtomic(); } } /// Post treatment } };
  131. lib/SILOptimizer/Transforms/AssumeSingleThreaded.cpp class AssumeSingleThreaded : public swift::SILFunctionTransform { /// The entry

    point to the transformation. void run() override { /// Checking option … for (auto &I : BB) { if (auto RCInst = dyn_cast<RefCountingInst>(&I)) RCInst->setNonAtomic(); } /// Post treatment } }; for (auto &BB : *getFunction()) { }
  132. Reading Pass Code getFunction returns current scanning SILFunction for (auto

    &BB : *getFunction()) { } … SILFunction can be treated as SILBasicBlock Collection
  133. lib/SILOptimizer/Transforms/AssumeSingleThreaded.cpp class AssumeSingleThreaded : public swift::SILFunctionTransform { /// The entry

    point to the transformation. void run() override { /// Checking option … for (auto &BB : *getFunction()) { for (auto &I : BB) { if (auto RCInst = dyn_cast<RefCountingInst>(&I)) RCInst->setNonAtomic(); } } /// Post treatment } }; for (auto &BB : *getFunction()) { }
  134. lib/SILOptimizer/Transforms/AssumeSingleThreaded.cpp class AssumeSingleThreaded : public swift::SILFunctionTransform { /// The entry

    point to the transformation. void run() override { /// Checking option … for (auto &BB : *getFunction()) { if (auto RCInst = dyn_cast<RefCountingInst>(&I)) RCInst->setNonAtomic(); } /// Post treatment } }; for (auto &I : BB) { }
  135. Reading Pass Code } … for (auto &I : BB)

    { SILBasicBlock is SILInstruction Collection Scanning SILInstruction from top
  136. lib/SILOptimizer/Transforms/AssumeSingleThreaded.cpp class AssumeSingleThreaded : public swift::SILFunctionTransform { /// The entry

    point to the transformation. void run() override { /// Checking option … for (auto &BB : *getFunction()) { if (auto RCInst = dyn_cast<RefCountingInst>(&I)) RCInst->setNonAtomic(); } /// Post treatment } }; for (auto &I : BB) { }
  137. lib/SILOptimizer/Transforms/AssumeSingleThreaded.cpp class AssumeSingleThreaded : public swift::SILFunctionTransform { /// The entry

    point to the transformation. void run() override { /// Checking option … for (auto &BB : *getFunction()) { if (. ) RCInst->setNonAtomic(); } /// Post treatment } }; for (auto &I : BB) { } auto RCInst = dyn_cast<RefCountingInst>(&I)
  138. Reading Pass Code Checking what kind of SILInstruction by casting

    RefCountingInst is instruction related to ARC auto RCInst = dyn_cast<RefCountingInst>(&I)
  139. Reading Pass Code If we want to check instruction is

    return or not Check type-cast by ReturnInst auto ReturnInst = dyn_cast<ReturnInst>(&I)
  140. lib/SILOptimizer/Transforms/AssumeSingleThreaded.cpp class AssumeSingleThreaded : public swift::SILFunctionTransform { /// The entry

    point to the transformation. void run() override { /// Checking option … for (auto &BB : *getFunction()) { if (. ) RCInst->setNonAtomic(); } /// Post treatment } }; for (auto &I : BB) { } auto RCInst = dyn_cast<RefCountingInst>(&I)
  141. lib/SILOptimizer/Transforms/AssumeSingleThreaded.cpp class AssumeSingleThreaded : public swift::SILFunctionTransform { /// The entry

    point to the transformation. void run() override { /// Checking option … for (auto &BB : *getFunction()) { for (auto &I : BB) { if (auto RCInst = dyn_cast<RefCountingInst>(&I)) } } /// Post treatment } }; RCInst->setNonAtomic();
  142. Reading Pass Code Setting Reference Count instruction as non Atomic

    RCInst->setNonAtomic();
  143. What AssumeSingleThreaded? Scanning SIL Instruction related to Reference Count Marking

    Reference Count Instruction as non Atomic Called by each SIL Function
  144. Now, you can read Swift Compiler Code!

  145. Using docs/SIL.rst for reference of SIL Instruction Understanding C++ and

    LLVM for more deep dive Recap to read SIL Optimizer Code Understanding structure of SIL Code
  146. For More your learning Compiler

  147. Build Swift Compiler! You can clone from https://github.com/apple/swift It requires

    more than 60 GB ⚠ to build
  148. SIL Optimizer may have bugs which not tracked There is

    many chance to contribute! Contribute to Swift Compiler!
  149. Talk/Write about Swift Compiler! Swift Compiler is difficult topic Your

    talk/article would be helpful for next learner!
  150. Thank you! Twitter: _ _ _ freddi _ _ _

    Give me a feed back and question!