Slide 1

Slide 1 text

ヒトがおしえる!LLVM 2014/3/21 柏木餅子

Slide 2

Slide 2 text

自己紹介  柏木餅子(♂)  サークルMotiPizzaで活動中  「きつねさんでもわかる!LLVM」  達人出版会様&インプレスジャパン様から  LLVM本ではフロントエンド側担当  LLVM本の弱い方  金髪幼女の方  お仕事はソフトウェア開発色々  LLVMを使う機会は無いです  外で発表するのは初めてなので。。。 2

Slide 3

Slide 3 text

アジェンダ  LLVMとは?  コンパイラの処理  LLVMのイメージ  LLVM-IR  LLVM-IRの特徴  LLVM-IRの例  Pass  Passの概念  Passの種類  おまけ 3

Slide 4

Slide 4 text

アジェンダ  LLVMとは?  コンパイラの処理  LLVMのイメージ  LLVM-IR  LLVM-IRの特徴  LLVM-IRの例  Pass  Passの概念  Passの種類  おまけ 4

Slide 5

Slide 5 text

LLVMとは?  コンパイラ基盤だよ? 5

Slide 6

Slide 6 text

LLVMとは? コンパイラ基盤って何!? 6

Slide 7

Slide 7 text

コンパイラの処理 C/C++ X86 Java ARM Haskell PowerPC 中間表現 7

Slide 8

Slide 8 text

コンパイラの処理 C/C++ X86 Java ARM Haskell PowerPC 中間表現 フロントエンド (解析・変換) 8

Slide 9

Slide 9 text

コンパイラの処理 C/C++ X86 Java ARM Haskell PowerPC 中間表現 フロントエンド (解析・変換) ミドルエンド (解析・最適化) 9

Slide 10

Slide 10 text

コンパイラの処理 C/C++ X86 Java ARM Haskell PowerPC 中間表現 フロントエンド (解析・変換) ミドルエンド (解析・最適化) バックエンド (コード生成) 10

Slide 11

Slide 11 text

コンパイラの処理 C/C++ X86 Java ARM Haskell PowerPC 中間表現 フロントエンド (解析・変換) ミドルエンド (解析・最適化) バックエンド (コード生成) ・中間表現の規定 ・中間表現の生成・解析/最適化 ・中間表現から各種ターゲットのコード生成 ⇒各種モジュールが整理されて再利用できると嬉しいよね 11

Slide 12

Slide 12 text

LLVMのイメージ C/C++ X86 Java ARM Haskell PowerPC 中間表現 (LLVM-IR) 変換前 LLVM-IR Pass A Pass B Backend Pass LLVM バックエンド 処理 変換後 LLVM-IR 解析・最適化 Pass=中間表現(LLVM-IR)の解析や 最適化を行うモジュール 12

Slide 13

Slide 13 text

LLVMとは?  コンパイラ基盤だよ?  中間表現(LLVM-IR)と最適化・コード生成等のモジュール 13

Slide 14

Slide 14 text

LLVMとは?  コンパイラ基盤だよ?  中間表現(LLVM-IR)と最適化・コード生成等のモジュール  正しくは、LLVM=Clangとかを含むプロジェクトの総称  どちらを指しているかは文脈による 14

Slide 15

Slide 15 text

LLVMとは?  コンパイラ基盤だよ?  中間表現(LLVM-IR)と最適化・コード生成等のモジュール  正しくは、LLVM=Clangとかを含むプロジェクトの総称  どちらを指しているかは文脈による  最近人気なようですね? 15

Slide 16

Slide 16 text

LLVMとは?  コンパイラ基盤だよ?  中間表現(LLVM-IR)と最適化・コード生成等のモジュール  正しくは、LLVM=Clangとかを含むプロジェクトの総称  どちらを指しているかは文脈による  最近人気なようですね?  BSDライクの比較的緩いライセンス  モジュール化されていて再利用しやすい  読みやすい(読める) 16

Slide 17

Slide 17 text

アジェンダ  LLVMとは?  コンパイラの処理  LLVMのイメージ  LLVM-IR  LLVM-IRの特徴  LLVM-IRの例  Pass  Passの概念  Passの種類  おまけ 17

Slide 18

Slide 18 text

LLVM IRの特徴 18

Slide 19

Slide 19 text

