当前位置:网站首页>LLVM - 生成 if-else 以及 PH
LLVM - 生成 if-else 以及 PH
2022-04-23 14:11:00 【Mrpre】
1、生成函数
2、函数有4个basic block,一个entry,一个 if-then 另一个 if-else,最后一个是因为需要使用ph,所以创建一个merge。
3、创建ph来处理if-else,相关概念 http://en.wikipedia.org/wiki/Static_single_assignment_form
4、使用jit运行
5、本例中KaleidoscopeJIT源码在./llvm-8.0.1.src/examples/Kaleidoscope/include/KaleidoscopeJIT.h
#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 mycmp(double a, double b) *{ * if (a < b) { * return 1; * * } else { * return 2; * } * *} * */
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;
//mycmp has 2 args
ArgNames.push_back(string("a"));
ArgNames.push_back(string("b"));
//make the 2 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, "mycmp", 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);
}
//4 blocks
//fitst is function's entry
BasicBlock *BB = BasicBlock::Create(TheContext, "entry", TheFunction);
//generate llvm function body:control-flow
//At least three blocks(MergeBB is not necessary)
//if's cond if(a > b)
//the if expression belongs to BB
//BB:
// if xxx then
// then-logic
// else
// else-logic
Builder.SetInsertPoint(BB);
Value *cond = Builder.CreateFCmpULT(innerargs[0], innerargs[1], "cmptmp");
//then block
BasicBlock *ThenBB = BasicBlock::Create(TheContext, "then", TheFunction);
//else block
BasicBlock *ElseBB = BasicBlock::Create(TheContext, "else");
//after control block
BasicBlock *MergeBB = BasicBlock::Create(TheContext, "ifcont");
//join three block
Builder.CreateCondBr(cond, ThenBB, ElseBB);
//then expression
//then:
// then-logic = ThenV
// goto MergeBB
Builder.SetInsertPoint(ThenBB);
Value *ThenV = ConstantFP::get(TheContext, APFloat(1.0));
//Builder.CreateRet(ThenV);
//We also could just CreateRet not CreateBr.
Builder.CreateBr(MergeBB);
//ElseBB has not been inserted because ElseBB doesn't
//created by Thefunction
TheFunction->getBasicBlockList().push_back(ElseBB);
//else expression and goto MergeBB
//else:
// else-logic = ElseV
// goto MergeBB
Builder.SetInsertPoint(ElseBB);
Value *ElseV = ConstantFP::get(TheContext, APFloat(2.0));
//Builder.CreateRet(ElseV);
Builder.CreateBr(MergeBB);
//MergeBB has not been inserted
TheFunction->getBasicBlockList().push_back(MergeBB);
//newly created code will go into the “merge” block
//ifcont
// ph
Builder.SetInsertPoint(MergeBB);
//need to construct MergeBB
PHINode *PN = Builder.CreatePHI(Type::getDoubleTy(TheContext), 2, "iftmp");
// if from ThenBB then ph is ThenV
// if from ElseBB then ph is ElseV
PN->addIncoming(ThenV, ThenBB);
PN->addIncoming(ElseV, ElseBB);
Builder.CreateRet(PN);
//print LLVM IR
TheFunction->print(errs());
//using jit to run this code
auto H = TheJIT->addModule(std::move(TheModule));
auto ExprSymbol = TheJIT->findSymbol("mycmp");
double (*mycmp)(double, double) = (double (*)(double, double))(intptr_t)cantFail(ExprSymbol.getAddress());
cout <<mycmp(30, 40)<<endl;
}
也可以不用ph,因为if else的值比较简单,所以也可以直接使用,Builder.CreateRet(ThenV);
或者Builder.CreateRet(ElseV);
创建返回值。
#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 mycmp(double a, double b) *{ * if (a < b) { * return 1; * * } else { * return 2; * } * *} * */
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;
//mycmp has 2 args
ArgNames.push_back(string("a"));
ArgNames.push_back(string("b"));
//make the 2 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, "mycmp", 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);
}
//4 blocks
BasicBlock *BB = BasicBlock::Create(TheContext, "entry", TheFunction);
//generate llvm function body:control-flow
//At least three blocks(MergeBB is not necessary)
//if's cond if(a > b)
//the if expression belongs to BB
Builder.SetInsertPoint(BB);
Value *cond = Builder.CreateFCmpULT(innerargs[0], innerargs[1], "cmptmp");
//then block
BasicBlock *ThenBB = BasicBlock::Create(TheContext, "then", TheFunction);
//else block
BasicBlock *ElseBB = BasicBlock::Create(TheContext, "else", TheFunction);
//after control block
BasicBlock *MergeBB = BasicBlock::Create(TheContext, "ifcont");
//join three block
Builder.CreateCondBr(cond, ThenBB, ElseBB);
//then expression and goto MergeBB
Builder.SetInsertPoint(ThenBB);
Value *ThenV = ConstantFP::get(TheContext, APFloat(1.0));
Builder.CreateRet(ThenV);
//We also could just CreateRet not CreateBr.
//Builder.CreateBr(MergeBB);
//ElseBB has been inserted
//TheFunction->getBasicBlockList().push_back(ElseBB);
//else expression and goto MergeBB
Builder.SetInsertPoint(ElseBB);
Value *ElseV = ConstantFP::get(TheContext, APFloat(2.0));
Builder.CreateRet(ElseV);
//Builder.CreateBr(MergeBB);
//MergeBB has not been inserted
//TheFunction->getBasicBlockList().push_back(MergeBB);
//newly created code will go into the “merge” block
//Builder.SetInsertPoint(MergeBB);
//need to construct MergeBB
//PHINode *PN = Builder.CreatePHI(Type::getDoubleTy(TheContext), 2, "iftmp");
//PN->addIncoming(ThenV, ThenBB);
//PN->addIncoming(ElseV, ElseBB);
//Builder.CreateRet(PN);
//print LLVM IR
TheFunction->print(errs());
//using jit to run this code
auto H = TheJIT->addModule(std::move(TheModule));
auto ExprSymbol = TheJIT->findSymbol("mycmp");
double (*mycmp)(double, double) = (double (*)(double, double))(intptr_t)cantFail(ExprSymbol.getAddress());
cout <<mycmp(30, 40)<<endl;
}
版权声明
本文为[Mrpre]所创,转载请带上原文链接,感谢
https://wonderful.blog.csdn.net/article/details/106900611
边栏推荐
猜你喜欢
随机推荐
Use the executors class to quickly create a thread pool
微信小程序客服接入,实现发送和接收消息
Thread group ThreadGroup uses introduction + custom thread factory class to implement threadfactory interface
Web page, adaptive, proportional scaling
mysql 5.1升级到5.611
XX project structure notes
tcp_diag 内核相关实现 1 调用层次
倒计时1天~2022云容灾产品线上发布会即将开始
ansible及常用模块的使用
微信小程序轮播图swiper
翻牌效果
Five ways of using synchronized to remove clouds and fog are introduced
JS key value judgment
返回数组排序后下标
x509证书cer格式转pem格式
JS parabola motion packaging method
Redis数据库讲解(一)
elk安装
线程间控制之Semaphore使用介绍
Win10 comes with groove music, which can't play cue and ape files. It's a curvilinear way to save the country. It creates its own aimpack plug-in package, and aimp installs DSP plug-in