当前位置:网站首页>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