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

freddi(Yuki Aki)

July 30, 2021
Tweet

More Decks by freddi(Yuki Aki)

Other Decks in Technology

Transcript

  1. How to develop SIL Op/mizer in
    Swi5 Language
    Θ͍Θ͍swi$c #29 30th/July/2021
    @___freddi___
    1

    View Slide

  2. ຊ೔ͷ࿩
    • ͓΋ͪ͞Μͷ࿩ͷଓ͖
    • SIL Op(mizer ͷ Pass ͕ Swi2 Ͱॻ͚ΔΑ͏ʹͳͬͨͱ͍͏࿩
    2

    View Slide

  3. ͪΐͬͱ෮श ~ SIL
    • Swi% Intermediate Language ͷུ
    • Swi% ͷιʔείʔυΛίϯύΠϧ͢Δͱ͖ʹܦΔதؒݴޠ
    • ͜͜ͰSwi%ίϯύΠϥʹΑΔ(ಛ༗ͷ)࠷దԽ͕૸Δ
    3

    View Slide

  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 [email protected] 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

    View Slide

  5. ͪΐͬͱ෮श ~ SIL ͷߏ଄(1)
    • ·ͣɺSIL ͸େ͖͍΋ͷ͔ΒҎԼͷߏ଄ʹ෼͚ΒΕΔ
    • SIL Module
    • SIL Func/on
    • SIL Basic Block
    • SIL Instruc/on
    • ࠓճ͸খ͍͞ํ͔Βݟ͍ͯ͘
    5

    View Slide

  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

    View Slide

  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

    View Slide

  8. ͪΐͬͱ෮श ~ SIL ͷߏ଄(4) SIL Func-on
    • SIL Func*on
    • ݴΘͣ΋͕ͳؔ਺
    • ̍ͭҎ্ͷ basic block ͔Βߏ੒͞ΕΔ
    • ̍ͭͷSwi3ͷؔ਺͸ ̍ͭͷSIL Func*on ʹม׵͞ΕΔ
    // mainؔ਺
    sil @main : [email protected](c) (Int32, ...) -> Int32 {
    bb0:
    ...
    %8 = string_literal utf8 "Hello, World!" // user: %13
    ...
    • SIL Func*on ͸ basic block ͷίϨΫγϣϯͱࢥ͏ͱࠓޙͷ࿩͕Θ͔Γ΍͍͢
    8

    View Slide

  9. ͪΐͬͱ෮श ~ SIL ͷߏ଄(5) mainؔ਺
    • ิ଍ͱͯ͠ɺͨͱ͑ swi&ϑΝΠϧʹؔ਺ʹΛॻ͍ͯͳͯ͘΋ίϯύΠϧ࣌ඞͣੜ੒͞
    ΕΔ func+onɹ͕͋Δ
    • ੜ੒͞ΕΔͷ͸ main ؔ਺
    • Cݴޠ ͷ mainؔ਺ͱػೳ΋ಉ͡ɻϓϩάϥϜͷΤϯτϦϙΠϯτ
    • swi&ϑΝΠϧʹ௚઀ॻ͍ͨίʔυ͕ mainؔ਺ʹғΘΕͯݺ͹ΕΔ
    // mainؔ਺
    sil @main : [email protected](c) (Int32, ...) -> Int32 {
    ...
    9

    View Slide

  10. ͪΐͬͱ෮श ~ SIL ͷߏ଄(6) SIL Module
    • ίϯύΠϧ͞ΕͨSILϑΝΠϧશମ
    • άϩʔόϧม਺΍import͞ΕͨϞδϡʔϧɺstructɾclassͷఆٛɺfunc2on ͳͲ͕ݱΕΔ
    // sil_stageɹਖ਼ମ͸࣍ͷϖʔδݟΔͱΘ͔Δ͚Ͳ
    // ͜ͷSIL͸ canonical SIL ͩΑͬͯҙຯ
    sil_stage canonical
    import Builtin
    ...
    sil @main : [email protected](c) (Int32, ...) -> Int32 {
    bb0:
    ...
    %8 = string_literal utf8 "Hello, World!" // user: %13
    ...
    10

    View Slide

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

    View Slide

  12. ͪΐͬͱ෮श ~ SIL Op(mizer (2) Pass ͷछྨ
    • Pass ʹ͸2छྨ͋Δ
    • Module Pass
    • Func0on Pass
    • ͲͪΒ΋উखʹ๻͕ݺΜͰΔ͚ͩͳͷͰ஫ҙ
    • Module or Func0on͝ͱʹൃಈ͢ΔPass͔ɺͱ͍͏ҧ͍ͷΈ
    12

    View Slide

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

    View Slide

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

    View Slide

  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(&I))
    RCInst->setNonAtomic();
    }
    }
    invalidateAnalysis(SILAnalysis::InvalidationKind::Instructions);
    }
    };
    • from: lib/SILOp1mizer/Transforms/AssumeSingleThreaded.cpp
    15

    View Slide

  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

    View Slide

  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

    View Slide

  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(&I))
    RCInst->setNonAtomic();
    }
    }
    invalidateAnalysis(SILAnalysis::InvalidationKind::Instructions);
    ...
    18

    View Slide

  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(&I))
    RCInst->setNonAtomic();
    }
    }
    invalidateAnalysis(SILAnalysis::InvalidationKind::Instructions);
    ...
    19

    View Slide

  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(&I)) // ίίͷઆ໌
    RCInst->setNonAtomic();
    }
    }
    invalidateAnalysis(SILAnalysis::InvalidationKind::Instructions);
    ...
    20

    View Slide

  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(&I))
    RCInst->setNonAtomic(); // ίίͷઆ໌
    }
    }
    invalidateAnalysis(SILAnalysis::InvalidationKind::Instructions); // ίίͷઆ໌
    ...
    21

    View Slide

  22. ͪΐͬͱ෮श ~ SIL Op(mizer (12) C++ ͷ Pass ΛಡΉ
    • ͜ͷ Pass Λద༻͢Δͱ͜Μͳײ͡ʹͳΔ
    • લ
    strong_release %4 : $Neko
    • ޙ
    strong_release [nonatomic] %4 : $Neko
    • ͳͥϦϑΝϨϯεΧ΢ϯτ͚ͩͳͷ͔ෆ໌
    22

    View Slide

  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

    View Slide

  24. ͪΐͬͱ෮श ~ ΋ͬͱ෮श͍ͨ͠ਓ͸
    • ๻ͷNSSpainͰ࿩ͨ͠಺༰Λݟ͍ͯͩ͘͞ɻ(ӳޠ)
    • Swi+ Op.mizing (at Compiler World)
    • ͋ͱ Swi+ckaigi ͷొஃ΋ࢀߟʹͳΓ·͢
    • SILOp.mizerΛࣗ෼Ͱ࡞ͬͯ༡ΜͰݟΔ @freddi-kit
    24

    View Slide

  25. ΍ͬͱຊ୊
    25

    View Slide

  26. Pass ͕ Swi( Ͱ΋ॻ͚ΔΑ͏ʹͳΓ·ͨ͠
    • libswift ͱ͍͏ Swi&ίϯύΠϥͷιʔεʹଘࡏ͢Δ Swi&
    Package Λར༻ͯ͠։ൃͰ͖ΔΑ͏ʹͳΓ·ͨ͠
    • ֘౰PR: #37398
    26

    View Slide

  27. AssumeSingleThreaded Λ Swi2 Ҡ২͠Α͏
    • ࢼ͠ʹ AssumeSingleThreaded Λ Swi3 ʹҠ২ͯ͠ΈΔ
    27

    View Slide

  28. ·ͣ͸͡Ίʹ (1) swi(ͷϏϧυ
    • swi% ίϯύΠϥΛ clone ͯ͠ build ͢Δ
    • apple/swi%
    • υΩϡϝϯτʹΑΔͱɺ libswi%Λ࢖͏ʹ͸ɺϏϧυΦϓγϣϯ
    ʹ --libswift ͕ඞཁ
    28

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  32. libswi&/Package.swi& Λ։͘
    • libswi' ͸ Package.swi' ͕༻ҙ͞Ε͍ͯͯɺ͜ΕΛ։͘ͱ Xcode ͕։͘
    • libswi'/Package.swi'
    • Xcode Ͱ։ൃͰ͖·͢
    • (ଟ෼) swi' Ϗϧυ͠ͳͯ͘΋ Xcode্Ͱ͸ build ͸Ͱ͖Δͱࢥ͏
    32

    View Slide

  33. Source/Func*onPasses ʹ
    AssumeSingleThreadedSwi8.swi8 Λ௥Ճ
    • AssumeSingleThreadedSwift.swift Λ Source/
    Func,onPasses ҎԼʹ௥Ճ͢Δ
    • ݱ࣌఺ͰԿ΋ॻ͔Ε͍ͯͳ͍
    33

    View Slide

  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

    View Slide

  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(&I))
    RCInst->setNonAtomic();
    }
    }
    invalidateAnalysis(SILAnalysis::InvalidationKind::Instructions);
    }
    };
    35

    View Slide

  36. Ҡ২ (1) Op'on ͷνΣοΫ
    ...
    if (!getOptions().AssumeSingleThreaded)
    return;
    ...
    ·ͣ͸͜Ε͔Β΍ͬͯΈΔ
    36

    View Slide

  37. Ҡ২ (1) Op'on ͷνΣοΫ
    • ࣮͸͜ͷ࣌఺Ͱop$onΛ֬ೝ͢Δํ๏͸ͳ͍
    • Ҿ਺ʹ͋Δ context ͔Β΋ݱ࣌఺Ͱ͸ΞΫηεͰ͖ͳ͍
    import SIL
    import SILBridging
    let assumeSingleThreadedSwift = FunctionPass(name: "sil-assume-single-threaded-swift") { function, context in
    }
    37

    View Slide

  38. Ҡ২ (1) FunctionPassContext ʹΑΔBrigde
    • ͜ͷΑ͏ͳ৔߹ɺΫϩʔδϟͷ context Λ௨ͯ͡ඞཁͳؔ਺
    ౳ʹBrigde͢Δ
    • context ͸ FunctionPassContext ܕ
    let assumeSingleThreadedSwift = ... { function, context in
    ...
    38

    View Slide

  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

    View Slide

  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

    View Slide

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

    View Slide

  42. Ҡ২ (1) ࢀߟʹ Op'on ͷνΣοΫΛ࡞ͬͯΈΔ(ఆٛ)
    • PassContext_isAssumeSingleThreadedEnabled Λఆٛ
    include/swi-/SIL/SILBridging.h ʹೖΕΔ
    SwiftInt PassContext_isAssumeSingleThreadedEnabled(BridgedPassContext context);
    • Swi% ͷ Int Λฦ͍ͨ͠ͱ͖͸ɺSwiftInt Λฦ͢Α͏ʹ͢Δ
    • Bool ͸ͳ͔ͬͨ...
    42

    View Slide

  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

    View Slide

  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

    View Slide

  45. Ҡ২ (2) instruc,on ͷ૸ࠪ
    • ࠶ͼΦϦδφϧ࣮૷
    • ࣍͸ίίΛ࣮૷ͯ͠ΈΔ
    ...
    for (auto &BB : *getFunction()) {
    for (auto &I : BB) {
    if (auto RCInst = dyn_cast(&I))
    RCInst->setNonAtomic();
    }
    }
    ...
    45

    View Slide

  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

    View Slide

  47. Ҡ২ (2) instruc,on ͷ૸ࠪ
    • ໰୊͸ C++ ͷ RCInst->setNonAtomic();
    • ͜Ε͸ libswi* ʹ͸ͳ͍ͷͰ Brigde ͕ඞཁ
    • ཁྖ͸͖ͬ͞ͱಉ͡
    47

    View Slide

  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

    View Slide

  49. Ҡ২ (2) setNonAtomic ͷ࣮૷ (ఆٛ)
    • RefCountingInst_setNonAtomic Λఆٛ include/swi-/SIL/
    SILBridging.h ʹೖΕΔ
    void RefCountingInst_setNonAtomic(BridgedInstruction inst);
    • ࣍ʹ RefCountingInst_setNonAtomic ͷ࣮૷ͱఆٛΛC+
    +ଆͰߦ͏
    49

    View Slide

  50. Ҡ২ (2) setNonAtomic ͷ࣮૷ɹ(࣮૷)
    • RefCountingInst_setNonAtomic Λ lib/SILOp,mizer/
    PassManager/PassManager.cpp Ͱ࣮૷͢Δ
    void RefCountingInst_setNonAtomic(BridgedInstruction inst) {
    castToInst(inst)->setNonAtomic();
    }
    • inst Λ castToInst ͯ͠ɺΦϦδφϧ࣮૷௨Γ
    setNonAtomic Λίʔϧ͢Δ
    50

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  59. ݱ࣌఺ͰͿ͔͍ͭͬͯΔน
    • AssumeSingleThreadedSwi2.swi2 ͷ࣮૷Λม͑ͯ࠶Ϗϧυͯ͠
    ΋൓ө͞Εͳ͍
    • --clean ͰϏϧυ͠௚͞ͳ͍ͱ͍͚ͳ͍͔΋ʁ
    • ͦΕҎ֎͸ࠓͷॴͳ͠
    59

    View Slide

  60. Θ͔ͬͨ͜ͱ΍ิ଍ͳͲ
    • libswi' Ͱ SILOp.mizer ͷ Pass Λ Swi' Ͱ։ൃͰ͖ΔΑ͏ʹͳͬͨͷ͸͔֬
    • ͓͓·͔ͳ͜ͱʢ૸ࠪͳͲʣ͸ ݱঢ়ͷ libswi' Ͱ༻ҙ͞Ε࣮ͨ૷ͷΈͰՄ

    • ࡉ͔͍͜ͱΛ΍Ζ͏ͱ͢Δͱ context ʹΑΔ Brigde ͕ඞཁ
    • ެࣜυΩϡϝϯτʹ͸༷ʑͳ੍໿͕ॻ͍ͯ͋Δ
    • Mandatory Pass ͸ݱ࣌఺Ͱ࣮૷Ͱ͖ͳ͍ɺͳͲ
    60

    View Slide

  61. ࢀߟจݙ
    • libswi'/README.md
    61

    View Slide