本文地址:https://www.cnblogs.com/wanger-sjtu/p/17573212.html

TVM在编译过程中,经历了

graph LR
A[3rd IR] --> B[Relay IR]
B --> C[TIR]
C --> D[LLVM IR]
C -->E[Source]

这一系列的过程。其中在生成cpu、rocm、nvptx、hexagon等平台的相关代码的时候,会先由TVM的TIR转换为LLVM IR,在后续由LLVM生成相关的机器码。

这一步是由tvm::codegen::Build调用转换的。

runtime::Module Build(IRModule mod, Target target) {
if (transform::PassContext::Current()
->GetConfig<Bool>("tir.disable_assert", Bool(false))
.value()) {
mod = tir::transform::SkipAssert()(mod);
}
auto target_attr_map = tvm::TargetKind::GetAttrMap<FTVMTIRToRuntime>("TIRToRuntime");
if (target_attr_map.count(target->kind)) {
return target_attr_map[target->kind](mod, target);
} // the build function.
std::string build_f_name = "target.build." + target->kind->name;
const PackedFunc* bf = runtime::Registry::Get(build_f_name);
ICHECK(bf != nullptr) << build_f_name << " is not enabled";
return (*bf)(mod, target);
}

在LLVM相关的target时候,这里的build_f_name就是target.build.llvm

这时候会走到

TVM_REGISTER_GLOBAL("target.build.llvm")
.set_body_typed([](IRModule mod, Target target) -> runtime::Module {
auto n = make_object<LLVMModuleNode>();
n->Init(mod, target);
return runtime::Module(n);
});

Init函数中创建codegen的具体类:


void LLVMModuleNode::Init(const IRModule& mod, const Target& target) {
llvm_instance_ = std::make_unique<LLVMInstance>();
With<LLVMTarget> llvm_target(*llvm_instance_, target);
llvm::TargetMachine* tm = llvm_target->GetOrCreateTargetMachine();
// 这里会根据target得到不同的codegen的实现类
std::unique_ptr<CodeGenLLVM> cg = CodeGenLLVM::Create(llvm_target.get()); std::string entry_func;
/*
skip crt/cpp systemlib options
*/
for (auto kv : mod->functions) {
if (!kv.second->IsInstance<PrimFuncNode>()) {
// (@jroesch): we relax constraints here, Relay functions will just be ignored.
DLOG(INFO) << "Can only lower IR Module with PrimFuncs, but got " << kv.second->GetTypeKey();
continue;
}
auto f = Downcast<PrimFunc>(kv.second);
auto global_symbol = f->GetAttr<String>(tvm::attr::kGlobalSymbol);
bool is_entry_func = f->HasNonzeroAttr(tir::attr::kIsEntryFunc); if (global_symbol) {
function_names_.push_back(global_symbol.value());
if (is_entry_func) {
entry_func = global_symbol.value();
}
}
}
// 初始化CodeGenLLVM, 会产生builder_, module_等llvm 中codegen需要的基础数据结构
cg->Init("TVMMod", llvm_target.get(), system_lib_prefix,
system_lib_prefix.defined(),
target_c_runtime);
cg->SetFastMathFlags(llvm_target->GetFastMathFlags());
// 核心功能,tir 转化为llvm ir就在此
cg->AddFunctionsOrdered(mod->functions.begin(), mod->functions.end());
if (entry_func.length() != 0) {
cg->AddMainFunction(entry_func);
} module_owning_ptr_ = cg->Finish();
module_ = module_owning_ptr_.get();
llvm_target->SetTargetMetadata(module_);
module_->addModuleFlag(llvm::Module::Override, "Debug Info Version",
llvm::DEBUG_METADATA_VERSION); }

