Slide 1

Slide 1 text

Getting start with llvm Θ͍Θ͍swiftc Yuichi Yoshida Senior researcher, DENSO IT Laboratory, Inc. #conference @sonson_twit © 2018 DENSO IT Laboratory, Inc., All rights reserved. Redistribution or public display not permitted without written permission from DENSO IT Laboratory, Inc. LLVM Tutorial

Slide 2

Slide 2 text

https://peaks.cc/books/iOS12

Slide 3

Slide 3 text

LLVM IRಡΊ·͔͢ʁ @G = weak global i32 0 ; type of @G is i32* @H = weak global i32 0 ; type of @H is i32* define i32 @test(i1 %Condition) { entry: br i1 %Condition, label %cond_true, label %cond_false cond_true: %X.0 = load i32* @G br label %cond_next cond_false: %X.1 = load i32* @H br label %cond_next cond_next: %X.2 = phi i32 [ %X.1, %cond_false ], [ %X.0, %cond_true ] ret i32 %X.2 }

Slide 4

Slide 4 text

LLVMͱ͸ʁ • ίϯύΠϥ։ൃج൫ • ίϯύΠϥΛ࡞ΔͨΊͷϥΠϒϥϦ • C++Ͱॻ͔Ε͍ͯΔ • ෭࢈෺ • LLDB • clang • GNU GCC͕ංେԽ͗ͨ͢͠ର߅അ • dragoneggͱݺ͹ΕΔgccͷόοΫΤϯυ΋͋Δ • libc++

Slide 5

Slide 5 text

$ݴޠ --7.*3 1BTT όΠφϦ ίϯύΠϥ 1BTT LLVMΛ࢖ͬͯ࡞Δ ͜ͷPass͕ॏཁ ৭ʑ༻ҙ͞Ε͍ͯΔ͠ ࣗ෼Ͱ΋࡞ΕΔ x86, ARM, ia64, i386ɾɾɾͳͲ όΠφϦ΁ͷม׵͸LLVMͷϞδϡʔϧ

Slide 6

Slide 6 text

ΦϨΦϨ ݴޠ --7.*3 1BTT όΠφϦ ίϯύΠϥ 1BTT ͑͜͜͞࡞Ε͹ ͋ͱ͸LLVMʹ೚ͤΒΕΔ

Slide 7

Slide 7 text

Swiftͷ৔߹ 4XJGU 4*- 4*- ܕ੍໿ 4*- 3"8 4*- ࠷దԽ --7.*3 4XJGU*OUFSNFEJBUF-BOHVBHF

Slide 8

Slide 8 text

Ԡ༻ BSN " " 4

Slide 9

Slide 9 text

Ԡ༻ BSN " " 4 BSN " " 4 BSN " " 4 BSN " " 4 BSN " " 4

Slide 10

Slide 10 text

Ԡ༻ CJUDPEF " " 4 BSN --7.Λ࢖͍ ֤σόΠε޲͚ ʹ࠷దԽ

Slide 11

Slide 11 text

ͳͥɼLLVMʁ • ੈͷதͷྲྀΕ • ϜʔΞͷ๏ଇͷݶք • CPUͷྔతਐԽ͸ɼݶքʹ͍͍ۙͮͯΔʢ෺ཧతʣ • ճආ͢Δʹ͸ʁ • ฒྻԽ • CPU͸ສೳ͗͢ΔˠGPU, FPGA, ASIC • ͲΕ΋։ൃ͕ࠓ·Ͱͷͱҧ͍͗ͯ͢ࠔ೉ۃ·Δ ιϑτ΢ΣΞͷ։ൃํ๏͕৭ʑࢼ͞Ε͍ͯΔ

Slide 12

Slide 12 text

