当前位置:网站首页>LLVM - 生成for循环
LLVM - 生成for循环
2022-04-23 14:11:00 【Mrpre】
1、生成函数
2、使用Phi表达式实现for循环
3、本例中,KaleidoscopeJIT源码位于./llvm-8.0.1.src/examples/Kaleidoscope/include/KaleidoscopeJIT.h
Phi的概念可参考https://stackoverflow.com/questions/11485531/what-exactly-phi-instruction-does-and-how-to-use-it-in-llvm
本例中,生成的llvm ir如下:
define double @myfor(double %a) {
myentry:
br label %loop
loop: ; preds = %loop, %myentry
%i = phi double [ 0.000000e+00, %myentry ], [ %nextvar, %loop ]
%a1 = fadd double %a, 2.000000e+00
%nextvar = fadd double 1.000000e+00, %i
%cmptmp = fcmp ult double %i, 1.000000e+01
br i1 %cmptmp, label %loop, label %afterloop
afterloop: ; preds = %loop
ret double %a1
}
phi的逻辑,如果从 myentry 来(比如刚进来),则 %i就是 0,否则%i 的值就是%nextvar(比如循环完一次)
代码:
#include "./llvm-8.0.1.src/examples/Kaleidoscope/include/KaleidoscopeJIT.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Verifier.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Transforms/InstCombine/InstCombine.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Scalar/GVN.h"
#include <string>
#include <vector>
#include <iostream>
using namespace std;
using namespace llvm;
using namespace llvm::orc;
//LLVM items
static LLVMContext TheContext;
static IRBuilder<> Builder(TheContext);
static std::unique_ptr<Module> TheModule;
//JIT
static std::unique_ptr<KaleidoscopeJIT> TheJIT;
/* *double myfor(double a) *{ * for(i = 0; i < a; i++) { * a = a + 1 * } * return a *} * */
int main()
{
InitializeNativeTarget();
InitializeNativeTargetAsmPrinter();
//init module
TheModule = llvm::make_unique<Module>("myjit", TheContext);
//used to be runned by jit later
TheJIT = llvm::make_unique<KaleidoscopeJIT>();
TheModule->setDataLayout(TheJIT->getTargetMachine().createDataLayout());
//define the args
vector<std::string> ArgNames;
//myfor has 1 args
ArgNames.push_back(string("a"));
//make the 1 args attach to LLVM Type::double
std::vector<Type *> Doubles(ArgNames.size(), Type::getDoubleTy(TheContext));
//generate llvm function type
FunctionType *FT = FunctionType::get(Type::getDoubleTy(TheContext), Doubles, false);
//Create function whose FunctionType is FT
Function *TheFunction = Function::Create(FT, Function::ExternalLinkage, "myfor", TheModule.get());
//give the name of Function args and save the args as innerargs
unsigned Idx = 0;
std::vector<Value *>innerargs;
for (auto &Arg : TheFunction->args()) {
Arg.setName(ArgNames[Idx++]);
innerargs.push_back(&Arg);
}
//this function's basic block
BasicBlock *BB = BasicBlock::Create(TheContext, "myentry", TheFunction);
//create the loop BasicBlock
BasicBlock *LoopBB = BasicBlock::Create(TheContext, "loop", TheFunction);
//exit the block
BasicBlock *AfterBB = BasicBlock::Create(TheContext, "afterloop", TheFunction);
Builder.SetInsertPoint(BB);
//add goto LoopBB in BB
Builder.CreateBr(LoopBB);
//start with LoopBB
Builder.SetInsertPoint(LoopBB);
//start with 0
Value *StartVal = ConstantFP::get(TheContext, APFloat(0.0));
//step is 1
Value *StepVal = ConstantFP::get(TheContext, APFloat(1.0));
//local Variable which name is a
PHINode *Variable = Builder.CreatePHI(Type::getDoubleTy(TheContext), 1, "i");
//if it's from start block, set Variable 0
Variable->addIncoming(StartVal, BB);
//do the body then do cond
//emit loop body in LoopBB
//body: arg_a += 1
Value *ret = Builder.CreateFAdd(innerargs[0], ConstantFP::get(TheContext, APFloat(2.0)), "a");
//do the cond,if Variable >= 2 then break(goto AfterBB)
Value *NextVar = Builder.CreateFAdd(StepVal, Variable, "nextvar");
//if Variable < 10 then goto LoopBB or gotot AfterBB
Value *cond = Builder.CreateFCmpULT(Variable, ConstantFP::get(TheContext, APFloat(10.0)), "cmptmp");
Builder.CreateCondBr(cond, LoopBB, AfterBB);
Builder.SetInsertPoint(AfterBB);
Variable->addIncoming(NextVar, LoopBB);
Builder.CreateRet(ret);
TheFunction->print(errs());
//using jit to run this code
auto H = TheJIT->addModule(std::move(TheModule));
auto ExprSymbol = TheJIT->findSymbol("myfor");
double (*myfor)(double) = (double (*)(double))(intptr_t)cantFail(ExprSymbol.getAddress());
cout <<myfor(40)<<endl;
}
版权声明
本文为[Mrpre]所创,转载请带上原文链接,感谢
https://wonderful.blog.csdn.net/article/details/106902005
边栏推荐
- MYSQL一种分表实现方案及InnoDB、MyISAM、MRG_MYISAM等各种引擎应用场景介绍
- 如何轻松做好一个项目
- 困扰多年的系统调研问题有自动化采集工具了,还是开源免费的
- Get the thread return value. Introduction to the use of future interface and futuretask class
- rsync+inotify远程同步
- Nacos作为配置中心(四) 使用Demo
- Research on recyclerview details - Discussion and repair of recyclerview click dislocation
- Docker篇 (五) MySQL的安装
- setcontext getcontext makecontext swapcontext
- Gif to still image processing
猜你喜欢
API Gateway/API 网关(三) - Kong的使用 - 限流rate limiting(redis)
微信小程序将原生请求通过es6的promise来进行优化
01-nio basic ByteBuffer and filechannel
VMware installation 64 bit XP Chinese tutorial
VMware 15pro mounts the hard disk of the real computer in the deepin system
微信小程序客服接入,实现发送和接收消息
字节面试编程题:最小的K个数
关于云容灾,你需要知道这些
x509证书cer格式转pem格式
Some experience of using dialogfragment and anti stepping pit experience (getactivity and getdialog are empty, cancelable is invalid, etc.)
随机推荐
Five ways of using synchronized to remove clouds and fog are introduced
时间复杂度计算举例
倒计时1天~2022云容灾产品线上发布会即将开始
进入新公司,运维工程师从下面这几项了解系统的部署
如何轻松做好一个项目
Date的after时间判断
修改Firebase Emulators的默认侦听IP
On the problem of cliff growth of loss function in the process of training
Man man notes and @ reboot usage of crontab
mysql锁数据库锁
SSH 通过跳板机连接远程主机
OpenStack命令操作
redis数据库讲解(三)redis数据类型
Request module
差分隐私(背景介绍)
解决ssh配置文件优化以及连接慢的问题
网页自适应,等比缩放
Thread group ThreadGroup uses introduction + custom thread factory class to implement threadfactory interface
Operation instructions of star boundary text automatic translator
Mysql的安装过程(已经安装成功的步骤说明)