Upgrade to Pro — share decks privately, control downloads, hide ads and more …

How to develop SIL Optimizer in Swift Language

How to develop SIL Optimizer in Swift Language

1405a601755e5fcbfdc93a2560368bb1?s=128

freddi(Yuki Aki)

July 30, 2021
Tweet

Transcript

  1. How to develop SIL Op/mizer in Swi5 Language Θ͍Θ͍swi$c #29

    30th/July/2021 @___freddi___ 1
  2. ຊ೔ͷ࿩ • ͓΋ͪ͞Μͷ࿩ͷଓ͖ • SIL Op(mizer ͷ Pass ͕ Swi2

    Ͱॻ͚ΔΑ͏ʹͳͬͨͱ͍͏࿩ 2
  3. ͪΐͬͱ෮श ~ SIL • Swi% Intermediate Language ͷུ • Swi%

    ͷιʔείʔυΛίϯύΠϧ͢Δͱ͖ʹܦΔதؒݴޠ • ͜͜ͰSwi%ίϯύΠϥʹΑΔ(ಛ༗ͷ)࠷దԽ͕૸Δ 3
  4. ͪΐͬͱ෮श ~ SIL • print("Hello World!") ͷ SIL (࠷దԽޙ) ͷจࣈྻϦςϥϧ

    Λ String ͷΠχγϟϥΠβʹͿͬ͜ΉίʔυͷΈΛൈਮ %8 = string_literal utf8 "Hello, World!" // user: %13 %9 = integer_literal $Builtin.Word, 13 // 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_builtinStringLiteral ... -> @owned String // user: %13 %13 = apply %12(%8, %9, %10, %11) : ... -> @owned String // user: %15 %14 = init_existential_addr %7 : $*Any, $String // user: %15 store %13 to %14 : $*String // id: %15 4
  5. ͪΐͬͱ෮श ~ SIL ͷߏ଄(1) • ·ͣɺSIL ͸େ͖͍΋ͷ͔ΒҎԼͷߏ଄ʹ෼͚ΒΕΔ • SIL Module

    • SIL Func/on • SIL Basic Block • SIL Instruc/on • ࠓճ͸খ͍͞ํ͔Βݟ͍ͯ͘ 5
  6. ͪΐͬͱ෮श ~ SIL ͷߏ଄(2) SIL Instruc/on • SIL Instruc,on •

    ௚༁͢Δͱ "SIL໋ྩ" ͰɺείʔϓதͷҰߦҰߦͷίʔυΛද͢ • ຆͲ͕ %(id) = (instruc,on) ͱ͍͏ϑΥʔϚοτ • ม਺໊ͷ୅ΘΓʹ id ͱ͍͏΋ͷΛ࢖͏ // ม਺ %8 ʹ จࣈྻϦςϥϧΛೖΕΔ %8 = string_literal utf8 "Hello, World!" // user: %13 • ίϝϯτͷ // user: %(id) ͱ͸ͦͷinstruc*onΛར༻͢ΔidΛදͯ͘͠ΕΔ • ࢖͍ͬͯΔ΋ͷ͕ͳ͍ɾલड़ͷϑΥʔϚοτʹैͬͯͳ͍ͳΒ // id: %(id) ͱͦͷ instruc*on ͷ id Λද ͯ͘͠ΕΔ 6
  7. ͪΐͬͱ෮श ~ SIL ͷߏ଄(3) SIL Basic Block • SIL Basic

    Block • bb(൪߸): ͱ͍͏ϑΥʔϚοτ͔Β࢝·Δ instruc6on ͷմΛࣔ͢ • είʔϓ ({ } ʹғ·Εͨίʔυ) ͱߟ͑Δͱྑ͍ // 0൪ basic block bb0: ... %8 = string_literal utf8 "Hello, World!" // user: %13 ... • SIL Basic Block ͸ instruc2on ͷίϨΫγϣϯͱࢥ͏ͱࠓޙͷ࿩͕Θ͔Γ΍͍͢ 7
  8. ͪΐͬͱ෮श ~ SIL ͷߏ଄(4) SIL Func-on • SIL Func*on •

    ݴΘͣ΋͕ͳؔ਺ • ̍ͭҎ্ͷ basic block ͔Βߏ੒͞ΕΔ • ̍ͭͷSwi3ͷؔ਺͸ ̍ͭͷSIL Func*on ʹม׵͞ΕΔ // mainؔ਺ sil @main : $@convention(c) (Int32, ...) -> Int32 { bb0: ... %8 = string_literal utf8 "Hello, World!" // user: %13 ... • SIL Func*on ͸ basic block ͷίϨΫγϣϯͱࢥ͏ͱࠓޙͷ࿩͕Θ͔Γ΍͍͢ 8
  9. ͪΐͬͱ෮श ~ SIL ͷߏ଄(5) mainؔ਺ • ิ଍ͱͯ͠ɺͨͱ͑ swi&ϑΝΠϧʹؔ਺ʹΛॻ͍ͯͳͯ͘΋ίϯύΠϧ࣌ඞͣੜ੒͞ ΕΔ func+onɹ͕͋Δ

    • ੜ੒͞ΕΔͷ͸ main ؔ਺ • Cݴޠ ͷ mainؔ਺ͱػೳ΋ಉ͡ɻϓϩάϥϜͷΤϯτϦϙΠϯτ • swi&ϑΝΠϧʹ௚઀ॻ͍ͨίʔυ͕ mainؔ਺ʹғΘΕͯݺ͹ΕΔ // mainؔ਺ sil @main : $@convention(c) (Int32, ...) -> Int32 { ... 9
  10. ͪΐͬͱ෮श ~ SIL ͷߏ଄(6) SIL Module • ίϯύΠϧ͞ΕͨSILϑΝΠϧશମ • άϩʔόϧม਺΍import͞ΕͨϞδϡʔϧɺstructɾclassͷఆٛɺfunc2on

    ͳͲ͕ݱΕΔ // sil_stageɹਖ਼ମ͸࣍ͷϖʔδݟΔͱΘ͔Δ͚Ͳ // ͜ͷSIL͸ canonical SIL ͩΑͬͯҙຯ sil_stage canonical import Builtin ... sil @main : $@convention(c) (Int32, ...) -> Int32 { bb0: ... %8 = string_literal utf8 "Hello, World!" // user: %13 ... 10
  11. ͪΐͬͱ෮श ~ SIL Op(mizer (1) • SILΛ࠷దԽ͢ΔίϯύΠϥͷ࠷దԽϑΣʔζ • SIL Op(mizerͷதʹ͋Δ

    Pass ͱ͍͏Ϟδϡʔϧ͕ͦΕͧΕ࠷దԽͷ໾ׂΛ͍࣋ͬͯΔ • ͦͷ Pass ͷద༻ͷॱ൪Λ૊ΈཱͯͯʢPass Pipelineʣ࣮ࡍʹSILΛ࠷దԽ͢ΔϑΣʔζ • raw SIL ͕࠷దԽલͷSILͰ canonical SIL ͕࠷దԽޙ • ্ͷਤͰݴ͑͹ɺ྘ͷ໼ҹ͕ Pipeline ͱߟ͑ͯ΋Β͑Δͱ • ࠷దԽPass͸C++Ͱॻ͔Ε͍ͯΔʢ͍ͨʣ 11
  12. ͪΐͬͱ෮श ~ SIL Op(mizer (2) Pass ͷछྨ • Pass ʹ͸2छྨ͋Δ

    • Module Pass • Func0on Pass • ͲͪΒ΋উखʹ๻͕ݺΜͰΔ͚ͩͳͷͰ஫ҙ • Module or Func0on͝ͱʹൃಈ͢ΔPass͔ɺͱ͍͏ҧ͍ͷΈ 12
  13. ͪΐͬͱ෮श ~ SIL Op(mizer (3) C++ ͷ Pass ΛಡΉ •

    ࣮ࡍʹͲ͏͍͏ Pass ͕͋Δ͔ಡΜͰΈΑ͏ 13
  14. ͪΐͬͱ෮श ~ SIL Op(mizer (4) C++ ͷ Pass ΛಡΉ •

    AssumeSingleThreaded • ஌ͬͯΔݶΓ࠷খͰಡΈ΍͍͢ Pass 14
  15. ͪΐͬͱ෮श ~ SIL Op(mizer (5) C++ ͷ Pass ΛಡΉ class

    AssumeSingleThreaded : public swift::SILFunctionTransform { /// The entry point to the transformation. void run() override { if (!getOptions().AssumeSingleThreaded) return; for (auto &BB : *getFunction()) { for (auto &I : BB) { if (auto RCInst = dyn_cast<RefCountingInst>(&I)) RCInst->setNonAtomic(); } } invalidateAnalysis(SILAnalysis::InvalidationKind::Instructions); } }; • from: lib/SILOp1mizer/Transforms/AssumeSingleThreaded.cpp 15
  16. ͪΐͬͱ෮श ~ SIL Op(mizer (6) C++ ͷ Pass ΛಡΉ •

    ॱʹݟ͍ͯ͘ • SILFunc)onTransform ʹ४ڌ͍ͯ͠Δ͕ɺ͜ΕͰ͜ͷ Pass ͸ func)on ͝ͱʹൃಈ͞Ε Δ • SILModuleTransform ʹ͢Δͱ Module ͝ͱʹൃಈ͞ΕΔ • ΤϯτϦϙΠϯτͰ͋Δ run ؔ਺ΛΦʔόʔϥΠυͯ͠ಈ࡞Λهड़͍ͯ͘͠ class AssumeSingleThreaded : public swift::SILFunctionTransform { /// The entry point to the transformation. void run() override { ... 16
  17. ͪΐͬͱ෮श ~ SIL Op(mizer (7) C++ ͷ Pass ΛಡΉ •

    getOptions Ͱ -assume-single-threaded Φϓγϣϯ͕෇͍ͯΔ͔ ݟΔ • ͍ͭͯͳ͔ͬͨΒɺ࠷దԽΛ͠ͳ͍ ... /// The entry point to the transformation. void run() override { if (!getOptions().AssumeSingleThreaded) return; ... 17
  18. ͪΐͬͱ෮श ~ SIL Op(mizer (8) C++ ͷ Pass ΛಡΉ •

    ͕͜͜৺ଁ෦෼ • ·ͣɺgetFunction Ͱ SILFunction ܕͷΦϒδΣΫτΛऔΔ • SILFunction ܕͷΦϒδΣΫτ ͸ SILBasicBlock ͷίϨΫγϣϯͳͷͰͦΕΛ forͰͿΜճ֤ͯ͠ basic block Λ ݟΔ • BB ͸ basic block ͷ͜ͱ ... for (auto &BB : *getFunction()) { // ίίͷઆ໌ for (auto &I : BB) { if (auto RCInst = dyn_cast<RefCountingInst>(&I)) RCInst->setNonAtomic(); } } invalidateAnalysis(SILAnalysis::InvalidationKind::Instructions); ... 18
  19. ͪΐͬͱ෮श ~ SIL Op(mizer (9) C++ ͷ Pass ΛಡΉ •

    ·ͨɺSILBasicBlock ܕͷΦϒδΣΫτ ͸ SILInstruction ͷίϨ ΫγϣϯͳͷͰͦΕΛ for ͰͿΜճ֤ͯ͠ instruc*on ΛݟΔ ... for (auto &BB : *getFunction()) { for (auto &I : BB) { // ίίͷઆ໌ if (auto RCInst = dyn_cast<RefCountingInst>(&I)) RCInst->setNonAtomic(); } } invalidateAnalysis(SILAnalysis::InvalidationKind::Instructions); ... 19
  20. ͪΐͬͱ෮श ~ SIL Op(mizer (10) C++ ͷ Pass ΛಡΉ •

    ࠓݟͯΔ SILInstruction ͕ͲΜͳ instruc*on ͔͸μ΢ϯΩϟετ͢Ε͹Θ͔Δ • ͜͜Ͱ͸ɺϦϑΝϨϯεΧ΢ϯτؔ܎ͷ instruc*on ͔Ͳ͏͔ΛνΣοΫ͍ͯ͠Δ • RefCountingInst ΁ͷΩϟετνΣοΫɻinstruc*on ͷछྨ͸ ܕͰදݱ • dyn_cast ͱ͍͏ಛघͳؔ਺Λ࢖͏ ... for (auto &BB : *getFunction()) { for (auto &I : BB) { if (auto RCInst = dyn_cast<RefCountingInst>(&I)) // ίίͷઆ໌ RCInst->setNonAtomic(); } } invalidateAnalysis(SILAnalysis::InvalidationKind::Instructions); ... 20
  21. ͪΐͬͱ෮श ~ SIL Op(mizer (11) C++ ͷ Pass ΛಡΉ •

    ΩϟετνΣοΫ͕௨ͬͨΒɺͦͷ insturcion Λ non atomic ʹ͢Δ • ͦͯ͠ invalidateAnalysis ΛಡΜͰPassͷϚωʔδϟʹมߋ͕͋ͬͨ͜ͱ Λ஌ΒͤΔ ... for (auto &BB : *getFunction()) { for (auto &I : BB) { if (auto RCInst = dyn_cast<RefCountingInst>(&I)) RCInst->setNonAtomic(); // ίίͷઆ໌ } } invalidateAnalysis(SILAnalysis::InvalidationKind::Instructions); // ίίͷઆ໌ ... 21
  22. ͪΐͬͱ෮श ~ SIL Op(mizer (12) C++ ͷ Pass ΛಡΉ •

    ͜ͷ Pass Λద༻͢Δͱ͜Μͳײ͡ʹͳΔ • લ strong_release %4 : $Neko • ޙ strong_release [nonatomic] %4 : $Neko • ͳͥϦϑΝϨϯεΧ΢ϯτ͚ͩͳͷ͔ෆ໌ 22
  23. ͪΐͬͱ෮श ~ SIL Op(mizer (13) Pass ͷొ࿥ํ๏ • ࣗલͰcppϑΝΠϧΛ༻ҙͨ͠ͳΒ lib/SILOp-mizer/Transforms/CMakeLists.txt

    ʹهࡌ • include/swiA/SILOp-mizer/PassManager/Passes.def ʹ ↓ Έ͍ͨͳهड़Λॻ͘ PASS({C++ͷPassͷΫϥε໊}, "sil-{C++ͷPassͷΫϥε໊}", "ͳΜ͔ద౰ͳઆ໌") • ↑ ʹΑͬͯ create{C++ͷPassͷΫϥε໊} ͱ͍͏ؔ਺ͷ࣮૷Λཁٻ͞ΕΔͷͰɺ࣮૷͢Δ • ࡞ͬͨPassΫϥεͷΦϒδΣΫτΛฦͤ͹ྑ͍ • lib/SILOp0mizer/PassManager/PassPipeline.cpp ͰͦͷPass͕ݺ͹ΕΔΑ͏ʹιʔεΛॻ͖׵͑Δ • Passes.def ΁ͷ↑ͷॻ͖׵͑ʹΑͬͯɺadd{C++ͷPassͷΫϥε໊} ͱ͍͏໊લͷؔ਺͕ SILPassPipelinePlan ܕʹੜ͑ΔͷͰͦΕΛ࢖͏ 23
  24. ͪΐͬͱ෮श ~ ΋ͬͱ෮श͍ͨ͠ਓ͸ • ๻ͷNSSpainͰ࿩ͨ͠಺༰Λݟ͍ͯͩ͘͞ɻ(ӳޠ) • Swi+ Op.mizing (at Compiler

    World) • ͋ͱ Swi+ckaigi ͷొஃ΋ࢀߟʹͳΓ·͢ • SILOp.mizerΛࣗ෼Ͱ࡞ͬͯ༡ΜͰݟΔ @freddi-kit 24
  25. ΍ͬͱຊ୊ 25

  26. Pass ͕ Swi( Ͱ΋ॻ͚ΔΑ͏ʹͳΓ·ͨ͠ • libswift ͱ͍͏ Swi&ίϯύΠϥͷιʔεʹଘࡏ͢Δ Swi& Package

    Λར༻ͯ͠։ൃͰ͖ΔΑ͏ʹͳΓ·ͨ͠ • ֘౰PR: #37398 26
  27. AssumeSingleThreaded Λ Swi2 Ҡ২͠Α͏ • ࢼ͠ʹ AssumeSingleThreaded Λ Swi3 ʹҠ২ͯ͠ΈΔ

    27
  28. ·ͣ͸͡Ίʹ (1) swi(ͷϏϧυ • swi% ίϯύΠϥΛ clone ͯ͠ build ͢Δ

    • apple/swi% • υΩϡϝϯτʹΑΔͱɺ libswi%Λ࢖͏ʹ͸ɺϏϧυΦϓγϣϯ ʹ --libswift ͕ඞཁ 28
  29. ·ͣ͸͡Ίʹ (2) swi(ͷϏϧυ • ҎԼͰ΍ͬͯΈΔʢxcodeproj ͷੜ੒Λߦ͏ʣ $ utils/build-script --xcode --release

    --skip-build-benchmarks \ --skip-ios --skip-watchos --skip-tvos --swift-darwin-supported-archs x86_64 \ --sccache --libswift 29
  30. ·ͣ͸͡Ίʹ (3) swi(ͷϏϧυ • Τϥʔൃੜ... CMake Error in libswift/CMakeLists.txt: The

    custom command generating /Users/freddi/swift-source/build/Xcode-ReleaseAssert/swift-macosx-x86_64/libswift/SIL.o is attached to multiple targets: libswift libswift-SIL.o but none of these is a common dependency of the other(s). This is not allowed by the Xcode "new build system". 30
  31. ·ͣ͸͡Ίʹ (4) swi(ͷϏϧυ • ninja Ͱ΍ͬͯΈΔ $ utils/build-script --release --skip-build-benchmarks

    \ # ͖ͬ͞ͱൺֱͯ͠ίίͷ --xcode ͕ফ͑ͯΔ --skip-ios --skip-watchos --skip-tvos --swift-darwin-supported-archs x86_64 \ --sccache --libswift • ͜Ε͸͍͚ͨ 31
  32. libswi&/Package.swi& Λ։͘ • libswi' ͸ Package.swi' ͕༻ҙ͞Ε͍ͯͯɺ͜ΕΛ։͘ͱ Xcode ͕։͘ •

    libswi'/Package.swi' • Xcode Ͱ։ൃͰ͖·͢ • (ଟ෼) swi' Ϗϧυ͠ͳͯ͘΋ Xcode্Ͱ͸ build ͸Ͱ͖Δͱࢥ͏ 32
  33. Source/Func*onPasses ʹ AssumeSingleThreadedSwi8.swi8 Λ௥Ճ • AssumeSingleThreadedSwift.swift Λ Source/ Func,onPasses ҎԼʹ௥Ճ͢Δ

    • ݱ࣌఺ͰԿ΋ॻ͔Ε͍ͯͳ͍ 33
  34. AssumeSingleThreadedSwi1.swi1 ʹۭͷ Pass Λ௥Ճ • ΦϦδφϧͷ AssumeSingleThreaded ͸ SILFunc6onTransform Λܧ

    ঝ͍ͯ͠Δ • ͳͷͰɺ·ͣ͸ಉ͡ಇ͖Λ͢Δ FunctionPass ͰۭͷPassΛ࡞Δ • Ϋϩʔδϟ಺ʹ࠷దԽͷΞϧΰϦζϜΛॻ͘ import SIL import SILBridging let assumeSingleThreadedSwift = FunctionPass(name: "sil-assume-single-threaded-swift") { function, context in } 34
  35. ࠶ܝ AssumeSingleThreaded.cpp class AssumeSingleThreaded : public swift::SILFunctionTransform { /// The

    entry point to the transformation. void run() override { if (!getOptions().AssumeSingleThreaded) return; for (auto &BB : *getFunction()) { for (auto &I : BB) { if (auto RCInst = dyn_cast<RefCountingInst>(&I)) RCInst->setNonAtomic(); } } invalidateAnalysis(SILAnalysis::InvalidationKind::Instructions); } }; 35
  36. Ҡ২ (1) Op'on ͷνΣοΫ ... if (!getOptions().AssumeSingleThreaded) return; ... ·ͣ͸͜Ε͔Β΍ͬͯΈΔ

    36
  37. Ҡ২ (1) Op'on ͷνΣοΫ • ࣮͸͜ͷ࣌఺Ͱop$onΛ֬ೝ͢Δํ๏͸ͳ͍ • Ҿ਺ʹ͋Δ context ͔Β΋ݱ࣌఺Ͱ͸ΞΫηεͰ͖ͳ͍

    import SIL import SILBridging let assumeSingleThreadedSwift = FunctionPass(name: "sil-assume-single-threaded-swift") { function, context in } 37
  38. Ҡ২ (1) FunctionPassContext ʹΑΔBrigde • ͜ͷΑ͏ͳ৔߹ɺΫϩʔδϟͷ context Λ௨ͯ͡ඞཁͳؔ਺ ౳ʹBrigde͢Δ •

    context ͸ FunctionPassContext ܕ let assumeSingleThreadedSwift = ... { function, context in ... 38
  39. Ҡ২ (1) FunctionPassContext ʹΑΔBrigde • FunctionPassContext ͷ࣮૷Λ೷͍ͯΈΔ struct FunctionPassContext {

    ... func erase(instruction: Instruction) { PassContext_eraseInstruction(passContext, instruction.bridged) } ... • Ͳ͏΍Β͜ͷ erase ͸ Brigde ͞Ε͍ͯΔ • PassContext_eraseInstruction ͸ C++ ͷίʔυʹ࣮૷ͱఆ͕ٛ͋Δ • ఆٛ͸ include/swi2/SIL/SILBridging.h ʹ͋Δ • ࣮૷͸ lib/SILOp;mizer/PassManager/PassManager.cpp ʹ͋Δ 39
  40. Ҡ২ (1) PassContext_eraseInstruction • FunctionPassContext ͷ࣮૷Λ೷͍ͯΈΔʢC++ʣ void PassContext_eraseInstruction(BridgedPassContext passContext, BridgedInstruction

    inst) { castToPassInvocation(passContext)->eraseInstruction(castToInst(inst)); } • BridgedPassContext ͸ libswi((Swi() ͷ FunctionPassContextɺBridgedInstruction ͸ Instruction • castToPassInvocation Λར༻ͯ͠ɺcontext Λ LibswiftPassInvocation ʹมߋ͠ C++ ͷ Pass ͷؔ਺Λίʔϧ͢Δ • Instruction ͸ SILInstruction ͱͯ͠ར༻͢Δʹ͸ɺcastToInst ʹ౉͞ͳ͚Ε͹ͳΒͳ͍ 40
  41. Ҡ২ (1) ࢀߟʹ Op'on ͷνΣοΫΛ࡞ͬͯΈΔ(libswi/) • FunctionPassContext ʹ isAssumeSingleThreadedEnabled ͷ

    ࣮૷Λ௥Ճ var isAssumeSingleThreadedEnabled: Bool { return !(PassContext_isAssumeSingleThreadedEnabled(passContext) == 0) } • ࣍ʹ PassContext_isAssumeSingleThreadedEnabled ͷ ࣮૷ͱఆٛΛC++ଆͰߦ͏ 41
  42. Ҡ২ (1) ࢀߟʹ Op'on ͷνΣοΫΛ࡞ͬͯΈΔ(ఆٛ) • PassContext_isAssumeSingleThreadedEnabled Λఆٛ include/swi-/SIL/SILBridging.h ʹೖΕΔ

    SwiftInt PassContext_isAssumeSingleThreadedEnabled(BridgedPassContext context); • Swi% ͷ Int Λฦ͍ͨ͠ͱ͖͸ɺSwiftInt Λฦ͢Α͏ʹ͢Δ • Bool ͸ͳ͔ͬͨ... 42
  43. Ҡ২ (1) ࢀߟʹ Op'on ͷνΣοΫΛ࡞ͬͯΈΔ(࣮૷) • PassContext_isAssumeSingleThreadedEnabled Λ lib/SILOp,mizer/PassManager/ PassManager.cpp

    Ͱ࣮૷͢Δ SwiftInt PassContext_isAssumeSingleThreadedEnabled(BridgedPassContext context) { SILPassManager *pm = castToPassInvocation(context)->getPassManager(); return pm->getOptions().AssumeSingleThreaded; } • context Λ castToPassInvocation ͨ͠΋ͷ͔Β getPassManager ͯ͠ PassManager ͷ object ΛखʹೖΕΔ • ͜Ε͔Β ΦϦδφϧͷ࣮૷ͷΑ͏ʹ getOptions ͕ίʔϧͰ͖Δ • op1on ͸ Swi5 ͷ ܕͱͯ͠ Brigde Ͱ͖ͳ͍ͷͰݱঢ়͜ͷΑ͏ͳ࣮૷ʹͳͬͨ 43
  44. Ҡ২ (1) Op'on ͷνΣοΫ • context.isAssumeSingleThreadedEnabled Λίʔϧͯ͠ ׬੒ import SIL

    import SILBridging let assumeSingleThreadedSwift = FunctionPass(name: "sil-assume-single-threaded-swift") { function, context in if !context.isAssumeSingleThreadedEnabled { return } } 44
  45. Ҡ২ (2) instruc,on ͷ૸ࠪ • ࠶ͼΦϦδφϧ࣮૷ • ࣍͸ίίΛ࣮૷ͯ͠ΈΔ ... for

    (auto &BB : *getFunction()) { for (auto &I : BB) { if (auto RCInst = dyn_cast<RefCountingInst>(&I)) RCInst->setNonAtomic(); } } ... 45
  46. Ҡ২ (2) instruc,on ͷ૸ࠪ • ΫϩʔδϟͷҾ਺ funcion ͸ C++࣮૷ͷ getFunction

    ͱಉ͡ • cast ΋ dyn_cast Ͱ͸ͳ͘ Swi, ͷΩϟετͰ໰୊ͳ͠ • Swi, Β͘͠ॻ͚Δ ... for block in funcion.blocks { for instruction in block.instructions { if let rcInst = instruction as? RefCountingInst { ... } } } ... 46
  47. Ҡ২ (2) instruc,on ͷ૸ࠪ • ໰୊͸ C++ ͷ RCInst->setNonAtomic(); •

    ͜Ε͸ libswi* ʹ͸ͳ͍ͷͰ Brigde ͕ඞཁ • ཁྖ͸͖ͬ͞ͱಉ͡ 47
  48. Ҡ২ (2) setNonAtomic ͷ࣮૷ (libswi*) • RefCountingInst ʹ setNonAtomic ͷ

    ࣮૷Λ௥Ճ public class RefCountingInst : Instruction { final public var reference: Value { operands[0].value } public func setNonAtomic() { RefCountingInst_setNonAtomic(bridged) } } • ࣍ʹ RefCountingInst_setNonAtomic ͷ࣮૷ͱఆٛΛC++ଆͰߦ͏ 48
  49. Ҡ২ (2) setNonAtomic ͷ࣮૷ (ఆٛ) • RefCountingInst_setNonAtomic Λఆٛ include/swi-/SIL/ SILBridging.h

    ʹೖΕΔ void RefCountingInst_setNonAtomic(BridgedInstruction inst); • ࣍ʹ RefCountingInst_setNonAtomic ͷ࣮૷ͱఆٛΛC+ +ଆͰߦ͏ 49
  50. Ҡ২ (2) setNonAtomic ͷ࣮૷ɹ(࣮૷) • RefCountingInst_setNonAtomic Λ lib/SILOp,mizer/ PassManager/PassManager.cpp Ͱ࣮૷͢Δ

    void RefCountingInst_setNonAtomic(BridgedInstruction inst) { castToInst<RefCountingInst>(inst)->setNonAtomic(); } • inst Λ castToInst ͯ͠ɺΦϦδφϧ࣮૷௨Γ setNonAtomic Λίʔϧ͢Δ 50
  51. Ҡ২ (2) instruc,on ͷ૸ࠪ • ͋ͱ͸ rcInst.setNonAtomic() ΛSwi&࣮૷Ͱίʔϧ ... for

    block in funcion.blocks { for instruction in block.instructions { if let rcInst = instruction as? RefCountingInst { rcInst.setNonAtomic() } } } ... 51
  52. ͍͍ͩͨͰ͖ͨ import SIL import SILBridging let assumeSingleThreadedSwift = FunctionPass(name: "sil-assume-single-threaded-swift")

    { function, context in if !context.isAssumeSingleThreadedEnabled { return } for block in funcion.blocks { for instruction in block.instructions { if let rcInst = instruction as? RefCountingInst { rcInst.setNonAtomic() } } } } 52
  53. ࢒Γͷ࡞ۀ • ಉ͡֊૚ʹ͋Δ CMakeList.txt ʹ AssumeSingleThreadedSwi:.swi: Λ௥ه͠ ͓ͯ͘ • PassManager/PassRegistra>on.swi:)

    Ͱ͜ͷ Pass Λ௥ه͢Δ private func registerSwiftPasses() { registerPass(silPrinterPass, { silPrinterPass.run($0) }) registerPass(mergeCondFailsPass, { mergeCondFailsPass.run($0) }) registerPass(simplifyGlobalValuePass, { simplifyGlobalValuePass.run($0) }) registerPass(assumeSingleThreadedSwift, { assumeSingleThreadedSwift.run($0) }) // ͜Ε } • ޙ͸ Pass Λ PassPipeline Ͱݺ͹ΕΔΑ͏ʹ͢Ε͹͍͍ 53
  54. ࠶ܝ: Pass ͷొ࿥ํ๏ • include/swi,/SILOp2mizer/PassManager/Passes.def ʹ ↓ Έ͍ͨͳهड़Λॻ͘ PASS({C++ͷPassͷΫϥε໊}, "sil-{C++ͷPassͷΫϥε໊}",

    "ͳΜ͔ద౰ͳઆ໌") • ↑ ʹΑͬͯ create{C++ͷPassͷΫϥε໊} ͱ͍͏ؔ਺ͷ࣮૷Λཁٻ͞ΕΔͷͰɺ࣮૷͢Δ • ࡞ͬͨPassΫϥεͷΦϒδΣΫτΛฦͤ͹ྑ͍ • lib/SILOp0mizer/PassManager/PassPipeline.cpp ͰͦͷPass͕ݺ͹ΕΔΑ͏ʹιʔεΛॻ͖׵͑ Δ • Passes.def ΁ͷ↑ͷॻ͖׵͑ʹΑͬͯɺadd{C++ͷPassͷΫϥε໊} ͱ͍͏໊લͷؔ਺͕ SILPassPipelinePlan ܕʹੜ͑ΔͷͰͦΕΛ࢖͏ 54
  55. Pass ͷొ࿥ํ๏ Ver: libswi- (1) • include/swi,/SILOp2mizer/PassManager/Passes.def ʹ ↓ Έ͍ͨͳهड़Λॻ͘

    SWIFT_FUNCTION_PASS({Pass໊}, "{name: Ҿ਺ʹ౉ͨ͠ string}", "ͳΜ͔ద౰ͳઆ໌") • ↑ ʹΑͬͯ create{Pass໊} ͱ͍͏ؔ਺͕ੜ੒͞ΕΔʢ࣮૷͸ඞཁͳ͍ʣ • ΋͠ C++ ͱ libswi+ ࣮૷྆ํ͋ΔͳΒɺSWIFT_FUNCTION_PASS_WITH_LEGACY ͱ ͍͏෺΋͋Δ • libswi+ ʹ࣮૷͕ͳ͍ͳΒ C++ ͷํΛݺͿɺΈ͍ͨͳ͜ͱ͕Ͱ͖Δ • ಉ༷ͷ৚݅ͰɺSWIFT_FUNCTION_PASS ʹ͢ΔͱϥϯλΠϜΤϥʔʹͳΔͷͰ஫ҙ 55
  56. Pass ͷొ࿥ํ๏ Ver: libswi- (2) • SWIFT_FUNCTION_PASS_WITH_LEGACY ͷ৔߹ɺ createLegacy{Pass໊} ͱ͍͏ؔ਺

    ͷ࣮૷͕C++ଆͷPassʹཁٻ͞ΕΔ • ࣮૷͠ͳ͍ͱ swi* ͕ϏϧυΤϥʔʹͳΔ • lib/SILOp3mizer/PassManager/PassPipeline.cpp ͰͦͷPass͕ݺ͹ΕΔΑ͏ʹιʔεΛॻ͖ ׵͑Δ • Passes.def ΁ͷ↑ͷॻ͖׵͑ʹΑͬͯɺadd{Pass໊} ͱ͍͏໊લͷؔ਺͕ SILPassPipelinePlan ܕʹੜ͑ΔͷͰͦΕΛ࢖͏ • legacy ͷ৔߹͸ɺউखʹίϯύΠϥଆ͕ϋϯυϦϯάͯ͘͠ΕΔ 56
  57. ࠶౓ Build ͯ͠ Test ͯ͠ΈΔ • ࠶౓ϏϧυίϚϯυͰϏϧυ͢Δ • ҎԼͷίϚϯυΛ࣮ߦͯ͠Test $

    {Ϗϧυ੒Ռ෺ͷ͋ΔϑΥϧμ}/swiftc test.swift \ -emit-sil -assume-single-threaded \ -o result.sil -Xllvm -sil-print-pass-name • -Xllvm -sil-print-pass-name Ͱ ݺ͹Εͨ Pass ΛνΣο ΫͰ͖Δ 57
  58. ݺ͹Εͨʂʂʂ ... Start function passes at stage: Rest of Onone

    Run #22, stage Rest of Onone, pass 1: AssumeSingleThreadedSwift (sil-assume-single-threaded-swift), Function: $s4test2OBCACycfc # ͜͜ Run #23, stage Rest of Onone, pass 2: OnonePrespecializations (onone-prespecializer), Function: $s4test2OBCACycfc Run #24, stage Rest of Onone, pass 1: AssumeSingleThreadedSwift (sil-assume-single-threaded-swift), Function: $s4test2OBCACycfC Run #25, stage Rest of Onone, pass 2: OnonePrespecializations (onone-prespecializer), Function: $s4test2OBCACycfC Run #26, stage Rest of Onone, pass 1: AssumeSingleThreadedSwift (sil-assume-single-threaded-swift), Function: $s4test2OBCfd Run #27, stage Rest of Onone, pass 2: OnonePrespecializations (onone-prespecializer), Function: $s4test2OBCfd Run #28, stage Rest of Onone, pass 1: AssumeSingleThreadedSwift (sil-assume-single-threaded-swift), Function: $s4test2OBCfD Run #29, stage Rest of Onone, pass 2: OnonePrespecializations (onone-prespecializer), Function: $s4test2OBCfD Run #30, stage Rest of Onone, pass 1: AssumeSingleThreadedSwift (sil-assume-single-threaded-swift), Function: main Run #31, stage Rest of Onone, pass 2: OnonePrespecializations (onone-prespecializer), Function: main Run module pass #32, stage Rest of Onone, pass 3: SILDebugInfoGenerator (sil-debuginfo-gen) ... • ※ ͪΌΜͱ non-atomic ʹͳ͍ͬͯΔͷ΋֬ೝ 58
  59. ݱ࣌఺ͰͿ͔͍ͭͬͯΔน • AssumeSingleThreadedSwi2.swi2 ͷ࣮૷Λม͑ͯ࠶Ϗϧυͯ͠ ΋൓ө͞Εͳ͍ • --clean ͰϏϧυ͠௚͞ͳ͍ͱ͍͚ͳ͍͔΋ʁ • ͦΕҎ֎͸ࠓͷॴͳ͠

    59
  60. Θ͔ͬͨ͜ͱ΍ิ଍ͳͲ • libswi' Ͱ SILOp.mizer ͷ Pass Λ Swi' Ͱ։ൃͰ͖ΔΑ͏ʹͳͬͨͷ͸͔֬

    • ͓͓·͔ͳ͜ͱʢ૸ࠪͳͲʣ͸ ݱঢ়ͷ libswi' Ͱ༻ҙ͞Ε࣮ͨ૷ͷΈͰՄ ೳ • ࡉ͔͍͜ͱΛ΍Ζ͏ͱ͢Δͱ context ʹΑΔ Brigde ͕ඞཁ • ެࣜυΩϡϝϯτʹ͸༷ʑͳ੍໿͕ॻ͍ͯ͋Δ • Mandatory Pass ͸ݱ࣌఺Ͱ࣮૷Ͱ͖ͳ͍ɺͳͲ 60
  61. ࢀߟจݙ • libswi'/README.md 61