͜͜਺೥ͷ࿩ • Halide • LLVMΛ࢖͍ɼC/C++ʹ௚઀ฒྻίʔυΛ͔͚Δ • fixstars͕͜ΕͰHalide FPGAͳͲΛϦϦʔε • temp.split(y, y, yi, 8).parallel(y).vectorize(x, 4); • Tensorflow for Swift • SwiftͰػցֶशͷߦྻܭࢉ΍ฒྻܭࢉΛ΍Γ͍ͨ • Julia • ਺ֶతͳܭࢉΛඳ͖΍ͨ͘͢͠ݴޠ • LLVMΛ࢖༻ ཁॴɼཁॴͰLLVM͕ग़ͯ͘Δ

Slide 13

Slide 13 text

[11]

Slide 14

Slide 14 text

Halide [10] • εϨου • SIMD • GPU • ͳͲͳͲɾɾɾ

Slide 15

Slide 15 text

Halide HalideͳΒɼ͜ͷίʔυͰશͯͷ؀ڥʹϙʔτͰ͖Δ [10] • εϨου • SIMD • GPU • ͳͲͳͲɾɾɾ

Slide 16

Slide 16 text

·ͱΊΔͱ • ࠷ۙͷίϯύΠϥ͸LLVM • HalideͳͲΛར༻͢Δʹ΋LLVM • ΍͸ΓɼLLVMΛ஌Βͳ͍ͱલʹਐΊͳ͍

Slide 17

Slide 17 text

LLVM Tutorial • LLVMΛ࢖ͬͯΦϨΦϨݴޠͷίϯύΠϥΛ࡞Δ • C++ͰllvmΛϥΠϒϥϦͱͯ͠ɼίϯύΠϥΛ։ൃ • ಡΉͷʹඞཁͳεΩϧ • C++ • ӳޠ • ͳΜ͔brokenͩͬͨΓɼ͚ͩͨ͘ײ͡ • ਖ਼௚ɼจ͕௕͗ͯ͢ಡΊͳ͔ͬͨΓɼ͋Μ·ϝϯς φϯε͞Εͯͳ͍ͱ͜Ζ΋͋Δ

Slide 18

Slide 18 text

LLVM Tutorialͱ͸ʁ • Tutorials about using LLVM. Includes a tutorial about making a custom language with LLVM.

Slide 19

Slide 19 text

ϝϞॻ͖ͳͲ • https://github.com/sonsongithub/llvm-tutorial • LLVM Release Licenseʹج͖ͮɼ຋༁ϝϞ౳Λެ։ ͍ͯ͠·͢

Slide 20

Slide 20 text

TutorialͷϏϧυʹ͍ͭͯ • 7.0͸Chapter4Ҏ߱ɼStandard libraryͷؔ਺Λ௚઀Ϧ ϯΫͯ͠Δαϯϓϧ͸࢖͑ͳ͍ • ֎෦ͷAPIݺͼग़͠ʹࣦഊͯ͠Ϋϥογϡ͢Δ • 6.0͸OK • github͔ΒνΣοΫΞ΢τ͠ɼϏϧυ͢Δͷ͕ྑ͍ • ֬ೝͨ͠؀ڥ • macOS, brewͱιʔε͔ΒϏϧυ • Linux, aptͷύοέʔδͱιʔε͔ΒϏϧυ

Slide 21

Slide 21 text

ίϯύΠϥͷதʹ /// ίϯύΠϥͷதͰɼKaleidoscope͔Βݺ΂Δؔ਺Λఆٛ͢Δ /// putchard - putchar that takes a double and returns 0. extern "C" DLLEXPORT double putchard(double X) { fputc((char)X, stderr); return 0; } /// printd - printf that takes a double prints it as "%f\n", returning 0. extern "C" DLLEXPORT double printd(double X) { fprintf(stderr, "%f\n", X); return 0; }

Slide 22

Slide 22 text

