Slide 1

Slide 1 text

© 2020 Yuichi Yoshida. All rights reserved. Redistribution or public display not permitted without written permission from Yuichi Yoshida. ܭࢉάϥϑͷJITίϯύΠϥΛLLVM on C++Ͱ࡞Ζ͏ #iOSDC2020 Yuichi Yoshida Senior Researcher, DENSO IT Laboratory, Inc.

Slide 2

Slide 2 text

਺ΧॴͰQRίʔυͱURLͰϦϯΫΛషΓ·͢ SpeakerDeck͔Β࠷৽ͷPDFΛμ΢ϯϩʔυͰ͖·͢ɽ ֤ιʔείʔυ΁ͷϦϯΫ͕Կ౓͔ग़͖ͯ·͕͢ɼPDFͳΒQRίʔυΛΫϦοΫͯ͠ඈ΂·͢ɽ ࠓ೔ͷࢿྉ https://speakerdeck.com/sonsongithub/ji-suan-gurahufalsejitkonpairawollvm-on-c-plus-plus-dezuo-rou

Slide 3

Slide 3 text

• sonson • @sonson_twit • github.com/sonsongithub • iOS͸͍ͩͿݹࢀͷ͓ͬ͞ΜͰ͢ • ຊ৬ • DENSO IT Laboratory, Inc. • Research Engineer • ը૾ೝࣝɼը૾ݕࡧɼػցֶशɾɾɾͳͲ ࣗݾ঺հ https://github.com/sonsongithub/zipr SwiftͰॻ͍ͯΔ zipͰਬ͖ग़ͨ͠ը૾ϑΝΠϧϏϡʔΞ

Slide 4

Slide 4 text

ࠓ೔ͷιʔείʔυͳͲ llvm.orgͷ೔ຊޠ༁Λ΍ͬͯΈͨϦϙδτϦ ࠓ೔঺հ͢Δίʔυશൠ https://github.com/sonsongithub/llvm-tutorial https://github.com/sonsongithub/llvm_jit_compile

Slide 5

Slide 5 text

LLVM

Slide 6

Slide 6 text

LLVM • ίϯύΠϥج൫ • ίϯύΠϥΛ࡞ΔͨΊͷ࢓༷΍ιϑτ΢ΣΞ܈ • C++, Python, GoͷΠϯλϑΣʔε͕ఏڙ͞Ε͍ͯΔ • ੲ͸ɼLow Level Virtual MachineͷུͩͬͨΒ͍͕͠ɼࠓ͸LLVM • ͨ͘͞Μͷιϑτ΢ΣΞ͕LLVMΛར༻͍ͯ͠Δ • Swift, Rust, Halide, Julia, clang, lldb…

Slide 7

Slide 7 text

LLVMͰԿ͔࡞Δͱ͖ͷΠϝʔδʙΦϨΦϨݴޠ ΦϨΦϨݴޠ ιʔείʔυ --7.*3 1BTT όΠφϦ ίϯύΠϥ LLVMΛAPIΛ࢖ͬͯɼLLVM IRʹม׵͢Δ ΦϨΦϨݴޠͷύʔα͸ࣗ෼Ͱ࡞Δ C++, Go, PythonͰॻ͚Δ ৭ʑ༻ҙ͞Ε͍ͯΔ͠ ࣗ෼Ͱ΋࡞ΕΔ x86ͷPassΛ࢖͑͹ɼx86ʹରԠͰ͖Δ armͷPassΛ࢖͑͹ɼar̼ʹରԠͰ͖Δ 1BTT 1BTT

Slide 8

Slide 8 text

Swiftͷ৔߹ 4XJGU ιʔείʔυ 4*- ந৅ߏจ໦ ࠷దԽ --7.*3 όΠφϦ ɾɾɾɾɾ 4XJGU*OUFSNFEJBUF-BOHVBHF

Slide 9

Slide 9 text

LLVMͰԿ͔࡞Δͱ͖ͷΠϝʔδʙࠓճͷ৔߹ ܭࢉάϥϑΞϓϦ --7.*3 --7. ந৅ߏจ໦ ܭࢉάϥϑ όΠφϦ

Slide 10

