当前位置:网站首页>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
边栏推荐
- JDBC details
- Thread group ThreadGroup uses introduction + custom thread factory class to implement threadfactory interface
- 第四届“传智杯”全国大学生IT技能大赛(决赛B组) 题解
- 获取线程返回值Future接口与FutureTask类使用介绍
- uni-app消息推送
- About the configuration and use of json5 in nodejs
- Date的after时间判断
- Get the thread return value. Introduction to the use of future interface and futuretask class
- Uni app message push
- OpenSSH的升级、版本号的修改
猜你喜欢

x509证书cer格式转pem格式

Tongxin UOS php7 2.3 upgrade to php7.0 two point two four

HyperBDR云容灾V3.3.0版本发布|容灾功能升级,资源组管理功能优化

OpenStack命令操作

API Gateway/API 网关(二) - Kong的使用 - 负载均衡Loadbalance

About the configuration and use of json5 in nodejs

倒计时1天~2022云容灾产品线上发布会即将开始

MySQL数据库讲解(八)

Uni app message push

政务云迁移实践 北明数科使用HyperMotion云迁移产品为某政府单位实施上云迁移项目,15天内完成近百套主机迁移
随机推荐
Use the executors class to quickly create a thread pool
Arrays类的使用案例
MySQL-InnoDB-事务
ansible及常用模块的使用
redis数据库讲解(三)redis数据类型
OpenSSH的升级、版本号的修改
mysql 5.1升级到5.66
Request module
gif转为静态图片处理
逻辑卷创建与扩容
MySQL同步Could not find first log file name in binary log index file错误
JumpServer
setcontext getcontext makecontext swapcontext
SED 学以致用
Logback logger and root
js 抛物线运动方法封装
sar命令详解
source insight via samba
STD:: map and STD:: vector memory free
openstack理论知识