Share
Embed
Transcript
61 slides
-
How to develop SIL Op/mizer in Swi5 Language Θ͍Θ͍swi$c #29
30th/July/2021 @___freddi___ 1 -
ຊͷ • ͓ͪ͞Μͷͷଓ͖ • SIL Op(mizer ͷ Pass ͕ Swi2
Ͱॻ͚ΔΑ͏ʹͳͬͨͱ͍͏ 2 -
ͪΐͬͱ෮श ~ SIL • Swi% Intermediate Language ͷུ • Swi%
ͷιʔείʔυΛίϯύΠϧ͢Δͱ͖ʹܦΔதؒݴޠ • ͜͜ͰSwi%ίϯύΠϥʹΑΔ(ಛ༗ͷ)࠷దԽ͕Δ 3 -
ͪΐͬͱ෮श ~ 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 -
ͪΐͬͱ෮श ~ SIL ͷߏ(1) • ·ͣɺSIL େ͖͍ͷ͔ΒҎԼͷߏʹ͚ΒΕΔ • SIL Module
• SIL Func/on • SIL Basic Block • SIL Instruc/on • ࠓճখ͍͞ํ͔Βݟ͍ͯ͘ 5 -
ͪΐͬͱ෮श ~ 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 -
ͪΐͬͱ෮श ~ 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 -
ͪΐͬͱ෮श ~ 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 -
ͪΐͬͱ෮श ~ SIL ͷߏ(5) mainؔ • ิͱͯ͠ɺͨͱ͑ swi&ϑΝΠϧʹؔʹΛॻ͍ͯͳͯ͘ίϯύΠϧ࣌ඞͣੜ͞ ΕΔ func+onɹ͕͋Δ
• ੜ͞ΕΔͷ main ؔ • Cݴޠ ͷ mainؔͱػೳಉ͡ɻϓϩάϥϜͷΤϯτϦϙΠϯτ • swi&ϑΝΠϧʹॻ͍ͨίʔυ͕ mainؔʹғΘΕͯݺΕΔ // mainؔ sil @main : $@convention(c) (Int32, ...) -> Int32 { ... 9 -
ͪΐͬͱ෮श ~ 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 -
ͪΐͬͱ෮श ~ SIL Op(mizer (1) • SILΛ࠷దԽ͢ΔίϯύΠϥͷ࠷దԽϑΣʔζ • SIL Op(mizerͷதʹ͋Δ
Pass ͱ͍͏Ϟδϡʔϧ͕ͦΕͧΕ࠷దԽͷׂΛ͍࣋ͬͯΔ • ͦͷ Pass ͷద༻ͷॱ൪ΛΈཱͯͯʢPass Pipelineʣ࣮ࡍʹSILΛ࠷దԽ͢ΔϑΣʔζ • raw SIL ͕࠷దԽલͷSILͰ canonical SIL ͕࠷దԽޙ • ্ͷਤͰݴ͑ɺͷҹ͕ Pipeline ͱߟ͑ͯΒ͑Δͱ • ࠷దԽPassC++Ͱॻ͔Ε͍ͯΔʢ͍ͨʣ 11 -
ͪΐͬͱ෮श ~ SIL Op(mizer (2) Pass ͷछྨ • Pass ʹ2छྨ͋Δ
• Module Pass • Func0on Pass • ͲͪΒউखʹ͕ݺΜͰΔ͚ͩͳͷͰҙ • Module or Func0on͝ͱʹൃಈ͢ΔPass͔ɺͱ͍͏ҧ͍ͷΈ 12 -
ͪΐͬͱ෮श ~ SIL Op(mizer (3) C++ ͷ Pass ΛಡΉ •
࣮ࡍʹͲ͏͍͏ Pass ͕͋Δ͔ಡΜͰΈΑ͏ 13 -
ͪΐͬͱ෮श ~ SIL Op(mizer (4) C++ ͷ Pass ΛಡΉ •
AssumeSingleThreaded • ͬͯΔݶΓ࠷খͰಡΈ͍͢ Pass 14 -
ͪΐͬͱ෮श ~ 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 -
ͪΐͬͱ෮श ~ 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 -
ͪΐͬͱ෮श ~ SIL Op(mizer (7) C++ ͷ Pass ΛಡΉ •
getOptions Ͱ -assume-single-threaded Φϓγϣϯ͕͍ͯΔ͔ ݟΔ • ͍ͭͯͳ͔ͬͨΒɺ࠷దԽΛ͠ͳ͍ ... /// The entry point to the transformation. void run() override { if (!getOptions().AssumeSingleThreaded) return; ... 17 -
ͪΐͬͱ෮श ~ 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 -
ͪΐͬͱ෮श ~ 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 -
ͪΐͬͱ෮श ~ 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 -
ͪΐͬͱ෮श ~ 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 -
ͪΐͬͱ෮श ~ SIL Op(mizer (12) C++ ͷ Pass ΛಡΉ •
͜ͷ Pass Λద༻͢Δͱ͜Μͳײ͡ʹͳΔ • લ strong_release %4 : $Neko • ޙ strong_release [nonatomic] %4 : $Neko • ͳͥϦϑΝϨϯεΧϯτ͚ͩͳͷ͔ෆ໌ 22 -
ͪΐͬͱ෮श ~ 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 -
ͪΐͬͱ෮श ~ ͬͱ෮श͍ͨ͠ਓ • ͷNSSpainͰͨ͠༰Λݟ͍ͯͩ͘͞ɻ(ӳޠ) • Swi+ Op.mizing (at Compiler
World) • ͋ͱ Swi+ckaigi ͷొஃࢀߟʹͳΓ·͢ • SILOp.mizerΛࣗͰ࡞ͬͯ༡ΜͰݟΔ @freddi-kit 24 -
Pass ͕ Swi( Ͱॻ͚ΔΑ͏ʹͳΓ·ͨ͠ • libswift ͱ͍͏ Swi&ίϯύΠϥͷιʔεʹଘࡏ͢Δ Swi& Package
Λར༻ͯ͠։ൃͰ͖ΔΑ͏ʹͳΓ·ͨ͠ • ֘PR: #37398 26 -
·ͣ͡Ίʹ (1) swi(ͷϏϧυ • swi% ίϯύΠϥΛ clone ͯ͠ build ͢Δ
• apple/swi% • υΩϡϝϯτʹΑΔͱɺ libswi%Λ͏ʹɺϏϧυΦϓγϣϯ ʹ --libswift ͕ඞཁ 28 -
·ͣ͡Ίʹ (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 -
·ͣ͡Ίʹ (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 -
·ͣ͡Ίʹ (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 -
libswi&/Package.swi& Λ։͘ • libswi' Package.swi' ͕༻ҙ͞Ε͍ͯͯɺ͜ΕΛ։͘ͱ Xcode ͕։͘ •
libswi'/Package.swi' • Xcode Ͱ։ൃͰ͖·͢ • (ଟ) swi' Ϗϧυ͠ͳͯ͘ Xcode্Ͱ build Ͱ͖Δͱࢥ͏ 32 -
AssumeSingleThreadedSwi1.swi1 ʹۭͷ Pass ΛՃ • ΦϦδφϧͷ AssumeSingleThreaded SILFunc6onTransform Λܧ
ঝ͍ͯ͠Δ • ͳͷͰɺ·ͣಉ͡ಇ͖Λ͢Δ FunctionPass ͰۭͷPassΛ࡞Δ • Ϋϩʔδϟʹ࠷దԽͷΞϧΰϦζϜΛॻ͘ import SIL import SILBridging let assumeSingleThreadedSwift = FunctionPass(name: "sil-assume-single-threaded-swift") { function, context in } 34 -
࠶ܝ 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 -
Ҡ২ (1) Op'on ͷνΣοΫ • ࣮͜ͷ࣌Ͱop$onΛ֬ೝ͢Δํ๏ͳ͍ • Ҿʹ͋Δ context ͔Βݱ࣌ͰΞΫηεͰ͖ͳ͍
import SIL import SILBridging let assumeSingleThreadedSwift = FunctionPass(name: "sil-assume-single-threaded-swift") { function, context in } 37 -
Ҡ২ (1) FunctionPassContext ʹΑΔBrigde • ͜ͷΑ͏ͳ߹ɺΫϩʔδϟͷ context Λ௨ͯ͡ඞཁͳؔ ʹBrigde͢Δ •
context FunctionPassContext ܕ let assumeSingleThreadedSwift = ... { function, context in ... 38 -
Ҡ২ (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 -
Ҡ২ (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 -
Ҡ২ (1) ࢀߟʹ Op'on ͷνΣοΫΛ࡞ͬͯΈΔ(libswi/) • FunctionPassContext ʹ isAssumeSingleThreadedEnabled ͷ
࣮ΛՃ var isAssumeSingleThreadedEnabled: Bool { return !(PassContext_isAssumeSingleThreadedEnabled(passContext) == 0) } • ࣍ʹ PassContext_isAssumeSingleThreadedEnabled ͷ ࣮ͱఆٛΛC++ଆͰߦ͏ 41 -
Ҡ২ (1) ࢀߟʹ Op'on ͷνΣοΫΛ࡞ͬͯΈΔ(ఆٛ) • PassContext_isAssumeSingleThreadedEnabled Λఆٛ include/swi-/SIL/SILBridging.h ʹೖΕΔ
SwiftInt PassContext_isAssumeSingleThreadedEnabled(BridgedPassContext context); • Swi% ͷ Int Λฦ͍ͨ͠ͱ͖ɺSwiftInt Λฦ͢Α͏ʹ͢Δ • Bool ͳ͔ͬͨ... 42 -
Ҡ২ (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 -
Ҡ২ (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 -
Ҡ২ (2) instruc,on ͷࠪ • ࠶ͼΦϦδφϧ࣮ • ࣍ίίΛ࣮ͯ͠ΈΔ ... for
(auto &BB : *getFunction()) { for (auto &I : BB) { if (auto RCInst = dyn_cast<RefCountingInst>(&I)) RCInst->setNonAtomic(); } } ... 45 -
Ҡ২ (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 -
Ҡ২ (2) instruc,on ͷࠪ • C++ ͷ RCInst->setNonAtomic(); •
͜Ε libswi* ʹͳ͍ͷͰ Brigde ͕ඞཁ • ཁྖ͖ͬ͞ͱಉ͡ 47 -
Ҡ২ (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 -
Ҡ২ (2) setNonAtomic ͷ࣮ (ఆٛ) • RefCountingInst_setNonAtomic Λఆٛ include/swi-/SIL/ SILBridging.h
ʹೖΕΔ void RefCountingInst_setNonAtomic(BridgedInstruction inst); • ࣍ʹ RefCountingInst_setNonAtomic ͷ࣮ͱఆٛΛC+ +ଆͰߦ͏ 49 -
Ҡ২ (2) setNonAtomic ͷ࣮ɹ(࣮) • RefCountingInst_setNonAtomic Λ lib/SILOp,mizer/ PassManager/PassManager.cpp Ͱ࣮͢Δ
void RefCountingInst_setNonAtomic(BridgedInstruction inst) { castToInst<RefCountingInst>(inst)->setNonAtomic(); } • inst Λ castToInst ͯ͠ɺΦϦδφϧ࣮௨Γ setNonAtomic Λίʔϧ͢Δ 50 -
Ҡ২ (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 -
͍͍ͩͨͰ͖ͨ 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 -
Γͷ࡞ۀ • ಉ͡֊ʹ͋Δ 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 -
࠶ܝ: 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 -
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 -
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 -
࠶ 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 -
ݺΕͨʂʂʂ ... 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 -
Θ͔ͬͨ͜ͱิͳͲ • libswi' Ͱ SILOp.mizer ͷ Pass Λ Swi' Ͱ։ൃͰ͖ΔΑ͏ʹͳͬͨͷ͔֬
• ͓͓·͔ͳ͜ͱʢࠪͳͲʣ ݱঢ়ͷ libswi' Ͱ༻ҙ͞Ε࣮ͨͷΈͰՄ ೳ • ࡉ͔͍͜ͱΛΖ͏ͱ͢Δͱ context ʹΑΔ Brigde ͕ඞཁ • ެࣜυΩϡϝϯτʹ༷ʑͳ੍͕ॻ͍ͯ͋Δ • Mandatory Pass ݱ࣌Ͱ࣮Ͱ͖ͳ͍ɺͳͲ 60