Slide 10 text

LLVM IR

Slide 11

Slide 11 text

LLVM IR • LLVMͷத֩ͱͳΔɼதؒදݱ • ΞηϯϒϦݴޠͬΆ͍ײ͡ͷදݱ • ʢ໋ྩʣʢಡΈग़͠ݩʣʢಡΈग़͠ݩʣʢॻ͖ࠐΈઌʣ • ແݶͷϨδελ͕͋Γɼܕ෇͚ݴޠɼSSA(Static Single Assignment) • ̏छྨͷ࢖͍ํ͕͋Δ • ςΩετܗࣜɾɾɾclangͱ͔Ͱग़ྗͰ͖Δ΍ͭɽhuman readable • ΠϯϝϞϦܗࣜɾɾɾɾࠓճͷΑ͏ͳϓϩάϥϜ্Ͱදݱ͞ΕΔ΋ͷ • bit codeܗࣜɾɾɾɾόΠφϦͰอ࣋ͯ͠ίϯύΫτͳ΍ͭ

Slide 12

Slide 12 text

LLVM IRͷྫ double func2(double a, double b, double *p) { return a + b - *p; } define double @func2(double, double, double*) #0 { %4 = alloca double, align 8 %5 = alloca double, align 8 %6 = alloca double*, align 8 store double %0, double* %4, align 8 store double %1, double* %5, align 8 store double* %2, double** %6, align 8 %7 = load double, double* %4, align 8 %8 = load double, double* %5, align 8 %9 = fadd double %7, %8 %10 = load double*, double** %6, align 8 %11 = load double, double* %10, align 8 %12 = fsub double %9, %11 ret double %12 }

Slide 13

Slide 13 text

LLVM IRͷྫ double func2(double a, double b, double *p) { return a + b - *p; } define double @func2(double, double, double*) #0 { %4 = alloca double, align 8 %5 = alloca double, align 8 %6 = alloca double*, align 8 store double %0, double* %4, align 8 store double %1, double* %5, align 8 store double* %2, double** %6, align 8 %7 = load double, double* %4, align 8 %8 = load double, double* %5, align 8 %9 = fadd double %7, %8 %10 = load double*, double** %6, align 8 %11 = load double, double* %10, align 8 %12 = fsub double %9, %11 ret double %12 }

Slide 14

Slide 14 text

LLVM IRͷྫ double func2(double a, double b, double *p) { return a + b - *p; } define double @func2(double, double, double*) #0 { %4 = alloca double, align 8 %5 = alloca double, align 8 %6 = alloca double*, align 8 store double %0, double* %4, align 8 store double %1, double* %5, align 8 store double* %2, double** %6, align 8 %7 = load double, double* %4, align 8 %8 = load double, double* %5, align 8 %9 = fadd double %7, %8 %10 = load double*, double** %6, align 8 %11 = load double, double* %10, align 8 %12 = fsub double %9, %11 ret double %12 }

Slide 15

Slide 15 text

LLVM IRͷྫ double func2(double a, double b, double *p) { return a + b - *p; } define double @func2(double, double, double*) #0 { %4 = alloca double, align 8 %5 = alloca double, align 8 %6 = alloca double*, align 8 store double %0, double* %4, align 8 store double %1, double* %5, align 8 store double* %2, double** %6, align 8 %7 = load double, double* %4, align 8 %8 = load double, double* %5, align 8 %9 = fadd double %7, %8 %10 = load double*, double** %6, align 8 %11 = load double, double* %10, align 8 %12 = fsub double %9, %11 ret double %12 }

Slide 16

Slide 16 text

LLVM IRͷྫ double func2(double a, double b, double *p) { return a + b - *p; } define double @func2(double, double, double*) #0 { %4 = alloca double, align 8 %5 = alloca double, align 8 %6 = alloca double*, align 8 store double %0, double* %4, align 8 store double %1, double* %5, align 8 store double* %2, double** %6, align 8 %7 = load double, double* %4, align 8 %8 = load double, double* %5, align 8 %9 = fadd double %7, %8 %10 = load double*, double** %6, align 8 %11 = load double, double* %10, align 8 %12 = fsub double %9, %11 ret double %12 }