LLVM IRの特徴  LLVM IR=LLVMの中間表現  言語非依存 19

Slide 20

Slide 20 text

LLVM IRの特徴  LLVM IR=LLVMの中間表現  言語非依存  レジスタマシンがターゲット  i32,floatなどの型があります 20

Slide 21

Slide 21 text

LLVM IRの特徴  LLVM IR=LLVMの中間表現  言語非依存  レジスタマシンがターゲット  i32,floatなどの型があります  静的単一代入形式(SSA)  変数への代入は一度だけ  def-useが追いやすい 21

Slide 22

Slide 22 text

LLVM IRの特徴  LLVM IR=LLVMの中間表現  言語非依存  レジスタマシンがターゲット  i32,floatなどの型があります  静的単一代入形式(SSA)  変数への代入は一度だけ  def-useが追いやすい  3種類あるけど全て等価  メモリ上のIR  シリアライズされたビットコード  人間が読めるアセンブリ形式  詳細はLLVMのドキュメントに・・・  LLVM Language Reference Manual 22

Slide 23

Slide 23 text

LLVM IRの例  例えば↑のソースコードをclang v3.4でコンパイルすると・・・  clang –emit-llvm –S HelloWorld.c #include int main() { printf("Hello World!\n"); return 0; } 23

Slide 24

Slide 24 text

LLVM IRの例 ; ModuleID = 'HelloWorld.cpp' target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0: 0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" @.str = private unnamed_addr constant [14 x i8] c"Hello World!\0A\00", align 1 ; Function Attrs: uwtable define i32 @main() #0 { entry: %retval = alloca i32, align 4 store i32 0, i32* %retval %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([14 x i8]* @.str, i32 0, i32 0)) ret i32 0 } declare i32 @printf(i8*, ...) #1 attributes #0 = { 省略 } attributes #1 = { 省略 } !llvm.ident = !{!0} !0 = metadata !{metadata !"clang version 3.4 (tags/RELEASE_34/final 204003)"} 24

Slide 25

Slide 25 text

LLVM IRの例 ; ModuleID = 'HelloWorld.cpp' target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0: 0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" @.str = private unnamed_addr constant [14 x i8] c"Hello World!\0A\00", align 1 ; Function Attrs: uwtable define i32 @main() #0 { entry: %retval = alloca i32, align 4 store i32 0, i32* %retval %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([14 x i8]* @.str, i32 0, i32 0)) ret i32 0 } declare i32 @printf(i8*, ...) #1 attributes #0 = { 省略 } attributes #1 = { 省略 } !llvm.ident = !{!0} !0 = metadata !{metadata !"clang version 3.4 (tags/RELEASE_34/final 204003)"} Module 25

Slide 26

Slide 26 text

LLVM IRの例 ; ModuleID = 'HelloWorld.cpp' target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0: 0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" @.str = private unnamed_addr constant [14 x i8] c"Hello World!\0A\00", align 1 ; Function Attrs: uwtable define i32 @main() #0 { entry: %retval = alloca i32, align 4 store i32 0, i32* %retval %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([14 x i8]* @.str, i32 0, i32 0)) ret i32 0 } declare i32 @printf(i8*, ...) #1 attributes #0 = { 省略 } attributes #1 = { 省略 } !llvm.ident = !{!0} !0 = metadata !{metadata !"clang version 3.4 (tags/RELEASE_34/final 204003)"} Module Grobal Variable 26

Slide 27

Slide 27 text

LLVM IRの例 ; ModuleID = 'HelloWorld.cpp' target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0: 0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" @.str = private unnamed_addr constant [14 x i8] c"Hello World!\0A\00", align 1 ; Function Attrs: uwtable define i32 @main() #0 { entry: %retval = alloca i32, align 4 store i32 0, i32* %retval %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([14 x i8]* @.str, i32 0, i32 0)) ret i32 0 } declare i32 @printf(i8*, ...) #1 attributes #0 = { 省略 } attributes #1 = { 省略 } !llvm.ident = !{!0} !0 = metadata !{metadata !"clang version 3.4 (tags/RELEASE_34/final 204003)"} Module Grobal Variable 27 Function

Slide 28

Slide 28 text

