前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >MLIR入门教程1-Toy语言以及AST

MLIR入门教程1-Toy语言以及AST

作者头像
hunterzju
发布2021-12-09 14:10:17
2K0
发布2021-12-09 14:10:17
举报
文章被收录于专栏:编译器开发

上周初步完成了LLVM入门教程的翻译,这几天了解了下LLVM项目中的MLIR架构,整体感觉MLIR目的是在高层语言转换到机器码的过程中能够重用更多的优化,核心思想是采用了多层IR,并定义了IR间相互转换的框架。本系列文章将对LLVM项目中的MLIR教程进行翻译。

受限于笔者个人的认知水平,翻译效果可能不是很理想,翻译原始文档也会放在github上,供大家参考,如发现问题也欢迎提PR或者Issue:

Toy教程

本教程基于MLIR构建了一中基础的Toy语言实现。本教程的目标是介绍MLIR的概念;特别是方言(dialects)如何帮助轻松支持特定于语言的构造和转换,同时仍然提供一条降低到LLVM或其他代码生成(codegen)基础设施的简单途径。本教程基于LLVM Kaleidoscope Tutorial的模型

本教程假定您已经克隆并构建了MLIR;如果您还没有这样做,请参阅MLIR入门.

本教程分为以下几章:

  • 第1章:Toy语言简介及其AST的定义。
  • 第2章:遍历AST以发出MLIR中的方言,介绍基本的MLIR概念。这里我们展示了如何开始将语义附加到MLIR中的自定义操作。
  • 第3章:使用模式重写系统的高级语言特定优化。
  • 第4章:使用接口编写与通用方言无关的转换。在这里,我们将展示如何将特定的方言信息插入到通用转换中,如维度推断和内联
  • 第5章:部分降低到较低级别的方言。为了优化,我们将把一些高级语言特定语义转换为面向仿射的通用方言
  • 第6章:降低到LLVM和代码生成。在这里,我们将把LLVM IR作为代码生成的目标,并详细介绍降低框架的更多内容。
  • 第7章:扩展Toy:添加对复合类型的支持。我们将演示如何将自定义类型添加到MLIR,以及它如何适应现有流程。

第一章将介绍Toy语言和AST。

第1章:玩具语言和AST

语言

本教程将用一种简单语言来说明,我们称之为“玩具”(命名很难……)。Toy是一种基于张量的语言,允许您定义函数、执行一些数学计算和打印结果。