Slide 17

Slide 17 text

LLVM IRͷྫ double func2(double a, double b, double *p) { return a + b - *p; } define double @func2(double, double, double*) #0 { %4 = alloca double, align 8 %5 = alloca double, align 8 %6 = alloca double*, align 8 store double %0, double* %4, align 8 store double %1, double* %5, align 8 store double* %2, double** %6, align 8 %7 = load double, double* %4, align 8 %8 = load double, double* %5, align 8 %9 = fadd double %7, %8 %10 = load double*, double** %6, align 8 %11 = load double, double* %10, align 8 %12 = fsub double %9, %11 ret double %12 }

Slide 18

Slide 18 text

LLVM IRͷྫ double func2(double a, double b, double *p) { return a + b - *p; } define double @func2(double, double, double*) #0 { %4 = alloca double, align 8 %5 = alloca double, align 8 %6 = alloca double*, align 8 store double %0, double* %4, align 8 store double %1, double* %5, align 8 store double* %2, double** %6, align 8 %7 = load double, double* %4, align 8 %8 = load double, double* %5, align 8 %9 = fadd double %7, %8 %10 = load double*, double** %6, align 8 %11 = load double, double* %10, align 8 %12 = fsub double %9, %11 ret double %12 }

Slide 19

Slide 19 text

LLVM IRͷྫ double func2(double a, double b, double *p) { return a + b - *p; } define double @func2(double, double, double*) #0 { %4 = alloca double, align 8 %5 = alloca double, align 8 %6 = alloca double*, align 8 store double %0, double* %4, align 8 store double %1, double* %5, align 8 store double* %2, double** %6, align 8 %7 = load double, double* %4, align 8 %8 = load double, double* %5, align 8 %9 = fadd double %7, %8 %10 = load double*, double** %6, align 8 %11 = load double, double* %10, align 8 %12 = fsub double %9, %11 ret double %12 }

Slide 20

Slide 20 text

ܭࢉάϥϑ

Slide 21

Slide 21 text

ܭࢉάϥϑɾɾɾ f(x, y, z) = sin(x) + y * log(z) double x = pi; double y = 1.0; double z = 0.1; float y = sin(x) + y * log(z); Var x, y, z; Func f; f(x, y, z) = sin(x) + y * log(z); double r = f(10, 1, 2); ී௨ʹ࣮૷ ܭࢉάϥϑͬΆ࣮͘૷

Slide 22

Slide 22 text

