• llvm for expr


    想要什么:

    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 fun(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) << "
    "; // 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));
    }
    
  • 相关阅读:
    Clean Code(三):注释
    Clean Code(二):函数
    mysql中查询某字段所在的表方法
    对于POI的XSSFCell 类型问题
    Clean Code 笔记 (一):命名
    java 注解
    搭建Eureka服务时报Cannot execute request on any known server 错误
    Jquery获取子父类方法
    Oracle 查询id相同多个数据取一条
    Ajax的使用及后台如何传参
  • 原文地址:https://www.cnblogs.com/ajanuw/p/14839367.html
Copyright © 2020-2023  润新知