考虑到我们希望保持简单,编码生成将被限制为秩<=2的张量,并且Toy中唯一的数据类型是64位浮点类型(在C中也称为“DOUBLE”)。因此,所有值都是隐式双精度的,‘Values`是不可变的(即,每个操作都返回一个新分配的值),并且释放是自动管理的。但长篇大论已经足够了;没有什么比通过一个例子来更好地理解更好的了:

代码语言:javascript
复制
def main() {
  # Define a variable `a` with shape <2, 3>, initialized with the literal value.
  # The shape is inferred from the supplied literal.
  var a = [[1, 2, 3], [4, 5, 6]];

  # b is identical to a, the literal tensor is implicitly reshaped: defining new
  # variables is the way to reshape tensors (element count must match).
  var b<2, 3> = [1, 2, 3, 4, 5, 6];

  # transpose() and print() are the only builtin, the following will transpose
  # a and b and perform an element-wise multiplication before printing the result.
  print(transpose(a) * transpose(b));
}

类型检查是通过类型推断静态执行的;该语言仅在需要时要求类型声明来指定张量形状。函数是通用的:它们的参数是为无秩的(换句话说,我们知道这些是张量,但我们不知道它们的维数)。它们专门用于调用点的每个新发现的签名。让我们通过添加一个用户定义函数来回顾上一个示例:

代码语言:javascript
复制
# User defined generic function that operates on unknown shaped arguments.
def multiply_transpose(a, b) {
  return transpose(a) * transpose(b);
}

def main() {
  # Define a variable `a` with shape <2, 3>, initialized with the literal value.
  var a = [[1, 2, 3], [4, 5, 6]];
  var b<2, 3> = [1, 2, 3, 4, 5, 6];

  # This call will specialize `multiply_transpose` with <2, 3> for both
  # arguments and deduce a return type of <3, 2> in initialization of `c`.
  var c = multiply_transpose(a, b);

  # A second call to `multiply_transpose` with <2, 3> for both arguments will
  # reuse the previously specialized and inferred version and return <3, 2>.
  var d = multiply_transpose(b, a);

  # A new call with <3, 2> (instead of <2, 3>) for both dimensions will
  # trigger another specialization of `multiply_transpose`.
  var e = multiply_transpose(c, d);

  # Finally, calling into `multiply_transpose` with incompatible shape will
  # trigger a shape inference error.
  var f = multiply_transpose(transpose(a), c);
}

抽象语法树AST

上面代码中的AST相当简单;下面是它的一个转储:

代码语言:javascript
复制
Module:
  Function 
    Proto 'multiply_transpose' @test/Examples/Toy/Ch1/ast.toy:4:1'
    Params: [a, b]
    Block {
      Return
        BinOp: * @test/Examples/Toy/Ch1/ast.toy:5:25
          Call 'transpose' [ @test/Examples/Toy/Ch1/ast.toy:5:10
            var: a @test/Examples/Toy/Ch1/ast.toy:5:20
          ]
          Call 'transpose' [ @test/Examples/Toy/Ch1/ast.toy:5:25
            var: b @test/Examples/Toy/Ch1/ast.toy:5:35
          ]
    } // Block
  Function 
    Proto 'main' @test/Examples/Toy/Ch1/ast.toy:8:1'
    Params: []
    Block {
      VarDecl a<> @test/Examples/Toy/Ch1/ast.toy:11:3
        Literal: <2, 3>[ <3>[ 1.000000e+00, 2.000000e+00, 3.000000e+00], <3>[ 4.000000e+00, 5.000000e+00, 6.000000e+00]] @test/Examples/Toy/Ch1/ast.toy:11:11
      VarDecl b<2, 3> @test/Examples/Toy/Ch1/ast.toy:15:3
        Literal: <6>[ 1.000000e+00, 2.000000e+00, 3.000000e+00, 4.000000e+00, 5.000000e+00, 6.000000e+00] @test/Examples/Toy/Ch1/ast.toy:15:17
      VarDecl c<> @test/Examples/Toy/Ch1/ast.toy:19:3
        Call 'multiply_transpose' [ @test/Examples/Toy/Ch1/ast.toy:19:11
          var: a @test/Examples/Toy/Ch1/ast.toy:19:30
          var: b @test/Examples/Toy/Ch1/ast.toy:19:33
        ]
      VarDecl d<> @test/Examples/Toy/Ch1/ast.toy:22:3
        Call 'multiply_transpose' [ @test/Examples/Toy/Ch1/ast.toy:22:11
          var: b @test/Examples/Toy/Ch1/ast.toy:22:30
          var: a @test/Examples/Toy/Ch1/ast.toy:22:33
        ]
      VarDecl e<> @test/Examples/Toy/Ch1/ast.toy:25:3
        Call 'multiply_transpose' [ @test/Examples/Toy/Ch1/ast.toy:25:11
          var: b @test/Examples/Toy/Ch1/ast.toy:25:30
          var: c @test/Examples/Toy/Ch1/ast.toy:25:33
        ]
      VarDecl f<> @test/Examples/Toy/Ch1/ast.toy:28:3
        Call 'multiply_transpose' [ @test/Examples/Toy/Ch1/ast.toy:28:11
          Call 'transpose' [ @test/Examples/Toy/Ch1/ast.toy:28:30
            var: a @test/Examples/Toy/Ch1/ast.toy:28:40
          ]
          var: c @test/Examples/Toy/Ch1/ast.toy:28:44
        ]
    } // Block

您在Examples/Toy/Ch1/目录中使用示例重现此结果;尝试运行path/to/build/bin/toyc-ch1test/Examples/Toy/Ch1/ast.toy -emit=ast

lexer的代码相当简单;所有代码都在一个头文件中:Examples/Toy/Ch1/Include/Toy/Lexfor.h。解析器可以在Examples/Toy/ch1/include/toy/Parser.h中找到,它是一个递归下降解析器。如果您不熟悉这样的词法分析器/解析器,它们与Kaleidcope Tutorial的前两章中详细介绍的LLVM Kaleidoscope非常相似.

下一章将演示如何将此AST转换为MLIR。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Toy教程
  • 第1章:玩具语言和AST
  • 语言
  • 抽象语法树AST
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档