llvm for表达式
Posted Ajanuw
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了llvm for表达式相关的知识,希望对你有一定的参考价值。
想要什么:
int fun(int p1)
{
int r = 0;
for(int i = 0; i < p1; i++)
{
r = r + i + p1;
}
return r;
}
IR:
define i32 @fun(i32 %p1) {
entry:
%r = alloca i32, align 4
store i32 0, i32* %r, align 4
br label %loop
loop: ; preds = %loopBody, %entry
%i = phi i32 [ 0, %entry ], [ %3, %loopBody ]
%0 = icmp slt i32 %i, %p1
br i1 %0, label %loopBody, label %return
loopBody: ; preds = %loop
%1 = add i32 %i, %p1
%r1 = load i32, i32* %r, align 4
%2 = add i32 %r1, %1
store i32 %2, i32* %r, align 4
%3 = add i32 %i, 1
br label %loop
return: ; preds = %loop
%r2 = load i32, i32* %r, align 4
ret i32 %r2
}
#include "llvm/ExecutionEngine/Orc/LLJIT.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
using namespace llvm::orc;
ExitOnError ExitOnErr;
ThreadSafeModule createTSM() {
// context 拥有许多核心的 LLVM 数据结构,例如类型和常量值表
auto Context = std::make_unique<LLVMContext>();
// module 包含函数和全局变量的LLVM构造,它是 LLVM IR 用来包含代码的顶级结构。它将拥有我们生成的所有 IR 的内存
auto M = std::make_unique<Module>("test", *Context);
// 创建一个构建器,可以轻松生成 LLVM 指令
IRBuilder<> builder(*Context);
// 声明一个函数 int add1(int) 添加到module中
auto funcType = FunctionType::get(Type::getInt32Ty(*Context), { Type::getInt32Ty(*Context) }, false);
Function* Add1F = Function::Create(funcType, Function::ExternalLinkage, "fun", M.get());
Argument* p1 = Add1F->getArg(0); // 获取参数
p1->setName("p1"); // 设置arg name
// 创建一个block添加到Add1F
BasicBlock* BB = BasicBlock::Create(*Context, "entry", Add1F);
// 构建器接下来的指令将插入到BB
builder.SetInsertPoint(BB);
// int r = 0
auto r = builder.CreateAlloca(Type::getInt32Ty(*Context), 0, "r");
builder.CreateStore(builder.getInt32(0), r);
BasicBlock* LoopBB = BasicBlock::Create(*Context, "loop", Add1F);
BasicBlock* LoopBodyBB = BasicBlock::Create(*Context, "loopBody", Add1F);
BasicBlock* ReturnBB = BasicBlock::Create(*Context, "return", Add1F);
builder.CreateBr(LoopBB);
builder.SetInsertPoint(LoopBB);
// i = 0
auto i = builder.CreatePHI(Type::getInt32Ty(*Context), 2, "i");
i->addIncoming(builder.getInt32(0), BB);
// i < p1
auto cmp = builder.CreateICmpSLT(i, p1);
builder.CreateCondBr(cmp, LoopBodyBB, ReturnBB );
builder.SetInsertPoint(LoopBodyBB);
// r = r + i + p1
builder.CreateStore(
builder.CreateAdd(builder.CreateLoad(r, "r"), builder.CreateAdd(i, p1)),
r
);
// i++
i->addIncoming(builder.CreateAdd(i, builder.getInt32(1)), LoopBodyBB);
builder.CreateBr(LoopBB);
// return r
builder.SetInsertPoint(ReturnBB);
builder.CreateRet(builder.CreateLoad(r, "r"));
// 打印出所有生成的代码
M->print(errs(), nullptr);
// 返回线程模块
return ThreadSafeModule(std::move(M), std::move(Context));
}
int main() {
InitializeNativeTarget();
InitializeNativeTargetAsmPrinter();
// Create an LLJIT instance.
auto _jit = ExitOnErr(LLJITBuilder().create());
auto M = createTSM();
ExitOnErr(_jit->addIRModule(std::move(M)));
// 查找 JIT 函数,将其转换为函数指针,然后调用它.
auto Add1Sym = ExitOnErr(_jit->lookup("fun"));
int (*_fun)(int) = (int (*)(int))Add1Sym.getAddress();
outs() << "fun(2) = " << _fun(2) << "\\n"; // 5
return 0;
}
或者:
define i32 @fun(i32 %p1) {
entry:
%r = alloca i32, align 4
store i32 0, i32* %r, align 4
%i = alloca i32, align 4
store i32 0, i32* %i, align 4
br label %loop
loop: ; preds = %loopBody, %entry
%0 = load i32, i32* %i, align 4
%1 = icmp slt i32 %0, %p1
br i1 %1, label %loopBody, label %return
loopBody: ; preds = %loop
%2 = load i32, i32* %i, align 4
%3 = add i32 %2, %p1
%r1 = load i32, i32* %r, align 4
%4 = add i32 %r1, %3
store i32 %4, i32* %r, align 4
%5 = load i32, i32* %i, align 4
%6 = add i32 %5, 1
store i32 %6, i32* %i, align 4
br label %loop
return: ; preds = %loop
%r2 = load i32, i32* %r, align 4
ret i32 %r2
}
ThreadSafeModule createTSM() {
...
// int r = 0
auto r = builder.CreateAlloca(Type::getInt32Ty(*Context), 0, "r");
builder.CreateStore(builder.getInt32(0), r);
// int i = 0
auto i = builder.CreateAlloca(Type::getInt32Ty(*Context), 0, "i");
builder.CreateStore(builder.getInt32(0), i);
BasicBlock* LoopBB = BasicBlock::Create(*Context, "loop", Add1F);
BasicBlock* LoopBodyBB = BasicBlock::Create(*Context, "loopBody", Add1F);
BasicBlock* ReturnBB = BasicBlock::Create(*Context, "return", Add1F);
builder.CreateBr(LoopBB);
builder.SetInsertPoint(LoopBB);
// i < p1
auto cmp = builder.CreateICmpSLT(builder.CreateLoad(i), p1);
builder.CreateCondBr(cmp, LoopBodyBB, ReturnBB );
builder.SetInsertPoint(LoopBodyBB);
// r = r + i + p1
builder.CreateStore(
builder.CreateAdd(builder.CreateLoad(r, "r"), builder.CreateAdd(builder.CreateLoad(i), p1)),
r
);
// i++
builder.CreateStore(builder.CreateAdd(builder.CreateLoad(i), builder.getInt32(1)), i);
builder.CreateBr(LoopBB);
// return r
builder.SetInsertPoint(ReturnBB);
builder.CreateRet(builder.CreateLoad(r, "r"));
// 打印出所有生成的代码
M->print(errs(), nullptr);
// 返回线程模块
return ThreadSafeModule(std::move(M), std::move(Context));
}
以上是关于llvm for表达式的主要内容,如果未能解决你的问题,请参考以下文章
使用 LLVM-for-Arm 工具链编译 RT-Thread 源码
Facebook‘s BOLT Nearing Mainline LLVM For Optimizing Binaries
Facebook‘s BOLT Nearing Mainline LLVM For Optimizing Binaries