TVM 代码生成—TIR to LLVM IR的更多相关文章

  1. 手写token解析器、语法解析器、LLVM IR生成器(GO语言)

    最近开始尝试用go写点东西,正好在看LLVM的资料,就写了点相关的内容 - 前端解析器+中间代码生成(本地代码的汇编.执行则靠LLVM工具链完成) https://github.com/daibinh ...

  2. TVM代码生成codegen

    TVM代码生成codegen 硬件后端提供程序(例如Intel,NVIDIA,ARM等),提供诸如cuBLAS或cuDNN之类的内核库以及许多常用的深度学习内核,或者提供框架例,如带有图形引擎的DNN ...

  3. LLVM 笔记(五)—— LLVM IR

    ilocker:关注 Android 安全(新手) QQ: 2597294287 LLVM 的 IR (Intermediate Representation) 是其设计中的最重要的部分.优化器在进行 ...

  4. clang -O3 for循环的LLVM IR

    O3都是怪物,这里分析的是CLANG怪物,示例程序遍历数组每个元素然后放大. void foreach_scale(int arr[],int elem){ for(int i=0;i<elem ...

  5. TVM设计与构架构建

    TVM设计与构架构建 本文档适用于希望了解TVM体系结构和/或在项目上进行积极开发的开发人员.该页面的组织如下: 实例编译流程Example Compilation Flow描述TVM把一个模型的高级 ...

  6. TVM 架构设计

    TVM 架构设计 本文面向希望了解TVM体系结构和/或积极参与项目开发的开发人员. 主要内容如下: 示例编译流程概述了TVM将模型的高级概念转换为可部署模块的步骤. 逻辑架构组件部分描述逻辑组件.针对 ...

  7. TVM:

    Hello TVM  发表于 2019-06-29 TVM 是什么?A compiler stack,graph level / operator level optimization,目的是(不同框 ...

  8. 关于llvm kaleidoscope: 记一次Debug血泪之路

    简而言之,慎(bu)用(yong)全局变量! 这次debug基本上花了我一周的时间,我基本上是晚上9点30下自习回然后调试到11点30,如此反复一周直到今天周五终于解决了,,以前都听说前辈们 说尽量不 ...

  9. Impala中的代码生成技术

    Cloudera Impala是一种为Hadoop生态系统打造的开源MPP(massive parallel processing)数据库,它主要为分析型查询负载而设计,而非OLTP.Impala能最 ...

  10. LLVM 概览

    下面是 LLVM 首页对 LLVM 介绍的中文翻译. LLVM 项目是一系列模块化.可重用和工具链技术的集合.不必在意它的名称,LLVM 和之前的虚拟机基本没什么关系了,然而也确实提供了对构建这些虚拟 ...

随机推荐

  1. 内置方法,序列化模块pickle和json---day15

    1.内置方法 ads 绝对值函数 val = -16 res = abs(val) print(res) #16 round 四舍五入(n.5 n为偶数则舍去,n.5 n为奇数 则进一) 奇进偶不进 ...

  2. ZYNQ核心板及其底板开源啦!

    Hello-FPGA ZYNQ 设计开源啦! 开源ZYNQ核心板 + 底板 硬件设计.软件设计,软件设计使用裸机演示,演示了如何使用AXI DMA等关键dma 模块 欢迎加QQ 讨论 94755958 ...

  3. Golang标准库之bytes介绍

    本次主要介绍golang中的标准库bytes,基本上参考了 字节 | bytes .Golang标准库--bytes 文章. bytes库主要包含 5 大部分,即: 常量 变量 函数 Buffer R ...

  4. 【Azure Developer】Go语言调用Azure SDK如何登录到中国区Azure环境

    问题描述 在 "使用 Azure SDK for Go 进行 Azure 身份验证" 文章中的 Go 示例代码进行登录Azure时,默认指向的是Globa Azure.当只修改AA ...

  5. linux服务器文件实时同步

    linux服务器文件实时同步 1 背景说明 在做系统集群部署时,涉及到两个或多个服务器之间文件同步.在软件层面linux服务环境找到以下两种同步方式 利用linux NFS功能将网络共享文件挂载成本地 ...

  6. Nebula Graph 源码解读系列|客户端的通信秘密——fbthrift

    概述 Nebula Clients 给用户提供了多种编程语言的 API 用于和 Nebula Graph 交互,并且对服务端返回的数据结构进行了重新封装,便于用户使用. 目前 Nebula Clien ...

  7. 导入Excel文件的时候公式为【#Ref!】应该怎么解决?

    前言 在我们使用Excel时,经常会遇到一个问题,就是导入Excel时公式显示为[#Ref!]的情况.这通常是因为公式中引用的单元格已被删除或对应的工作表被删除,导致原公式无法识别对应的参数而显示为[ ...

  8. 压测中TPS上不去的几种原因及分析?

    1. 服务器资源限制:服务器的硬件资源(如 CPU.内存.磁盘)可能不足以处理大量的请求.在高负载情况下,服务器可能无法及时响应所有的请求,导致 TPS 上不去.解决方法可以考虑升级硬件资源或通过负载 ...

  9. ConfigMap挂载与Subpath在Nginx容器中的应用

    本文分享自华为云社区<nginx.conf以configmap文件形式挂载到nginx容器中以及subpath使用场景>,作者:可以交个朋友. 背景 nginx.conf通过configm ...

  10. 有n步台阶,一次只能上1步或2步,共有多少种走法

    循环迭代:   1 public class steps { 2 public int js(int n) { 3 int one = 2; //初始化为第三级台阶最后跨一步的走法 4 int two ...