Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

ͪΐͬͱ෮श ~ 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

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

ͪΐͬͱ෮श ~ 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

Slide 7

Slide 7 text

ͪΐͬͱ෮श ~ 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

Slide 8

Slide 8 text

ͪΐͬͱ෮श ~ 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

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

ͪΐͬͱ෮श ~ 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

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

ͪΐͬͱ෮श ~ 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

Slide 16

Slide 16 text

ͪΐͬͱ෮श ~ 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

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

ͪΐͬͱ෮श ~ 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

Slide 19

Slide 19 text

ͪΐͬͱ෮श ~ 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

Slide 20

Slide 20 text

ͪΐͬͱ෮श ~ 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

Slide 21

Slide 21 text

ͪΐͬͱ෮श ~ 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

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

ͪΐͬͱ෮श ~ 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

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

΍ͬͱຊ୊ 25

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

·ͣ͸͡Ίʹ (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

Slide 30

Slide 30 text

·ͣ͸͡Ίʹ (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

Slide 31

Slide 31 text

·ͣ͸͡Ίʹ (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

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

AssumeSingleThreadedSwi1.swi1 ʹۭͷ Pass Λ௥Ճ • ΦϦδφϧͷ AssumeSingleThreaded ͸ SILFunc6onTransform Λܧ ঝ͍ͯ͠Δ • ͳͷͰɺ·ͣ͸ಉ͡ಇ͖Λ͢Δ FunctionPass ͰۭͷPassΛ࡞Δ • Ϋϩʔδϟ಺ʹ࠷దԽͷΞϧΰϦζϜΛॻ͘ import SIL import SILBridging let assumeSingleThreadedSwift = FunctionPass(name: "sil-assume-single-threaded-swift") { function, context in } 34

Slide 35

Slide 35 text

࠶ܝ 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

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

Ҡ২ (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

Slide 40

Slide 40 text

Ҡ২ (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

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

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

Slide 43

Slide 43 text

Ҡ২ (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

Slide 44

Slide 44 text

Ҡ২ (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

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

Ҡ২ (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

Slide 47

Slide 47 text

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

Slide 48

Slide 48 text

Ҡ২ (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

Slide 49

Slide 49 text

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

Slide 50

Slide 50 text

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

Slide 51

Slide 51 text

Ҡ২ (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

Slide 52

Slide 52 text

͍͍ͩͨͰ͖ͨ 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

Slide 53

Slide 53 text

࢒Γͷ࡞ۀ • ಉ͡֊૚ʹ͋Δ 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

Slide 54

Slide 54 text

࠶ܝ: 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

Slide 55

Slide 55 text

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

Slide 56

Slide 56 text

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

Slide 57

Slide 57 text

࠶౓ 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

Slide 58

Slide 58 text

ݺ͹Εͨʂʂʂ ... 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

Slide 59

Slide 59 text

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

Slide 60

Slide 60 text

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

Slide 61

Slide 61 text

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