首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用于循环的LLVM IR

用于循环的LLVM IR
EN

Stack Overflow用户
提问于 2019-09-03 09:57:09
回答 1查看 960关注 0票数 0

我使用LLVM C++ api来生成LLVM,并使用JIT运行该函数。我想要模拟的函数是

代码语言:javascript
复制
double foofor(double a)
{
    for (int i = 0; i < 10; i++) {
        a += 2;
    }
    return a;
}

我生成的对应的llvm IR代码是(使用函数->打印)

代码语言:javascript
复制
define double @foofor(double %a) {
entry:
  br label %loop

loop:                                             ; preds = %loop, %entry
  %a1 = phi double [ 0.000000e+00, %entry ], [ %nextvar, %loop ]
  %addtmp = fadd double %a, 2.000000e+00
  %nextvar = fadd double 1.000000e+00, %a1
  %cmptmp = fcmp ult double %a1, 1.000000e+01
  br i1 %cmptmp, label %loop, label %afterloop

afterloop:                                        ; preds = %loop
  ret double %addtmp
}

当我调用foofor(40)时,我得到42而不是60(40 + 20)。

我编写的代码(没有AST)

代码语言:javascript
复制
#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 foofor(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;

    //foocfor 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, "foofor", TheModule.get());

    //give the name for Function args and save the args in 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, "entry", 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, "a");
    //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)), "addtmp");


    //do the cond,if Variable >= 10 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("foofor");
    double (*foofor)(double) = (double (*)(double))(intptr_t)cantFail(ExprSymbol.getAddress());
    cout <<foofor(40)<<endl;
}
EN

回答 1

Stack Overflow用户

发布于 2019-09-07 08:38:06

下面是增加的变量的LLVM IR表单:

代码语言:javascript
复制
define double @foofor(double %a) {
entry:
  br label %loop

loop:                                             ; preds = %loop, %entry
  %a1 = phi double [ 0.000000e+00, %entry ], [ %nextvar, %loop ]
  %a2 = phi double [ 0.000000e+00, %a ], [ %addtmp, %loop ]
  %addtmp = fadd double %a2, 2.000000e+00
  %nextvar = fadd double 1.000000e+00, %a1
  %cmptmp = fcmp ult double %a1, 1.000000e+01
  br i1 %cmptmp, label %loop, label %afterloop

afterloop:                                        ; preds = %loop
  ret double %addtmp
}

%a1/%nextvar也应该是ints,而不是双倍,但我留下了它,因为这不是你问题的主题。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57769298

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档