LLVM IRの例 ; ModuleID = 'HelloWorld.cpp' target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0: 0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" @.str = private unnamed_addr constant [14 x i8] c"Hello World!\0A\00", align 1 ; Function Attrs: uwtable define i32 @main() #0 { entry: %retval = alloca i32, align 4 store i32 0, i32* %retval %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([14 x i8]* @.str, i32 0, i32 0)) ret i32 0 } declare i32 @printf(i8*, ...) #1 attributes #0 = { 省略 } attributes #1 = { 省略 } !llvm.ident = !{!0} !0 = metadata !{metadata !"clang version 3.4 (tags/RELEASE_34/final 204003)"} Module Grobal Variable 28 Function BasicBlock

Slide 29

Slide 29 text

LLVM IRの例 ; ModuleID = 'HelloWorld.cpp' target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0: 0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" @.str = private unnamed_addr constant [14 x i8] c"Hello World!\0A\00", align 1 ; Function Attrs: uwtable define i32 @main() #0 { entry: %retval = alloca i32, align 4 store i32 0, i32* %retval %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([14 x i8]* @.str, i32 0, i32 0)) ret i32 0 } declare i32 @printf(i8*, ...) #1 attributes #0 = { 省略 } attributes #1 = { 省略 } !llvm.ident = !{!0} !0 = metadata !{metadata !"clang version 3.4 (tags/RELEASE_34/final 204003)"} Module Grobal Variable 29 Function BasicBlock Instruction

Slide 30

Slide 30 text

LLVM IRの例 ; ModuleID = 'HelloWorld.cpp' target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0: 0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" @.str = private unnamed_addr constant [14 x i8] c"Hello World!\0A\00", align 1 ; Function Attrs: uwtable define i32 @main() #0 { entry: %retval = alloca i32, align 4 store i32 0, i32* %retval %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([14 x i8]* @.str, i32 0, i32 0)) ret i32 0 } declare i32 @printf(i8*, ...) #1 attributes #0 = { 省略 } attributes #1 = { 省略 } !llvm.ident = !{!0} !0 = metadata !{metadata !"clang version 3.4 (tags/RELEASE_34/final 204003)"} Module Grobal Variable 30 Function BasicBlock Instruction Metadata

Slide 31

Slide 31 text

アジェンダ  LLVMとは?  コンパイラの処理  LLVMのイメージ  LLVM-IR  LLVM-IRの特徴  LLVM-IRの例  Pass  Passの概念  Passの種類  おまけ 31

Slide 32

Slide 32 text

Passの概念  LLVMの解析や最適化を担う重要な要素  LLVMの各種解析/最適化は全てPass  optコマンドで任意のPassを適用することも可能 ● opt -pass-name XX.ll 32

Slide 33

Slide 33 text

Passの種類  以下の基底クラスを目的に応じて継承  ImmutablePass  ModulePass  FunctionPass  LoopPass  RegionPass  BasicBlockPass  MachineFunctionPass  どのようなPassがあるかは公式ドキュメントを・・・  LLVM’s Analysis and Transform Passes 33

Slide 34

Slide 34 text

Passの種類  以下の基底クラスを目的に応じて継承  ImmutablePass  ModulePass  FunctionPass  LoopPass  RegionPass  BasicBlockPass  MachineFunctionPass  どのようなPassがあるかは公式ドキュメントを・・・  LLVM’s Analysis and Transform Passes 34 ART内のGPCExpander はFunctionPassを継承

Slide 35

Slide 35 text

アジェンダ  LLVMとは?  コンパイラの処理  LLVMのイメージ  LLVM-IR  LLVM-IRの特徴  LLVM-IRの例  Pass  Passの概念  Passの種類  おまけ 35

Slide 36

Slide 36 text

おまけ 36 折角なのでARTの話を少し

Slide 37

Slide 37 text

おまけ:ARTにおけるLLVM  Android4.4に含まれる新しいruntime  開発者向け  ARTのソースコードを少し眺めてみた  とりあえずart/compiler配下だけ  ぐーぐる先生に「LLVM ART」と聞くと良いエントリがありますよ! 37

Slide 38

Slide 38 text

おまけ:ARTにおけるLLVM  ARTの処理系も幾つか種類があるらしい  Quick  Portable  SeaIR  インタプリタ? 38

Slide 39

Slide 39 text

おまけ:ARTにおけるLLVM  ARTの処理系も幾つか種類があるらしい  Quick  Portable  SeaIR  インタプリタ? 39 LLVMが関係してくるのはここ