TutorialϏϧυํ๏ • macOS • clang++ɾɾɾdeveloper tool • llvm-configɾɾɾιʔε͔ΒࣗલͰϏϧυͨ͠΋ͷ • linux • g++ɾɾɾbuild essentials • llvm-configɾɾɾaptͰπʔϧΛΠϯετʔϧ • -rdynamic,-Wl,–export-dynamic͕ඞཁͳ͜ͱ΋͋Δ clang++ ./toy.cpp `../../../build/bin/llvm-config --cxxflags --ldflags --libs --libfiles --system-libs`

Slide 23

Slide 23 text

಺༁ • ͸͡Ίʹ • ύʔαͱந৅ߏจ໦ • LLVM IRίʔυੜ੒ • JITͱ࠷దԽ • ੍ޚϑϩʔ • ԋࢉࢠͷఆٛ • mutableͷಋೖ • ίϯύΠϧ • σόοά৘ใ • ·ͱΊ

Slide 24

Slide 24 text

LLVM IRͷಛ௃ • Ϩδελɼม਺͸ແݶʹ͋Δ • ̏൪஍ίʔυΈ͍ͨͳײ͡ • SSA(Static Single Assignment form) • ੩త୯Ұ୅ೖɾɾɾม਺͸มԽ͠ͳ͍ • ܕ͸ݫີ a = (b + c) ∗ d ʢʴɼ̱ɼ̲ɼtmpaddʣ ʢˎɼtmpaddɼ̳ɼaʣ

Slide 25

Slide 25 text

LLVM IRͷαϯϓϧ define double @baz(double %x) { entry: %ifcond = fcmp one double %x, 0.000000e+00 br i1 %ifcond, label %then, label %else then: ; preds = %entry %calltmp = call double @foo() br label %ifcont else: ; preds = %entry %calltmp1 = call double @bar() br label %ifcont ifcont: ; preds = %else, %then %iftmp = phi double [ %calltmp, %then ], [ %calltmp1, %else ] ret double %iftmp }

Slide 26

Slide 26 text

։ൃ͢ΔݴޠKaleidoscope • ໨ඪͱ࢓༷ • doubleܕͷΈ • ؔ਺͕࢖͑Δ • Standard libraryͷؔ਺Λ࢖͑Δ • if/elseจ • forจ • Ϣʔβఆٛԋࢉࢠ • REPL/JIT

Slide 27

Slide 27 text

࠷ॳ • ̍ߦΛίϯύΠϧ͢Δ • ม਺͸ͳ͍ • ؔ਺͸͋Δ • math.hͱ͔͸࢖͑Δ • if/else/forจ͸ͳ͠ɾɾɾޙ͔Β௥Ճ • ͭ·ΓνϡʔϦϯά׬શͰ͸ͳ͍

Slide 28

Slide 28 text

͜Ε͔ΒC++Ͱ࡞Δ΋ͷ ,BMFJEPTDPQFͷιʔείʔυ ΦϨΦϨݴޠͷιʔείʔυ ίϯύΠϥ --7.*3΍όΠφϦ ,BMFJEPTDPQFΛղऍ͠ --7.Λ࢖ͬͯɼ--7.*3Λੜ੒͠ɼ όΠφϦΛు͘ ͭ·ΓɼC++Ͱݴޠͷ࢓༷Λॻ͍͍ͯ͘ײ͡

Slide 29

Slide 29 text

࠷ॳͷҰาʙޠኮղੳ(Lexer) • ·ͣιʔείʔυΛݻ·Γʹ෼ׂ͍ͯ͘͠ extern cos(0.1); ֎෦એݴ tok_extern Կ͔ͷࣝผࢠ tok_identifier ਺஋τʔΫϯ tok_number Χοίͱηϛίϩϯ͸ޠኮʹ౰ͨΒͳ͍ͷͰɼ ͱΓ͋͑ͣඈ͹͢

Slide 30

Slide 30 text

