LLVM Tutorial - わいわいswiftc

F9feb45c0a049cccc3e2563f1fe2f869?s=47 sonson
December 17, 2018

LLVM Tutorial - わいわいswiftc

LLVM Tutorialについて発表しました.
公開しようと思っている翻訳メモはこちら.
https://github.com/sonsongithub/llvm-tutorial

F9feb45c0a049cccc3e2563f1fe2f869?s=128

sonson

December 17, 2018
Tweet

Transcript

  1. 1.

    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
  2. 4.

    ͳͥɼLLVMʁ • ੈͷதͷྲྀΕ • ϜʔΞͷ๏ଇͷݶք • CPUͷྔతਐԽ͸ɼݶքʹ͍͍ۙͮͯΔʢ෺ཧతʣ • ճආ͢Δʹ͸ʁ •

    ฒྻԽ • CPU͸ສೳ͗͢ΔˠGPU, FPGA, ASIC • ͲΕ΋։ൃ͕ࠓ·Ͱͷͱҧ͍͗ͯ͢ࠔ೉ۃ·Δ ιϑτ΢ΣΞͷ։ൃํ๏͕৭ʑࢼ͞Ε͍ͯΔ
  3. 5.

    ͜͜਺೥ͷ࿩ • 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͕ग़ͯ͘Δ
  4. 11.

    ίϯύΠϧ؀ڥ • ίϚϯυͷྫ • llvm-configͳͲXcodeʹؚ·Εͳ͍πʔϧ͕͋Δ • macOSͷ৔߹ • brew install

    llvmͰΠϯετʔϧ͓ͯ͘͠ • Mojave͸/usr/include͕ͳ͍ͷͰखಈͰɾɾɾɾ • ࢲ͸ϋϚͬͨɾɾɾɾɾ • ”Xcode 10 Release Notes” • ؀ڥม਺ͷ੾Γସ͑Λ๨Εͣʹ clang++ --std=c++14 ./toy.cpp `llvm-config --cxxflags --ldflags --libs --libfiles —system-libs`
  5. 13.

    αϯϓϧ # Compute the x'th fibonacci number. def fib(x) if

    x < 3 then 1 else fib(x-1)+fib(x-2) # This expression will compute the 40th number. fib(40) # load standard library extern sin(arg); extern cos(arg); extern atan2(arg1, arg2); # call atan2 atan2(sin(.4), cos(42))
  6. 15.
  7. 18.

    The error recovery in our parser will not be the

    best and is not particular user-friendly, but it will be enough for our tutorial. Note that instead of adding virtual methods to the ExprAST class hierarchy, it could also make sense to use a visitor pattern or some other way to model this. Again, this tutorial won’t dwell on good software engineering practices: for our purposes, adding a virtual method is simplest.
  8. 22.

    ߏจ໦ͷϊʔυΫϥε /// ExprAST - Base class for all expression nodes.

    class ExprAST { public: virtual ~ExprAST() {} }; /// NumberExprAST - Expression class for numeric literals like "1.0". class NumberExprAST : public ExprAST { double Val; public: NumberExprAST(double Val) : Val(Val) {} }; ਺஋Λอଘ͢Δϊʔυ
  9. 23.

    ม਺ͱೋ߲ԋࢉࢠ /// VariableExprAST - ม਺Λอଘ͢ΔͨΊͷཁૉ class VariableExprAST : public ExprAST

    { std::string Name; public: VariableExprAST(const std::string &Name) : Name(Name) {} }; /// BinaryExprAST - +ͱ͔ͷԋࢉࢠΛอଘ͢ΔͨΊͷཁૉʁ class BinaryExprAST : public ExprAST { char Op; std::unique_ptr<ExprAST> LHS, RHS; public: BinaryExprAST(char op, std::unique_ptr<ExprAST> LHS, std::unique_ptr<ExprAST> RHS) : Op(op), LHS(std::move(LHS)), RHS(std::move(RHS)) {} }; +ͱ͔-Έ͍ͨͳԋࢉࢠͱ͔
  10. 24.

    ؔ਺ݺͼग़͠ͷͨΊͷϊʔυ /// CallExprAST - ؔ਺ݺͼग़͠ͱҾ਺Λอଘ͢ΔͨΊͷ໦ class CallExprAST : public ExprAST

    { std::string Callee; std::vector<std::unique_ptr<ExprAST>> Args; public: CallExprAST(const std::string &Callee, std::vector<std::unique_ptr<ExprAST>> Args) : Callee(Callee), Args(std::move(Args)) {} }; ؔ਺ݺͼग़͠ͷϊʔυɽ͔͜͜Βؔ਺ϙΠϯλΛݺͿʁ
  11. 25.

    ؔ਺ͷϓϩτλΠϓએݴ /// PrototypeAST - This class represents the "prototype" for

    a function, /// which captures its name, and its argument names (thus implicitly the number /// of arguments the function takes). class PrototypeAST { std::string Name; std::vector<std::string> Args; public: PrototypeAST(const std::string &name, std::vector<std::string> Args) : Name(name), Args(std::move(Args)) {} const std::string &getName() const { return Name; } }; ؔ਺ͷ໊લɼҾ਺ͷ໊લͷϦετ͕ϓϩύςΟɽ ʢී௨͸ܕͷϦετͷ΋ඞཁʣ
  12. 26.

    ؔ਺ͷϓϩτλΠϓએݴ /// FunctionAST - This class represents a function definition

    itself. class FunctionAST { std::unique_ptr<PrototypeAST> Proto; std::unique_ptr<ExprAST> Body; public: FunctionAST(std::unique_ptr<PrototypeAST> Proto, std::unique_ptr<ExprAST> Body) : Proto(std::move(Proto)), Body(std::move(Body)) {} }; ؔ਺ͷ࣮૷ɽ ϓϩτλΠϓ΁ͷϙΠϯλͱؔ਺ͷ࣮૷ຊମ΁ͷϙΠϯλ
  13. 28.

    ιʔε͔Βؤுͬͯ໦Λ࡞͍ͬͯ͘ /// numberexpr ::= number static std::unique_ptr<ExprAST> ParseNumberExpr() { auto

    Result = llvm::make_unique<NumberExprAST>(NumVal); getNextToken(); // consume the number return std::move(Result); } NumVal͕άϩʔόϧม਺ͰɼgetNextToken()Ͱ άϩʔόϧม਺ʹ࣍ͷτʔΫϯΛಡΈࠐΉ ͭ·ΓɼԚ͍
  14. 30.

    codegenͷͨΊͷΦϒδΣΫτ • static LLVMContext TheContext; • γϯάϧτϯʁσʔλ΍ܕ͕͢΂ͯอଘ͢ΔΦϒδΣ Ϋτɽ • static

    IRBuilder<> Builder(TheContext); • llvmͷIRΛੜ੒͢ΔͨΊͷΦϒδΣΫτɽ • static std::unique_ptr<Module> TheModule; • ͍ΘΏΔϞδϡʔϧɽ͜͜ʹάϩʔόϧม਺͕อଘ ͞ΕΔɽ͜ͷΦϒΤδΣΫτʹ͢΂ͯͷσʔλ͕อ ଘ͞Εɼ͋ΒΏΔ΋ͷ͸͜͜΁ͷϙΠϯλ • static std::map<std::string, Value *> NamedValues; • ม਺໊ʁͷ௥੻ʹ࢖͏ϚοϓͬΆ͍ɽ
  15. 31.

    LLVM IRΛੜ੒͢Δ • ͖͞΄ͲͷϊʔυʹcodegenΛੜ΍͢ /// ExprAST - Base class for

    all expression nodes. class ExprAST { public: virtual ~ExprAST() {} virtual Value *codegen() = 0; }; /// NumberExprAST - Expression class for numeric literals like "1.0". class NumberExprAST : public ExprAST { double Val; public: NumberExprAST(double Val) : Val(Val) {} virtual Value *codegen(); }; ValueɾɾɾStatic Single Assignment RegisterΛࣔ͢ม਺
  16. 32.

    ೋ߲ԋࢉࢠͷ৔߹ 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"); // Convert bool 0/1 to double 0.0 or 1.0 return Builder.CreateUIToFP(L, Type::getDoubleTy(TheContext), "booltmp"); default: return LogErrorV("invalid binary operator"); } }
  17. 33.