Slide 40

Slide 40 text

おまけ:ARTにおけるLLVM  ARTの処理系も幾つか種類があるらしい  Quick  Portable  SeaIR  インタプリタ?  今回はPortableまわりで読んだところを少しだけ  Dexを入力としてコード生成する 40 LLVMが関係してくるのはここ

Slide 41

Slide 41 text

おまけ:ARTにおけるLLVM  Portableの場合  Dex2Oat::CreateOatFile  art/dex2oat/dex2oat.cc  一番下にmainがあるのでそこから読んでみる 41

Slide 42

Slide 42 text

おまけ:ARTにおけるLLVM  Portableの場合  Dex2Oat::CreateOatFile  art/dex2oat/dex2oat.cc  一番下にmainがあるのでそこから読んでみる  CompilerDriver::CompileAll  art/compiler/llvm/compiler_driver.cc  CompilerLLVM::CompileDexFile等を経由しCompilerLLVM::CompileDexMethodへ? 42

Slide 43

Slide 43 text

おまけ:ARTにおけるLLVM  Portableの場合  Dex2Oat::CreateOatFile  art/dex2oat/dex2oat.cc  一番下にmainがあるのでそこから読んでみる  CompilerDriver::CompileAll  art/compiler/llvm/compiler_driver.cc  CompilerLLVM::CompileDexFile等を経由しCompilerLLVM::CompileDexMethodへ?  CompilerLLVM::CompileDexMethod  art/compiler/llvm/compiler_llvm.cc  CompileOneMethod,LLVMCompilationUnit::Materialize 43

Slide 44

Slide 44 text

おまけ:ARTにおけるLLVM  Portableの場合  Dex2Oat::CreateOatFile  art/dex2oat/dex2oat.cc  一番下にmainがあるのでそこから読んでみる  CompilerDriver::CompileAll  art/compiler/llvm/compiler_driver.cc  CompilerLLVM::CompileDexFile等を経由しCompilerLLVM::CompileDexMethodへ?  CompilerLLVM::CompileDexMethod  art/compiler/llvm/compiler_llvm.cc  CompileOneMethod,LLVMCompilationUnit::Materialize  CompileOneMethod  frontend.ccのCompileMethodへ  MIRの最適化とLLVMIRへの変換(PortableじゃなければArm/MIPS/X86CodeGenerator) 44

Slide 45

Slide 45 text

おまけ:ARTにおけるLLVM  Portableの場合  Dex2Oat::CreateOatFile  art/dex2oat/dex2oat.cc  一番下にmainがあるのでそこから読んでみる  CompilerDriver::CompileAll  art/compiler/llvm/compiler_driver.cc  CompilerLLVM::CompileDexFile等を経由しCompilerLLVM::CompileDexMethodへ?  CompilerLLVM::CompileDexMethod  art/compiler/llvm/compiler_llvm.cc  CompileOneMethod,LLVMCompilationUnit::Materialize  CompileOneMethod  frontend.ccのCompileMethodへ  MIRの最適化とLLVMIRへの変換(PortableじゃなければArm/MIPS/X86CodeGenerator)  LLVMCompilationUnit::Materialize  GBCExpanderの適用とPassManagerBuilderを利用してO3最適化  PassManagerはnothingcosmosさんのwikiとエントリがわかりやすいよ! 45

Slide 46

Slide 46 text

おまけ:ARTにおけるLLVM  今回読んだところ  PortableはDex⇒MIR⇒MIR最適化⇒LLVMIR⇒GBCExpander⇒O3最適化⇒コード生成  SeaIRはDex⇒SeaGraph⇒LLVMIR⇒O3最適化⇒コード生成という感じ?  残念ながらPortableは動いていない?らしい 46

Slide 47

Slide 47 text

まとめ  LLVMはコンパイラ基盤  コンパイラ基盤=中間表現とその操作セット  Passを用いて解析や最適化  optコマンドで任意のPassを適用可能  自分で実装する場合は目的に応じて基底クラスを継承  Android4.4のARTでもLLVMが!  PortableではDex⇒MIR⇒MIR最適化⇒LLVMIR⇒GBCExpander⇒O3最適化⇒コード生成 47

Slide 48

Slide 48 text

ありがとうございました 48