ୈೋาʙந৅ߏจ໦ def hoge(a b c) a+(b+c); FunctionAST Proto PrototypeAST Body BinaryExprAST - + LHS VariableExprAST - a RHS BinaryExprAST - + LHS VariableExprAST - b RHS VariableExprAST - c ԋࢉࢠͷ༏ઌ౓ʹج͖ͮɼਂ͞༏ઌͰߏจ໦Λ࡞͍ͬͯ͘

Slide 31

Slide 31 text

ந৅ߏจ໦ͷΫϥε class ExprAST { public: virtual ~ExprAST() = default; virtual Value *codegen() = 0; };

Slide 32

Slide 32 text

ม਺Λอ࣋͢Δϊʔυ class VariableExprAST : public ExprAST { std::string Name; public: VariableExprAST(const std::string &Name) : Name(Name) {} Value *codegen() override; };

Slide 33

Slide 33 text

ೋ߲ԋࢉࢠ class BinaryExprAST : public ExprAST { char Op; std::unique_ptr LHS, RHS; public: BinaryExprAST(char Op, std::unique_ptr LHS, std::unique_ptr RHS) : Op(Op), LHS(std::move(LHS)), RHS(std::move(RHS)) {} Value *codegen() override; };

Slide 34

Slide 34 text

ؔ਺એݴ class PrototypeAST { std::string Name; std::vector Args; public: PrototypeAST(const std::string &Name, std::vector Args) : Name(Name), Args(std::move(Args)) {} Function *codegen(); const std::string &getName() const { return Name; } };

Slide 35

Slide 35 text

ؔ਺࣮૷ class FunctionAST { std::unique_ptr Proto; std::unique_ptr Body; public: FunctionAST(std::unique_ptr Proto, std::unique_ptr Body) : Proto(std::move(Proto)), Body(std::move(Body)) {} Function *codegen(); };

Slide 36

Slide 36 text

ந৅ߏจ໦ def hoge(a b c) a+(b+c); FunctionAST Proto PrototypeAST Body BinaryExprAST - + LHS VariableExprAST - a RHS BinaryExprAST - + LHS VariableExprAST - b RHS VariableExprAST - c ԋࢉࢠͷ༏ઌ౓ʹج͖ͮɼਂ͞༏ઌͰߏจ໦Λ࡞͍ͬͯ͘

Slide 37

Slide 37 text

ந৅ߏจ໦ def hoge(a b c) a+b+c; FunctionAST Proto PrototypeAST Body BinaryExprAST - + LHS VariableExprAST - c RHS BinaryExprAST - + LHS VariableExprAST - a RHS VariableExprAST - b ԋࢉࢠͷ༏ઌ౓ʹج͖ͮɼਂ͞༏ઌͰߏจ໦Λ࡞͍ͬͯ͘

Slide 38

Slide 38 text

LLVM IRΛੜ੒͢Δ class ExprAST { public: virtual ~ExprAST() = default; virtual Value *codegen() = 0; }; ֤ϊʔυ͔ΒLLVM IRΛੜ੒͢Δ ߏจ໦ͷϊʔυ͝ͱʹੜ੒ͷͨΊͷίʔυΛ࣮૷͍ͯ͘͠

Slide 39

Slide 39 text

codegenͷ࢓ࣄ • llvm::ValueΫϥεΛฦ͢ • ͜ͷΫϥε͕LLVM IRΛు͍ͯ͘ΕΔ • llvm::Value • ੩త୯Ұ୅ೖϨδελΛࣔ͢ if (auto *FnIR = ProtoAST->codegen()) { fprintf(stderr, "Read extern: "); FnIR->print(errs()); fprintf(stderr, "\n"); }

Slide 40

Slide 40 text

ೋ߲ԋࢉࢠͷ৔߹ Value *BinaryExprAST::codegen() { Value *L = LHS->codegen(); Value *R = RHS->codegen(); if (!L || !R) return nullptr; switch (Op) { case '+': return Builder.CreateFAdd(L, R, "addtmp"); case '-': return Builder.CreateFSub(L, R, "subtmp"); case '*': return Builder.CreateFMul(L, R, "multmp"); case '<': L = Builder.CreateFCmpULT(L, R, "cmptmp"); return Builder.CreateUIToFP( L, Type::getDoubleTy(TheContext), "booltmp"); default: return LogErrorV("invalid binary operator"); } } ܭࢉ݁ՌΛอଘ͢ΔϨδελ໊