ܭࢉάϥϑ Var x, y, z; Func f; f(x, y, z) = sin(x) + y * log(z); double r = f(10, 1, 2); ม਺ͱؔ਺Λͭͳ͍Ͱ ؔ਺Λ࡞Δײ͡ Y Z [ TJO MPH NVMUJQMZ BEE ࣮ߦ࣌ʹґଘؔ܎͕Θ͔Δ G ࣮ߦ࣌ʹ೚ҙͷม਺Ͱඍ෼ͨ͠Γɼґଘؔ܎Λ೺Ѳͨ͠ΓͰ͖Δ

Slide 23

Slide 23 text

ྫɿHalide - ࠷దԽ C++ͷΈͰSIMDʹରԠ HalideͳΒɼ͜ΕͰSIMD/εϨου/GPUʹରԠ ܭࢉάϥϑͰදݱ͢Δ͜ͱͰɼґଘؔ܎౳͕໌֬ʹͳΔ Halide͸ɼͦΕΛ༻͍ͯɼϋʔυ΢ΣΞʹಈతʹ࠷దԽͨ͠όΠφϦΛLLVMܦ༝Ͱు͚Δ

Slide 24

Slide 24 text

ࠓ೔ͷ໨ඪɿܭࢉάϥϑΛJITίϯύΠϧ͢Δ • LLVMͱLLVM IRΛͪΐͬͱཧղ͢Δ • C++ͰܭࢉάϥϑΛ࣮૷͢Δ • ܭࢉάϥϑ͔Βந৅ߏจ໦Λ࡞Δ • ந৅ߏจ໦ΛɼLLVMʹҾ͖౉͠ɼLLVM IRʹม׵͢Δ • ϞδϡʔϧΛίϯύΠϧ͠ɼؔ਺ϙΠϯλΛಘΔ • ܭࢉάϥϑ͔Βੜ੒ͨؔ͠਺Λ࣮ߦ͢Δ ※ͪͳΈʹܭࢉάϥϑࣗମ͸JITͰͳͯ͘΋࣮ݱͰ͖·͢

Slide 25

Slide 25 text

ࠓ೔ͷίʔυͷ౔୆ HalideͷαΠτ ܭࢉάϥϑͳͲ͸ɼ͜ͷιʔεͰษڧ llvm.org - Tutorial Kaleidoscope C++ͰΦϨΦϨݴޠΛ࡞ΔνϡʔτϦΞϧ https://llvm.org/docs/tutorial/MyFirstLanguageFrontend/index.html https://halide-lang.org

Slide 26

Slide 26 text

LLVM API

Slide 27

Slide 27 text

LLVMͷΠϯετʔϧ • macOS - brew, ιʔε͔ΒϏϧυ • Xcode͸಺แͷ΋ͷ͸͓͢͢Ί͠ͳ͍ɹྫɿllvm-config͕ͳ͍ • Linux - ύοέʔδϚωʔδϟͰ͍ΕΕ͹͍͍ • ubuntuͰ͸aptͰ͍Ε·ͨ͠ • Windows - ஌Βͳ͍ɾɾɾɾ • ͢Μ·ͤΜ

Slide 28

Slide 28 text

LLVMͰؔ਺Λ࡞ΔΠϝʔδ ܭࢉάϥϑΞϓϦ --7.*3 --7. ந৅ߏจ໦ ܭࢉάϥϑ όΠφϦ

Slide 29

Slide 29 text

LLVMͰؔ਺Λ࡞ΔΠϝʔδ ܭࢉάϥϑΞϓϦ --7.*3ʢΠϯϝϞϦʣ --7. ந৅ߏจ໦ ܭࢉάϥϑ όΠφϦ --7."1* ม਺ఆٛɼԋࢉɼ໭Γ஋ɾɾɾɾ ; ModuleID = 'originalModule' source_filename = "originalModule" define double @func(double %a, double %b) { entry: %addtmp = fadd double %a, %b ret double %addtmp } όΠφϦ ʢΦϒδΣΫτϑΝΠϧʁʣ llcͳͲͷπʔϧ ςΩετܗࣜͷLLVM IR

Slide 30

Slide 30 text

γϯϓϧͳؔ਺ΛLLVMͰ࣮૷ͯ͠ΈΔ • ࣮૷͢Δؔ਺ a + b double func(double a, double b) { return a + b; }

Slide 31

Slide 31 text

LLVMͰϓϩάϥϛϯά͢ΔΠϝʔδ

Slide 32

Slide 32 text

ී௨ͷCͩͱ Ҿ਺ͳͲΛఆٛ͢Δ ؔ਺Λ࡞Δ ԋࢉ͢Δ ໭Γ஋Λఆٛ͢Δ ίϯύΠϧ͢Δ ࣮ߦ͢Δ (double a, double b)... double hoge (double a, double b)... a + b return a + b; clang hoge.cpp -o hoge hoge

Slide 33

Slide 33 text

$ͷίʔυ LLVM APIͰؔ਺Λ࡞Δ Ҿ਺ͳͲΛఆٛ͢Δ ؔ਺Λ࡞Δ ԋࢉ͢Δ ໭Γ஋Λఆٛ͢Δ ίϯύΠϧ͢Δ ࣮ߦ͢Δ llvm::FunctionType::get(Type::getDoubleTy(TheContext)… llvm::Function::Create(functionType, Function::ExternalLinkage... auto result = builder.CreateFAdd(dict["a"], dict["b"], “addtmp"); builder.CreateRet(result); ExecutionEngine *executionEngine = EngineBuilder(std::move(module))... executionEngine->getFunctionAddress(function->getName().str())

Slide 34

Slide 34 text

४උɾɾɾɾ͓·͡ͳ͍ --7.͕؅ཧ͢Δ$POUFYU static llvm::LLVMContext TheContext; InitializeNativeTarget(); InitializeNativeTargetAsmPrinter();

Slide 35

Slide 35 text

࣮૷ͷཁɼϞδϡʔϧΛ࡞Δ --7.͕؅ཧ͢Δ$POUFYU static llvm::LLVMContext TheContext; InitializeNativeTarget(); InitializeNativeTargetAsmPrinter(); // Create a new module std::unique_ptr module(new llvm::Module("originalModule", TheContext)); .PEVMF

Slide 36

Slide 36 text

LLVM IRͷϏϧμΛ࡞Δ --7.͕؅ཧ͢Δ$POUFYU .PEVMF static llvm::LLVMContext TheContext; InitializeNativeTarget(); InitializeNativeTargetAsmPrinter(); // Create a new module std::unique_ptr module(new llvm::Module("originalModule", TheContext)); // LLVM IR builder static IRBuilder<> builder(TheContext); ͜ͷΦϒδΣΫτʹ଍͠ࢉͷ໋ྩͳͲΛ౉ͯ͠ ϓϩάϥϛϯά͍ͯ͘͠

Slide 37

Slide 37 text

ࢦఆͨ͠ܕΛ࣋ͭؔ਺Λ࡞Δ --7.͕؅ཧ͢Δ$POUFYU .PEVMF 'VODUJPO Ҿ਺ɾ໭Γ஋ ໊લ static llvm::LLVMContext TheContext; InitializeNativeTarget(); InitializeNativeTargetAsmPrinter(); // Create a new module std::unique_ptr module(new llvm::Module("originalModule", TheContext)); // LLVM IR builder static IRBuilder<> builder(TheContext); // define function // argument name list auto functionName = "originalFunction"; // argument type list std::vector Doubles(2, Type::getDoubleTy(TheContext)); // create function type FunctionType *functionType = FunctionType::get(Type::getDoubleTy(TheContext), Doubles, false); // create function in the module. Function *function = Function::Create(functionType, Function::ExternalLinkage, functionName, module.get()); ໭Γ஋΍Ҿ਺ͷܕΛࢦఆͯ͠ ؔ਺ͷܕΛ࡞Δ Ϟδϡʔϧɼ໊લɼܕΛࢦఆͯ͠ ؔ਺Λ࡞Δ

Slide 38

Slide 38 text

ॲཧͷϒϩοΫΛ࡞Δ --7.͕؅ཧ͢Δ$POUFYU .PEVMF 'VODUJPO Ҿ਺ɾ໭Γ஋ ໊લ // Create a new basic block to start insertion into. BasicBlock *basicBlock = BasicBlock::Create(TheContext, "entry", function); builder.SetInsertPoint(basicBlock); #MPDL FOUSZ

Slide 39

Slide 39 text

FunctionΫϥε͔ΒҾ਺ͷϦετΛ΋Β͏ --7.͕؅ཧ͢Δ$POUFYU .PEVMF 'VODUJPO Ҿ਺ɾ໭Γ஋ ໊લ // Create a new basic block to start insertion into. BasicBlock *basicBlock = BasicBlock::Create(TheContext, "entry", function); builder.SetInsertPoint(basicBlock); std::vector argNames{"a", “b"}; // Set names for all arguments. // I'd like to use "zip" function, here..... unsigned idx = 0; for (auto &arg : function->args()) { arg.setName(argNames[idx++]); } // Create argument table for LLVM::Value type. static std::map dict; for (auto &arg : function->args()) { dict[arg.getName()] = &arg; } #MPDL FOUSZ ॲཧ ͜ͷؔ਺ͷҾ਺ͱͳΔMMWN7BMVFΛ MMWN'VODUJPO͔Βྻڍ͠ɼ ໊લΛηοτ͢Δ TUENBQʹม਺Λอଘ͓ͯ͘͠ ޙ͔Βݺͼग़͢ͱ͖ʹศར

Slide 40

Slide 40 text

ԋࢉ͢Δʢࠓճ͸଍͠ࢉʣ --7.͕؅ཧ͢Δ$POUFYU .PEVMF 'VODUJPO Ҿ਺ɾ໭Γ஋ ໊લ // Create a new basic block to start insertion into. BasicBlock *basicBlock = BasicBlock::Create(TheContext, "entry", function); builder.SetInsertPoint(basicBlock); std::vector argNames{"a", “b"}; // Set names for all arguments. // I'd like to use "zip" function, here..... unsigned idx = 0; for (auto &arg : function->args()) { arg.setName(argNames[idx++]); } // Create argument table for LLVM::Value type. static std::map dict; for (auto &arg : function->args()) { dict[arg.getName()] = &arg; } // calculate "add" auto result = builder.CreateFAdd(dict["a"], dict["b"], “addtmp"); #MPDL FOUSZ ॲཧ ೋͭͷม਺ͷ࿨ ஋͸ɼMMWN7BMVFͰࢦఆ͢Δ "EEͷ݁Ռ΋MMWN7BMVFͰฦͬͯ͘Δ

Slide 41

Slide 41 text

໭Γ஋ͱͯ͠ܭࢉ݁ՌΛηοτ͢Δ --7.͕؅ཧ͢Δ$POUFYU .PEVMF 'VODUJPO Ҿ਺ɾ໭Γ஋ ໊લ #MPDL FOUSZ ॲཧ SFUVSO // Create a new basic block to start insertion into. BasicBlock *basicBlock = BasicBlock::Create(TheContext, "entry", function); builder.SetInsertPoint(basicBlock); std::vector argNames{"a", “b"}; // Set names for all arguments. // I'd like to use "zip" function, here..... unsigned idx = 0; for (auto &arg : function->args()) { arg.setName(argNames[idx++]); } // Create argument table for LLVM::Value type. static std::map dict; for (auto &arg : function->args()) { dict[arg.getName()] = &arg; } // calculate "add" auto result = builder.CreateFAdd(dict["a"], dict["b"], “addtmp"); // set return builder.CreateRet(result);

Slide 42

Slide 42 text

ςΩετܗࣜͰ֬ೝ // confirm LLVM IR module->print(llvm::outs(), nullptr); ; ModuleID = 'originalModule' source_filename = "originalModule" define double @originalFunction(double, double) { entry: %addtmp = fadd double %0, %1 ret double %addtmp }

Slide 43

Slide 43 text

࣮ߦ // confirm LLVM IR module->print(llvm::outs(), nullptr); // Builder JIT ExecutionEngine *executionEngine = EngineBuilder(std::move(module)) .setEngineKind(EngineKind::JIT) .create(); // Get pointer to a function which is built by EngineBuilder. auto f = reinterpret_cast( executionEngine->getFunctionAddress(function->getName().str()) ); f(1.0, 2.0); ࠓճͷ࣮૷͸ɼ&YFDVUJPO&OHJOFΫϥεΛ࢖ͬͯ+*5ίϯύΠϧ .$+*5ͱ͍͏ͷΛ࢖͍ͬͯͯݱࡏEFQSFDBUFE ϗϯτ͸ɼ03$+*5Λ࢖͏΂͖Β͍͠

Slide 44

Slide 44 text

࣮ߦ // confirm LLVM IR module->print(llvm::outs(), nullptr); // Builder JIT ExecutionEngine *executionEngine = EngineBuilder(std::move(module)) .setEngineKind(EngineKind::JIT) .create(); // Get pointer to a function which is built by EngineBuilder. auto f = reinterpret_cast( executionEngine->getFunctionAddress(function->getName().str()) ); f(1.0, 2.0); $$͸ؔ਺ͷϙΠϯλͷܕΛϥϯλΠϜ࣌ʹಈతʹม͑ΒΕͳ͍ɾɾɾ ํ๏͋Γ·͢ɾɾɾʁ

Slide 45

Slide 45 text

Մม௕Ҿ਺ΛLLVM IRͰ࢖͏ • ରࡦҊɿҾ਺ΛϙΠϯλͰ౉͠ɼ໌ࣔతʹݺͼग़͞ͳ͍ ݺͼग़͠ଆͷΫϥε΍είʔϓ --7.Ͱ+*5ͨؔ͠਺ EPVCMF EPVCMF ɹݺͼग़͠ଆͷΫϥε΍είʔϓ --7.Ͱ+*5ͨؔ͠਺ EPVCMF EPVCMF ୈೋҊ͸ɼՄม௕Ҿ਺ͷC/C++ͷؔ਺ϙΠϯλͰ࣮ݱ͢Δɾɾɾɾʁ

Slide 46

Slide 46 text

ܭࢉάϥϑͷ࣮૷

Slide 47

Slide 47 text

ܭࢉάϥϑΛC++Ͱ࡞Δ • ந৅ߏจ໦ΛΘ͔Γ΍͘͢͢ΔͨΊ • ؆୯ͷͨΊʹ+ͷΈͷೋͭͷ୯७ܭࢉάϥϑͷΈΛߟ͑Δ • ܕ͸͢΂ͯdouble • ܭࢉ͸ɼԋࢉࢠͷΦʔόʔϩʔυͰ࣮૷͢Δ • ܭࢉάϥϑ͔Βந৅ߏจ໦Λ࡞Γɼ͔ͦ͜ΒLLVM IRΛు͖ग़͢ • ੿࡞ͷαϯϓϧ͸ɼVISITORύλʔϯͰ࣮૷ͯ͠Έͨ

Slide 48

Slide 48 text

• ந৅ߏจ໦ͷϊʔυΛϥοϓͨ͠ม਺Λ࢖͏ • ໦ߏ଄ͷϊʔυͱɼܭࢉʹݱΕΔม਺ͱ݁ՌΛ෼͚Δ • ԋࢉࢠͷΦʔόʔϩʔυ͕࣮૷͠΍͍͢ • Halideͷड͚ചΓ ந৅ߏจ໦ΛC++ͷΦʔόʔϩʔυͰ࣮૷͢Δ

Slide 49

Slide 49 text

ܭࢉάϥϑΛC++Ͱॻ͘ Func f; Var a, b; f(a, b) = a + b; f.realise();

Slide 50

Slide 50 text

·ͣ͸ม਺એݴɹม਺ͷఆٛͷϊʔυΛ಺แ 7BSB 7BS&YQS"45WBMVF 7BSC 7BS&YQS"45WBMVF Func f; Var a, b; f(a, b) = a + b; f.realise(); 7BSΫϥε͸҉໧ͷܕม׵Ͱ &YQSΫϥεͱͯ΋ԋࢉࢠΛΦʔόʔϩʔυ͢Δ ͳͷͰ7BSಉ࢜Λ଍ͤΔ ͞Βʹ--7.*3Ͱ࢖ΘΕΔ໊લ͕7BS͕࡞ΒΕͨλΠϛϯάͰ ࣗಈੜ੒͞ΕΔʢϚϧνεϨουඇରԠʣ

Slide 51

Slide 51 text

࿨ΛऔΔϊʔυΛߏ੒͢Δʔࢠϊʔυ͕ೋͭ &YQS 7BS&YQS"45WBMVF &YQS 7BS&YQS"45WBMVF B C &YQS#JOBSZ"45 DIBSPQ &YQS"45MIT &YQS"45SIT Func f; Var a, b; f(a, b) = a + b; f.realise(); &YQΫϥεͰ಺แ͢Δ &YQSΫϥεͷԋࢉࢠΛΦʔόʔϩʔυͯ͠ 7BSͷΦϒδΣΫτ΍ܭࢉ݁ՌΛ ίʔυͰͦͷ··ॻ͚ΔΑ͏ʹ͢Δ

Slide 52

Slide 52 text

݁ՌΛExprͰแΉ &YQS 7BS&YQS"45WBMVF &YQS 7BS&YQS"45WBMVF B C &YQS#JOBSZ"45 DIBSPQ &YQS"45MIT &YQS"45SIT &YQS Func f; Var a, b; f(a, b) = a + b; f.realise(); ͞Βʹ'VODʹ಺แ͞ΕΔ ͜͏͓͔ͯ͠ͳ͍ͱ ԋࢉࢠͷΦʔόʔϩʔυͷ࣮૷͕େม

Slide 53

Slide 53 text

݁ՌΛExprͰแΉ Func f; Var a, b; f(a, b) = a + b; f.realise(); ͜ͷࠨล஋͸ɼ'VODͷϓϩύςΟͷ&YQSͷࢀরΛฦ͢ ͜ͷࠨล஋ͷதͰɼBͱCΛؔ਺ͷҾ਺ͱͯ͠ηοτ͢Δ // Set names for all arguments. unsigned idx = 0; for (auto &arg : callee->args()) { arg.setName(argumentPlacefolders[idx++].name); }

Slide 54

Slide 54 text

ϊʔυΛḷͬͯLLVM IRΛ૊Έཱ͍ͯͯ͘ &YQS 7BS&YQS"45WBMVF &YQS 7BS&YQS"45WBMVF Func f; Var a, b; f(a, b) = a + b; f.realise(); &YQS#JOBSZ"45 DIBSPQ &YQS"45MIT &YQS"45SIT &YQS llvm::Value* BinaryExprAST::accept(IRVisitor* visitor) { std::cout << "accept - BinaryExprAST" << std::endl; llvm::Value* left = visitor->visit(lhs); llvm::Value* right = visitor->visit(rhs); auto p = visitor->builder; return p->CreateFAdd(left, right, "addtmp"); }

Slide 55

Slide 55 text

ϊʔυΛḷͬͯLLVM IRΛ૊Έཱ͍ͯͯ͘ &YQS 7BS&YQS"45WBMVF &YQS 7BS&YQS"45WBMVF Func f; Var a, b; f(a, b) = a + b; f.realise(); &YQS#JOBSZ"45 DIBSPQ &YQS"45MIT &YQS"45SIT &YQS llvm::Value* VarExprAST::accept(IRVisitor* visitor) { // Ϟδϡʔϧʹొ࿥͞Εͨม਺Λฦ͢ auto p = visitor->name2Value[name]; return p; }

Slide 56

Slide 56 text

&YQS &YQS#JOBSZ"45 ͜ͷ࢓૊ΈΛߏ଄తʹ࡞͍͚ͬͯ͹Α͍ f(a, b, c) = a + b * c * c; 7BSB &YQS"45WBMVF DIBSPQ &YQS"45MIT &YQS"45SIT 7BSC &YQS"45WBMVF 7BSD &YQS"45WBMVF &YQS &YQS#JOBSZ"45 DIBSPQ &YQS"45MIT &YQS"45SIT &YQS &YQS#JOBSZ"45 DIBSPQ &YQS"45MIT &YQS"45SIT

Slide 57

Slide 57 text

Further more… • ఆ਺͸ɼcreateValueؔ਺Ͱఆ਺Λ࡞੒Ͱ͖Δ • C/C++Ͱݺ΂Δ֎෦ؔ਺ͷݺͼग़͠ɾɾɾ໊લͰొ࿥͢Δ͚ͩ • C͸؆୯͕ͩɼC++͸mangling͕ೖΔͷͰେมʢmangling͕ॲཧܥʹґଘ͢ΔͨΊʣ • double hoge_cpp(double a) → _Z8hoge_cppd • ৚݅෼ذ • blockΛ׆༻࣮ͯ͠૷͢Δ • ϝϞϦ֬อɾɾɾSSA͔Βͷղ์ • allocaͰ֬อ͠ɼSSA͡Όͳ͍ม਺Λ࡞ΕΔɽ͜ΕͰforจͱ͔΋؆୯ʹ࡞ΕΔ

Slide 58

Slide 58 text

࠷ऴతʹɾɾɾɾɾ int main() { Func f; Var a, b, c; f(a, b, c) = F::sin(a * 1.2) + F::sin(b * F::pow(a, b)); f.realise(); std::cout << f(10.0, 2.0, 3.0) << std::endl; return 0; }

Slide 59

Slide 59 text

·ͱΊ • LLVMͷ׆༻ɼܭࢉάϥϑͷԠ༻ • LLVM IRͷجຊ • ܭࢉάϥϑˠந৅ߏจ໦ͷ࡞Γํͷ͸͡ΊͷҰา • ͓͢͢Ίڭࡐ • LLVM IR → llvm.orgͷTutorial Kaleidoscope Language • ந৅ߏจ໦ͱJIT → Halideͷιʔείʔυ