Upgrade to Pro — share decks privately, control downloads, hide ads and more …

用 MLIR 實作 一個 Ruby IR (intermediate representation)

Johnlin
August 03, 2024

用 MLIR 實作 一個 Ruby IR (intermediate representation)

Johnlin

August 03, 2024
Tweet

More Decks by Johnlin

Other Decks in Technology

Transcript

  1. John Lin 2024/08/03 Coscup 2024 ༻ MLIR መ࡞ Ұݸ Ruby

    IR (intermediate representation) Implement a Ruby IR with MLIR
  2. COSCUP 2024 • Twitter: @johnlinvc • website: https://johnlin.vc • SRE

    @ West Pharmaceutical services
 ੢ࣜဌऱ • Do Ruby as a hobby.
 ڵझ࢖વత Rubyistɻ John Lin
  3. COSCUP 2024 coscup = 40 + 2 Automatically optimized into

    ࣗಈ࠷ՂԽ੒ coscup = 42 What if ? ೗Ռʁ
  4. COSCUP 2024 $ cat << EOF > coscup.rb coscup =

    40 + 2 EOF $ bundle exec mlir_rb_optimizer coscup.rb coscup = 42 ՄҎʂ We can!
  5. COSCUP 2024 • Optimizer parse the Ruby code, emit the

    IR(intermediate representation), optimize the IR, translate the IR back to Ruby Code.
 Optimizer parse Ruby ఔࣜᛰɼ༌ग़ IR (தհᛰʣɼ࠷ՂԽ IRɼ೺ IR ຋ᩄճ Ruby ఔࣜ ᛰɻ • Use a Ruby IR based on MLIR. 
 ࢖༻جԙ MLIR త Ruby IR ɻ • https://github.com/johnlinvc/mlir-dialect-ruby ዎኄ၏౸తʁ How ?
  6. COSCUP 2024 • What is IR?
 ॄኄੋ IR ? •

    What is MLIR?
 ॄኄੋ MLIR ? • Intro to MLIR Ruby dialect
 հ঺ MLIR Ruby ํݴ • Future plan & Q&A
 ະိܭᙘᢛ Q&A େߝ Agenda
  7. COSCUP 2024 • IR stands for intermediate representation.
 IR ੋ

    தհᛰతॖሜɻ • IR is the a program representation between AST(abstract syntax tree) and Machine Code.
 IR ੋհԙ AST(ޠ๏थʣ࿨ػցᛰ ೭ؒతҰछఔࣜදࣔ๏ɻ ॄኄੋ IR ? What is IR?
  8. COSCUP 2024 define i32 @add(i32 %a) #0 { %1 =

    alloca i32, align 4 store i32 %a, i32* %1, align 4 %2 = load i32, i32* @globvar, align 4 %3 = load i32, i32* %1, align 4 %4 = add nsw i32 %2, %3 ret i32 %4 } Clang (LLVM IR) C/C++ LLVM IR Machine
  9. COSCUP 2024 sil @_T5norms11taxicabNormfT1aV5norms5Point_Sd : $(Point) -> Double { bb0(%0

    : $Point): // func Swift.+(Double, Double) -> Double %1 = function_ref @_Tsoi1pfTSdSd_Sd %2 = struct_extract %0 : $Point, #Point.x %3 = struct_extract %0 : $Point, #Point.y %4 = apply %1(%2, %3) : $(Double, Double) -> Double return %4 : Double } Swift IR (SIL) Swift SIL LLVM IR Machine
  10. COSCUP 2024 HIR: Tree based थ㐫 THIR: HIR with inferred

    Type ༗ਪᏗܕผత HIR MIR: SSA Form IR ᄸҰොᆴ IR Rust IR (HIR,THIR,MIR) Rust HIR THIR Machine LLVM IR LIR
  11. COSCUP 2024 • Makes Optimizing & Type Checking easier
 ߋ༰қ࠷ՂԽ࿨ܕผᒾҰ

    • As an abstraction layer between the Programming Language and It's running environment.
 ࡞ҝఔࣜޠݴ࿨ࣥߦ؀ڥؒతந৅૚
 IR త༻్ The Purpose of IR
  12. COSCUP 2024 • The CRuby virtual machine(YARV, Yet another Ruby

    VM) 
 has a instruction set (ISeq).
 CRuby 㐘ٖػ YARV ༗ఆٛҰݸࢦྩू ISEQɻ • YARV is a stack machine.
 YARV ࢖༻ Stack ိ၏ܭࢉɻ • Dynamic typed, with some optimization like tagged pointer. 
 ಈଶܕผɼෆա༗Ұࠣ࠷ՂԽ૾ੋ tagged pointerɻ Ruby ݱࡏత IR Ruby's current IR Ruby ISEQ YARV VM
  13. COSCUP 2024 3.3.0 :008 > puts RubyVM::InstructionSequence.compile('coscup = 40 +

    2').disasm ... 0000 putobject 40 ( 1)[Li] 0002 putobject 2 0004 opt_plus <calldata!mid:+, argc:1, ARGS_SIMPLE>[CcCr] 0006 dup 0007 setlocal_WC_0 coscup@0 0009 leave Ruby ݱࡏత IR Ruby's current IR
  14. COSCUP 2024 • YARV is stack machine. Which is easier

    to implement and port across di ff erent CPU Arch. But harder to optimize and runs slower. [1]
 YARV ੋ stack machineɻ༰қመ࡞࿨Ҡ২ɼୠੋൺֱຫ࿨ֱ೉࠷ՂԽɻ • YARV is dynamic typed, making Monomorphization harder.
 ಈଶܕผൺֱ೉ Monomorphization • YARV is made for CPU, we don't want to miss the AI train on GPU.
 YARV ੋҝ CPU ઃܭతɼᔒ㭎๏䋯ࡏ GPU ্ɻ Why do we need a new IR for Ruby?
  15. COSCUP 2024 • A optimization on generating specialized code for

    a speci fi c type.
 ҝಛఆܕผ㗞ੜಛผతػցᛰత࠷ՂԽɻ • e.g. 40+2 can be compiled into a single ADD instruction.
 40 + 2 ՄҎඃฤᩄ੒ᄸҰ ADD ࢦྩɻ Monomorphization
  16. COSCUP 2024 • Ability to run the same program on

    CPU, GPU, FPGA etc.
 ՄҎࡏ CPU/GPU/FPGA ࣥߦಉҰࢧఔࣜɻ • Very useful for AI/ML workload
 ሣ AI/ML ိ㘸኷ॏཁ • YARV only support CPUɻ
 YARV ୞ࢧԉ CPUɻ • ҟߏܭࢉ Heterogeneous computing
  17. COSCUP 2024 • Register machine for better performance & easier

    to optimize
 ࢖༻࢑ଘثိᩋᏈೳߋ޷ɼߋ༰қ࠷ՂԽ • Static typed to have Monomorphization optimization
 ᯩଶܕผɼߋ༰қ၏Monomorphization • Support Heterogeneous computing
 ࢧԉҟߏܭࢉ զ၇ՄҎ༗Ұݸߋ޷త Ruby IR 䆩ʁ Can we have a better IR for Ruby?
  18. COSCUP 2024 • Multi-Level Intermediate Representation 
 ଟ૚࣍தհᛰ • Part

    of LLVM project.
 LLVM తҰ෦෼ • A extensible common IR syntax for di ff erent compiler backend & frontend.
 ՄᎷॆత௨༻ IR ޠ๏ɼՄ༻ԙଟछฤᩄثલޙ୺ɻ • Provide tool & framework for developing your own IR.
 ఏڙ޻۩࿨ᐽՍိᩋ㟬։ᚙࣗݾత IR MLIR
  19. COSCUP 2024 • Enable compilers to have more language speci

    fi c IR for optimization & diagnostic
 ᩋฤᩄثՄҎೳⴺ༗ߋషۙޠݴత IR ိ၏࠷ՂԽ࿨෼ੳɻ • Support compile to non-CPU based targets like GPU, FPGA.
 ՄҎฤᩄ౸ CPU Ҏ֎తฏ୆૾ੋ GPU, FPGAɻ • Act as a cross language compatibility platform.
 ၏ҝލޠݴత૬༰ੑฏ୆ɻ MLIR త໨ඪ Goals of MLIR
  20. COSCUP 2024 • Compilers: • Clang (ClangIR) • Mojo, a

    super set of Python. • Nx, an Elixir ML tool. • Onnx, an ML tool. MLIR ࢖༻ऀ User of MLIR
  21. COSCUP 2024 • Extensible IR syntax ՄᎷॆత IR ޠ๏ •

    Parser for custom IR ٬੍ IR త Parser • Framework to translate between source language & MLIR
 ࡏိݯޠݴ࿨ MLIR ೭ؒ຋ᩄతᐽՍɻ • Framework to optimize IR ࠷ՂԽ IR తᐽՍɻ • Framework to convert between IRs. ࡏ IR ؒ᫚׵తᐽՍɻ MLIR ޭೳ MLIR features
  22. COSCUP 2024 • Instructions are called Operations, user can de

    fi ne their own operations.
 ࢦྩڣ၏ Operationɼ࢖༻ऀՄҎఆٛࣗݾత Operation • Static single assignment form(SSA) , make optimization easier.
 ᄸҰොᆴɼߋ༰қ࠷ՂԽɻ • Strong static typed. ᯩଶڧܕผ • Block based syntax instead of Φ(PHI) node. 
 ࢖༻ block ိऔ୅ Φ(PHI) nodeɻ MLIR IR ޠ๏ಛ৭ MLIR IR syntax features
  23. COSCUP 2024 module { %0 = ruby.constant_int "40" : !ruby.int

    %1 = ruby.constant_int "2" : !ruby.int %2 = ruby.call %0 : !ruby.int -> "+"(%1) : (!ruby.int) -> ! ruby.opaque_object %3 = ruby.local_variable_write "coscup" = %2 {rb_stmt = true} : ! ruby.opaque_object } foo=40+2 MLIR IR
  24. COSCUP 2024 module { %0 = ruby.def "hello" (required_args :

    ["name"]) : (required_args : [! ruby.opaque_object]) -> !ruby.opaque_object { %1 = ruby.local_variable_read "name" : !ruby.opaque_object ruby.return %1 : !ruby.opaque_object } : !ruby.sym } MLIR block
  25. COSCUP 2024 • A set of IR de fi nition

    with it's own tools is called a dialect in MLIR.
 Ұ૊ IR ఆٛɼ౥഑ଞࣗݾత޻۩बڣ၏Ұݸ MLIR ํݴɻ • Operation(IR) de fi nitions. Operation ఆٛ • A translator that convert to/from MLIR to target language.
 ࡏ໨ඪޠݴ࿨ MLIR ೭ؒ᫚׵త຋ᩄ޻۩ɻ • Optimization passes to optimize the IR. IR త࠷ՂԽྲྀఔɻ • Converter to convert from/to other MLIR dialects. 
 ࡏ MLIR ํݴؒ᫚׵త᫚׵޻۩ɻ ॄኄੋ MLIR ํݴ? What is a MLIR dialect?
  26. COSCUP 2024 • https://github.com/johnlinvc/mlir-dialect-ruby • Current Features: • Ruby Operations

    de fi nition in MLIR
 MLIR Ruby Operation ఆٛ • Ruby Optimization Passes.
 Ruby ࠷ՂԽྲྀఔ • Translate from Ruby code to IR. ኺ Ruby ຋ᩄ੒ IRɻ • Translate from IR back to Ruby code. ኺ IR ຋ᩄճ Ruby MLIR Ruby dialect
  27. COSCUP 2024 MLIR Ruby dialect Ruby MLIR Ruby Optimization passes

    Ruby MLIR Ruby ISEQ YARV MLIR LLVM IR Machine Code
  28. COSCUP 2024 MLIR Ruby dialect Ruby MLIR Ruby Optimization passes

    Ruby MLIR Ruby ISEQ YARV MLIR LLVM IR Machine Code
  29. COSCUP 2024 • Use tablegen, a tool from LLVM ༻

    MLIR ఆٛ Ruby IR Define a Ruby IR with MLIR def Ruby_LocalVariableWriteOp : Ruby_Op<"local_variable_write", [SameOperandsAndResultType]> { let arguments = (ins StrAttr:$var_name, Ruby_AnyType: $input); let results = (outs Ruby_AnyType:$res); let assemblyFormat = [{ $var_name `=` $input attr-dict `:` type($res) }]; }
  30. COSCUP 2024 MLIR Ruby dialect Ruby MLIR Ruby Optimization passes

    Ruby MLIR Ruby ISEQ YARV MLIR LLVM IR Machine Code
  31. COSCUP 2024 • Prism is the new cross implementation parser

    for Ruby.
 Prism ੋ৽తލመ࡞ Ruby Parserɻ • Has richer info than the 'Parser' gem.
 ൺى 'Parser' gem ༗ߋଟతࢿ㘤ɻ • Provides Ruby,C & JS API.
 ఏڙ Ruby, C & JS API ༻ Prism ိ Parse Ruby Parse Ruby with Prism
  32. COSCUP 2024 class PrismLoader def initialize(program) @prog = program @ast

    = Prism.parse(@prog) @visitor = PrismVisitor.new @module = nil end end ༻ Prism ိ Parse Ruby Parse Ruby with Prism
  33. COSCUP 2024 ༻ Prism ိ Parse Ruby Parse Ruby with

    Prism @ ProgramNode (location: (1,0)-(1,11)) ├── locals: [:coscup] └── statements: @ StatementsNode (location: (1,0)-(1,11)) └── body: (length: 1) └── @ LocalVariableWriteNode (location: (1,0)-(1,11)) ├── name: :coscup ├── depth: 0 ├── name_loc: (1,0)-(1,6) = "coscup" ├── value: │ @ CallNode (location: (1,7)-(1,11)) │ ├── flags: ∅ │ ├── receiver: │ │ @ IntegerNode (location: (1,7)-(1,9)) │ │ └── flags: decimal │ ├── call_operator_loc: ∅ │ ├── name: :+ │ ├── message_loc: (1,9)-(1,10) = "+" │ ├── opening_loc: ∅ │ ├── arguments: │ │ @ ArgumentsNode (location: (1,10)-(1,11)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (1,10)-(1,11)) │ │ └── flags: decimal coscup = 40 + 2
  34. COSCUP 2024 ༻ Prism ိ Parse Ruby Parse Ruby with

    Prism └── @ LocalVariableWriteNode (location: (1,0)-(1,11)) ├── name: :coscup ├── value: │ @ CallNode (location: (1,7)-(1,11)) │ ├── receiver: │ │ @ IntegerNode (location: (1,7)-(1,9)) │ │ └── flags: decimal │ ├── name: :+ │ ├── arguments: │ │ @ ArgumentsNode (location: (1,10)-(1,11)) │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (1,10)-(1,11)) │ │ └── flags: decimal coscup = 40 + 2
  35. COSCUP 2024 • Use the Prism Visitor to Emit IR.


    ࢖༻ Prism Visitor ိ༌ग़ IR • Create SSA vars on the fl y.
 ಈଶ㗞ੜ SSA ᏓᏐ໊ ኺ AST ༌ग़ IR Emit IR from AST
  36. COSCUP 2024 class PrismVisitor def visit(node) type = node.type.to_s method_name

    = "visit_#{type.split("_")[..-2].join("_")}" raise "not implemented: #{method_name}" unless respond_to? (method_name) send(method_name, node) end end ኺ AST ༌ग़ IR Emit IR from AST
  37. COSCUP 2024 class PrismVisitor def visit_integer(node) build_int_stmt(node.value) end def build_int_stmt(value)

    with_new_ssa_var do |ssa_var, attr_dict| ret_type = "!ruby.int" @stmts << " #{ssa_var} = ruby.constant_int \"#{value}\" #{attr_dict} : #{ret_type}" ret_type end end end ኺ AST ༌ग़ IR Emit IR from AST
  38. COSCUP 2024 %0 = ruby.constant_int "40" : !ruby.int %1 =

    ruby.constant_int "2" : !ruby.int %2 = ruby.call %0 : !ruby.int -> "+"(%1) : (!ruby.int) -> ! ruby.opaque_object %3 = ruby.local_variable_write "coscup" = %2 {rb_stmt = true} : ! ruby.opaque_object Emit IR from AST ኺ AST ༌ग़ IR coscup = 40 + 2
  39. COSCUP 2024 MLIR Ruby dialect Ruby MLIR Ruby Optimization passes

    Ruby MLIR Ruby ISEQ YARV MLIR LLVM IR Machine Code
  40. COSCUP 2024 • Use the MLIR Pass infrastructure to optimize

    the IR.
 ࢖༻ MLIR Pass Սߏိ࠷ՂԽ IR • Rewrite Patterns: Pattern match an Operation DAG, then perform edit/replace/delete on the DAG.
 ሣ Operation DAG ࡞ pattern matchɼ࠶ሣDAG ၏मվ/औ୅/႟আ • Fold: Replace an Operation with another Operation or a Value.
 औ୅ಛఆత Operation ҃ੋ᫚׵੒ Valueɻ ࠷ՂԽԋࢉ๏ Optimization passes
  41. COSCUP 2024 • Use the Pattern Rewrite
 ࢖༻ Pattern Rewrite

    • Convert the `call` op with an `add` op when method name is "+". and has 2 arguments.
 ೗Ռ `call` op త method ੋ "+" ࣕ׌༗ၷݸჩᏐత࿩ɼ᫚׵੒ `add` opɻ Specialization pass
  42. COSCUP 2024 %0 = ruby.constant_int "40" : !ruby.int %1 =

    ruby.constant_int "2" : !ruby.int %2 = ruby.call %0 : !ruby.int -> "+"(%1) : (!ruby.int) -> ! ruby.opaque_object %3 = ruby.local_variable_write "coscup" = %2 {rb_stmt = true} : ! ruby.opaque_object Specialization pass coscup = 40 + 2
  43. COSCUP 2024 LogicalResult matchAndRewrite(CallOp op, PatternRewriter &rewriter) const final {

    if (op.getMethodName() != "+") { return failure(); } if (op.getArgs().size() != 1) { return failure(); } auto lhs = op.getCallee(); if (lhs == ::mlir::Value()) { return failure(); } auto rhs = op.getArgs()[0]; auto resultType = lhs.getType(); rewriter.replaceOpWithNewOp<AddOp>(op, resultType, lhs, rhs); return success(); } Specialization pass
  44. COSCUP 2024 %0 = ruby.constant_int "40" {} : !ruby.int %1

    = ruby.constant_int "2" {} : !ruby.int %2 = ruby.add %0, %1 : (!ruby.int, !ruby.int) -> !ruby.int %3 = ruby.local_variable_write "coscup"= %2 {rb_stmt = true} : ! ruby.opaque_object Specialization pass coscup = 40 + 2
  45. COSCUP 2024 • Rewrite does not edit the subsequent calls,

    so the return type must keep the same. ܕผࡨޡ Type error after specialization %0 = ruby.constant_int "40" {} : !ruby.int %1 = ruby.constant_int "2" {} : !ruby.int %2 = ruby.add %0, %1 : (!ruby.int, !ruby.int) -> !ruby.int %3 = ruby.local_variable_write "coscup"= %2 {rb_stmt = true} : !ruby.opaque_object error: use of value '%2' expects different type than prior uses: '!ruby.opaque_object' vs '!ruby.int' coscup = 40 + 2
  46. COSCUP 2024 • Use the Pattern Rewrite • Convert the

    `call` op with an `add` op when method name is "+". and has 2 arguments. • Add a `cast` op at the end to maintain the result type. Specialization pass
  47. COSCUP 2024 LogicalResult matchAndRewrite(CallOp op, PatternRewriter &rewriter) const final {

    ... auto newAdd = rewriter.create<AddOp>(op.getLoc(), resultType, lhs, rhs); rewriter.replaceOpWithNewOp<CastOp>(op, op.getRes().getType(), newAdd); return success(); } Specialization pass
  48. COSCUP 2024 %0 = ruby.constant_int "40" : !ruby.int %1 =

    ruby.constant_int "2" : !ruby.int %2 = ruby.add %0, %1 : (!ruby.int, !ruby.int) -> !ruby.int %3 = ruby.cast %2 : !ruby.int -> !ruby.opaque_object %4 = ruby.local_variable_write "coscup" = %3 {rb_stmt = true} : ! ruby.opaque_object Specialization pass coscup = 40 + 2
  49. COSCUP 2024 • Use Pattern rewrite
 ࢖༻ Pattern rewrite •

    Change the input type & value.
 վᏓ input Type & input Value • The unused cast will be removed automatically.
 ᔒ༗༻౸త cast ။ࣗಈඃҠআ ܕผਪᏗ Type Inference Pass
  50. COSCUP 2024 %0 = ruby.constant_int "40" : !ruby.int %1 =

    ruby.constant_int "2" : !ruby.int %2 = ruby.add %0, %1 : (!ruby.int, !ruby.int) -> !ruby.int %3 = ruby.cast %2 : !ruby.int -> !ruby.opaque_object %4 = ruby.local_variable_write "coscup" = %3 {rb_stmt = true} : ! ruby.opaque_object ܕผਪᏗ Type Inference Pass coscup = 40 + 2
  51. COSCUP 2024 LogicalResult matchAndRewrite(LocalVariableWriteOp op, PatternRewriter &rewriter) const final {

    auto inputOp = op.getInput().getDefiningOp<CastOp>(); if (!inputOp) { return failure(); } auto newOp = rewriter.create<LocalVariableWriteOp>( op.getLoc(), inputOp.getInput().getType(), op.getVarName(), inputOp.getInput()); newOp->setAttrs(op->getAttrs()); rewriter.replaceOp(op, newOp.getOperation()); return success(); } ܕผਪᏗ Type Inference Pass
  52. COSCUP 2024 %0 = ruby.constant_int "40" : !ruby.int %1 =

    ruby.constant_int "2" : !ruby.int %2 = ruby.add %0, %1 : (!ruby.int, !ruby.int) -> !ruby.int %3 = ruby.local_variable_write "coscup" = %2 {rb_stmt = true} : !ruby.int ܕผਪᏗ Type Inference Pass coscup = 40 + 2
  53. COSCUP 2024 • Make the IR easier to optimize in

    following passes.
 ᩋ IR ࡏޙ᠃త Pass தߋ޷࠷ՂԽɻ • Run the fold method automatically.
 ။ࣗಈ䋯 foldɻ • Can add additional pass as part of canonicalize.
 ՄҎ⃧Ճֹ֎త pass ਐنൣԽ pass نൣԽ pass Canonicalization pass
  54. COSCUP 2024 • Part of the canonicalization pass
 نൣԽతҰ෦෼ •

    Use the fold system to remove constant values.
 ࢖༻ fold ိҠআᯩଶᆴɻ
 ৗᏐંᙟ Constant folding
  55. COSCUP 2024 ৗᏐંᙟ Constant folding %0 = ruby.constant_int "40" :

    !ruby.int %1 = ruby.constant_int "2" : !ruby.int %2 = ruby.add %0, %1 : (!ruby.int, !ruby.int) -> !ruby.int %3 = ruby.local_variable_write "coscup" = %2 {rb_stmt = true} : !ruby.int coscup = 40 + 2
  56. COSCUP 2024 ৗᏐંᙟ Constant folding def Ruby_AddOp : Ruby_BinaryOp<"add"> {

    let summary = "Add two objects"; let description = [{ This operation adds two objects. }]; let hasFolder = 1; } coscup = 40 + 2
  57. COSCUP 2024 ৗᏐંᙟ Constant folding OpFoldResult AddOp::fold(AddOp::FoldAdaptor adaptor){ auto operands

    = adaptor.getOperands(); auto strLhs = operands[0].dyn_cast<StringAttr>(); auto strRhs = operands[1].dyn_cast<StringAttr>(); if (!strLhs || !strRhs) return nullptr; auto lhsInt = ::std::stoi(strLhs.getValue().str()); auto rhsInt = ::std::stoi(strRhs.getValue().str()); auto sum = lhsInt + rhsInt; auto sumStr = ::std::to_string(sum); auto str = StringAttr::get(getContext(), sumStr); return str; } coscup = 40 + 2
  58. COSCUP 2024 ৗᏐંᙟ Constant folding Operation *RubyDialect::materializeConstant(OpBuilder &builder, Attribute value,

    Type type, Location loc) { return llvm::TypeSwitch<Type, Operation *>(type) .Case<IntegerType>([&](auto type) { auto strAttr = value.dyn_cast<StringAttr>(); return strAttr ? builder.create<ConstantIntOp>(loc, type, strAttr) : nullptr; }) .Default([&](auto type) { return nullptr; }); } coscup = 40 + 2
  59. COSCUP 2024 ৗᏐંᙟ Constant folding %0 = ruby.constant_int "42" :

    !ruby.int %1 = ruby.local_variable_write "coscup" = %0 {rb_stmt = true} : !ruby.int coscup = 40 + 2
  60. COSCUP 2024 • Use the MLIR translate tools.
 ࢖༻ MLIR

    ຋ᩄ޻۩ɻ • Translate an op when visited by the visitor.
 ຋ᩄඃ visitor ๚໰౸త op. • Use a rb_stmt attribute to identify the top level statements.
 ࢖༻ rb_stmt attribute ိ൑ผ࠷্૚త statementsɻ ༌ग़ Ruby ఔࣜᛰ Emit Ruby code
  61. COSCUP 2024 MLIR Ruby dialect Ruby MLIR Ruby Optimization passes

    Ruby MLIR Ruby ISEQ YARV MLIR LLVM IR Machine Code
  62. COSCUP 2024 ༌ग़ Ruby ఔࣜᛰ Emit Ruby code %0 =

    ruby.constant_int "42" : !ruby.int %1 = ruby.local_variable_write "coscup" = %0 {rb_stmt = true} : !ruby.int coscup = 40 + 2
  63. COSCUP 2024 ༌ग़ Ruby ఔࣜᛰ Emit Ruby code static LogicalResult

    printOperation(RubyEmitter &emitter, ruby::LocalVariableWriteOp op, bool skipStmtCheck = false) { if (!op->getAttrDictionary().get("rb_stmt") && !skipStmtCheck) return success(); Attribute value = op.getVarNameAttr(); raw_ostream &os = emitter.ostream(); if(!isa<StringAttr>(value)) return failure(); if (auto sAttr = dyn_cast<StringAttr>(value)) os << sAttr.getValue().str(); os << " = "; if( failed(emitter.emitOperand(op.getInput())) ) return failure(); if (op->getAttrDictionary().get("rb_stmt")) os << "\n"; return success(); }
  64. COSCUP 2024 MLIR Ruby dialect Ruby MLIR Ruby Optimization passes

    Ruby MLIR Ruby ISEQ YARV MLIR LLVM IR Machine Code
  65. COSCUP 2024 • Complete translator between MLIR & Ruby. 


    ׬੔ಘࡏ Ruby & MLIR ؒ᫚׵ɻ • More Optimization Passes ߋଟత࠷ՂԽԋࢉ๏ɻ • Another dialect for YARV ISEQ? 㠥Ұݸ YARV ISEQ dialect ? • Act as a Rubocop backend? ᙛ࡞ Rubocop తޙ୺ʁ • AOT compiling for Ruby? ሣ Ruby ၏ఏલฤᩄʁ • Heterogeneous computing for Ruby? Ruby ҟߏܭࢉʁ Future plans ະိܭᙘ
  66. COSCUP 2024 • IR is a tool for compiler to

    optimize & validate programs.
 தհᛰ(IR) ੋฤᩄث༻ိ࠷ՂԽ࿨ᱛᨽఔࣜత޻۩ • It's time to have a new IR for Ruby.
 Ruby ࠩෆଟՄҎ༗Ұݸ৽ IR ྃ • MLIR is a state of art IR tool.
 MLIR ੋҰݸઌਐత IR ޻۩ • MLIR Ruby can optimize Ruby.
 MLIR Ruby ՄҎ࠷ՂԽ Ruby ݁࿦ Takeaways