Slide 41

Slide 41 text

ؔ਺એݴ Function *PrototypeAST::codegen() { std::vector Doubles( Args.size(), Type::getDoubleTy(TheContext) ); FunctionType *FT = FunctionType::get( Type::getDoubleTy(TheContext), Doubles, false ); Function *F = Function::Create( FT, Function::ExternalLinkage, Name, TheModule.get() ); // Set names for all arguments. unsigned Idx = 0; for (auto &Arg : F->args()) Arg.setName(Args[Idx++]); return F; }

Slide 42

Slide 42 text

ؔ਺࣮૷ Function *FunctionAST::codegen() { Function *TheFunction = TheModule->getFunction( Proto->getName()); if (!TheFunction) TheFunction = Proto->codegen(); if (!TheFunction) return nullptr; // Create a new basic block to start insertion into. BasicBlock *BB = BasicBlock::Create( TheContext, "entry", TheFunction); Builder.SetInsertPoint(BB);

Slide 43

Slide 43 text

ؔ਺࣮૷ // Record the function arguments in the NamedValues map. NamedValues.clear(); for (auto &Arg : TheFunction->args()) NamedValues[Arg.getName()] = &Arg; if (Value *RetVal = Body->codegen()) { // Finish off the function. Builder.CreateRet(RetVal); // Validate the generated code, checking for consistency. verifyFunction(*TheFunction); return TheFunction; } // Error reading body, remove function. TheFunction->eraseFromParent(); return nullptr; }

Slide 44

Slide 44 text

ந৅ߏจ໦͔ΒLLVM IRΛ࡞Δ def hoge(a b c) a+b+c; FunctionAST Proto PrototypeAST Body BinaryExprAST - + LHS VariableExprAST - c RHS BinaryExprAST - + LHS VariableExprAST - a RHS VariableExprAST - b

Slide 45

Slide 45 text

codegen def hoge(a b c) a+b+c; FunctionAST Proto PrototypeAST Body BinaryExprAST - + LHS VariableExprAST - c RHS BinaryExprAST - + LHS VariableExprAST - a RHS VariableExprAST - b BEEUNQGBEEEPVCMFB C

Slide 46

Slide 46 text

codegen def hoge(a b c) a+b+c; FunctionAST Proto PrototypeAST Body BinaryExprAST - + LHS VariableExprAST - c RHS BinaryExprAST - + LHS VariableExprAST - a RHS VariableExprAST - b BEEUNQGBEEEPVCMFB C BEEUNQGBEEEPVCMFBEEUNQ D

Slide 47

Slide 47 text

codegen def hoge(a b c) a+b+c; FunctionAST Proto PrototypeAST Body BinaryExprAST - + LHS VariableExprAST - c RHS BinaryExprAST - + LHS VariableExprAST - a RHS VariableExprAST - b EFpOFEPVCMF!IPHF EPVCMFB EPVCMFC EPVCMFD \ FOUSZ BEEUNQGBEEEPVCMFB C BEEUNQGBEEEPVCMFBEEUNQ D SFUEPVCMFBEEUNQ ^

Slide 48

Slide 48 text

·ͱΊ • LLVMʹ͍ͭͯ • എܠɼྺ࢙ɼԠ༻ • LLVM Tutorial • ந৅ߏจ໦ • LLVM IRͷੜ੒ • ͔͜͜Β͕͓΋͠Ζ͍ • PassʹΑΔ࠷దԽ • ੍ޚϑϩʔͷ࣮૷ • mutableม਺ͷಋೖ

Slide 49

Slide 49 text

ଓ͘