Lock in $30 Savings on PRO—Offer Ends Soon! ⏳

How to develop SIL Optimizer in Swift Language

How to develop SIL Optimizer in Swift Language

freddi(Yuki Aki)

July 30, 2021
Tweet

More Decks by freddi(Yuki Aki)

Other Decks in Technology

Transcript

  1. ͪΐͬͱ෮श ~ SIL • Swi% Intermediate Language ͷུ • Swi%

    ͷιʔείʔυΛίϯύΠϧ͢Δͱ͖ʹܦΔதؒݴޠ • ͜͜ͰSwi%ίϯύΠϥʹΑΔ(ಛ༗ͷ)࠷దԽ͕૸Δ 3
  2. ͪΐͬͱ෮श ~ 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
  3. ͪΐͬͱ෮श ~ SIL ͷߏ଄(1) • ·ͣɺSIL ͸େ͖͍΋ͷ͔ΒҎԼͷߏ଄ʹ෼͚ΒΕΔ • SIL Module

    • SIL Func/on • SIL Basic Block • SIL Instruc/on • ࠓճ͸খ͍͞ํ͔Βݟ͍ͯ͘ 5
  4. ͪΐͬͱ෮श ~ 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
  5. ͪΐͬͱ෮श ~ 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
  6. ͪΐͬͱ෮श ~ 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
  7. ͪΐͬͱ෮श ~ SIL ͷߏ଄(5) mainؔ਺ • ิ଍ͱͯ͠ɺͨͱ͑ swi&ϑΝΠϧʹؔ਺ʹΛॻ͍ͯͳͯ͘΋ίϯύΠϧ࣌ඞͣੜ੒͞ ΕΔ func+onɹ͕͋Δ

    • ੜ੒͞ΕΔͷ͸ main ؔ਺ • Cݴޠ ͷ mainؔ਺ͱػೳ΋ಉ͡ɻϓϩάϥϜͷΤϯτϦϙΠϯτ • swi&ϑΝΠϧʹ௚઀ॻ͍ͨίʔυ͕ mainؔ਺ʹғΘΕͯݺ͹ΕΔ // mainؔ਺ sil @main : $@convention(c) (Int32, ...) -> Int32 { ... 9
  8. ͪΐͬͱ෮श ~ 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
  9. ͪΐͬͱ෮श ~ SIL Op(mizer (1) • SILΛ࠷దԽ͢ΔίϯύΠϥͷ࠷దԽϑΣʔζ • SIL Op(mizerͷதʹ͋Δ

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

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

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

    AssumeSingleThreaded • ஌ͬͯΔݶΓ࠷খͰಡΈ΍͍͢ Pass 14
  13. ͪΐͬͱ෮श ~ 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
  14. ͪΐͬͱ෮श ~ 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
  15. ͪΐͬͱ෮श ~ SIL Op(mizer (7) C++ ͷ Pass ΛಡΉ •

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

    ͜ͷ Pass Λద༻͢Δͱ͜Μͳײ͡ʹͳΔ • લ strong_release %4 : $Neko • ޙ strong_release [nonatomic] %4 : $Neko • ͳͥϦϑΝϨϯεΧ΢ϯτ͚ͩͳͷ͔ෆ໌ 22
  21. ͪΐͬͱ෮श ~ 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
  22. ͪΐͬͱ෮श ~ ΋ͬͱ෮श͍ͨ͠ਓ͸ • ๻ͷNSSpainͰ࿩ͨ͠಺༰Λݟ͍ͯͩ͘͞ɻ(ӳޠ) • Swi+ Op.mizing (at Compiler

    World) • ͋ͱ Swi+ckaigi ͷొஃ΋ࢀߟʹͳΓ·͢ • SILOp.mizerΛࣗ෼Ͱ࡞ͬͯ༡ΜͰݟΔ @freddi-kit 24
  23. ·ͣ͸͡Ίʹ (1) swi(ͷϏϧυ • swi% ίϯύΠϥΛ clone ͯ͠ build ͢Δ

    • apple/swi% • υΩϡϝϯτʹΑΔͱɺ libswi%Λ࢖͏ʹ͸ɺϏϧυΦϓγϣϯ ʹ --libswift ͕ඞཁ 28
  24. ·ͣ͸͡Ίʹ (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
  25. ·ͣ͸͡Ίʹ (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
  26. ·ͣ͸͡Ίʹ (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
  27. libswi&/Package.swi& Λ։͘ • libswi' ͸ Package.swi' ͕༻ҙ͞Ε͍ͯͯɺ͜ΕΛ։͘ͱ Xcode ͕։͘ •

    libswi'/Package.swi' • Xcode Ͱ։ൃͰ͖·͢ • (ଟ෼) swi' Ϗϧυ͠ͳͯ͘΋ Xcode্Ͱ͸ build ͸Ͱ͖Δͱࢥ͏ 32
  28. AssumeSingleThreadedSwi1.swi1 ʹۭͷ Pass Λ௥Ճ • ΦϦδφϧͷ AssumeSingleThreaded ͸ SILFunc6onTransform Λܧ

    ঝ͍ͯ͠Δ • ͳͷͰɺ·ͣ͸ಉ͡ಇ͖Λ͢Δ FunctionPass ͰۭͷPassΛ࡞Δ • Ϋϩʔδϟ಺ʹ࠷దԽͷΞϧΰϦζϜΛॻ͘ import SIL import SILBridging let assumeSingleThreadedSwift = FunctionPass(name: "sil-assume-single-threaded-swift") { function, context in } 34
  29. ࠶ܝ 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
  30. Ҡ২ (1) Op'on ͷνΣοΫ • ࣮͸͜ͷ࣌఺Ͱop$onΛ֬ೝ͢Δํ๏͸ͳ͍ • Ҿ਺ʹ͋Δ context ͔Β΋ݱ࣌఺Ͱ͸ΞΫηεͰ͖ͳ͍

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

    context ͸ FunctionPassContext ܕ let assumeSingleThreadedSwift = ... { function, context in ... 38
  32. Ҡ২ (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
  33. Ҡ২ (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
  34. Ҡ২ (1) ࢀߟʹ Op'on ͷνΣοΫΛ࡞ͬͯΈΔ(libswi/) • FunctionPassContext ʹ isAssumeSingleThreadedEnabled ͷ

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

    SwiftInt PassContext_isAssumeSingleThreadedEnabled(BridgedPassContext context); • Swi% ͷ Int Λฦ͍ͨ͠ͱ͖͸ɺSwiftInt Λฦ͢Α͏ʹ͢Δ • Bool ͸ͳ͔ͬͨ... 42
  36. Ҡ২ (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
  37. Ҡ২ (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
  38. Ҡ২ (2) instruc,on ͷ૸ࠪ • ࠶ͼΦϦδφϧ࣮૷ • ࣍͸ίίΛ࣮૷ͯ͠ΈΔ ... for

    (auto &BB : *getFunction()) { for (auto &I : BB) { if (auto RCInst = dyn_cast<RefCountingInst>(&I)) RCInst->setNonAtomic(); } } ... 45
  39. Ҡ২ (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
  40. Ҡ২ (2) instruc,on ͷ૸ࠪ • ໰୊͸ C++ ͷ RCInst->setNonAtomic(); •

    ͜Ε͸ libswi* ʹ͸ͳ͍ͷͰ Brigde ͕ඞཁ • ཁྖ͸͖ͬ͞ͱಉ͡ 47
  41. Ҡ২ (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
  42. Ҡ২ (2) setNonAtomic ͷ࣮૷ (ఆٛ) • RefCountingInst_setNonAtomic Λఆٛ include/swi-/SIL/ SILBridging.h

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

    void RefCountingInst_setNonAtomic(BridgedInstruction inst) { castToInst<RefCountingInst>(inst)->setNonAtomic(); } • inst Λ castToInst ͯ͠ɺΦϦδφϧ࣮૷௨Γ setNonAtomic Λίʔϧ͢Δ 50
  44. Ҡ২ (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
  45. ͍͍ͩͨͰ͖ͨ 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
  46. ࢒Γͷ࡞ۀ • ಉ͡֊૚ʹ͋Δ 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
  47. ࠶ܝ: 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
  48. 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
  49. 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
  50. ࠶౓ 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
  51. ݺ͹Εͨʂʂʂ ... 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
  52. Θ͔ͬͨ͜ͱ΍ิ଍ͳͲ • libswi' Ͱ SILOp.mizer ͷ Pass Λ Swi' Ͱ։ൃͰ͖ΔΑ͏ʹͳͬͨͷ͸͔֬

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