• llvm if expr


    想要什么:

    int fun(int p1)
    {
     if(p1 < 5) return 1;
     else return 2;
    }
    

    IR:

    define i32 @fun(i32 %p1) {
    entry:
      %cmp = icmp slt i32 %p1, 5
      br i1 %cmp, label %then, label %else
    
    then:                                             ; preds = %entry
      ret i32 1
    
    else:                                             ; preds = %entry
      ret i32 2
    }
    
    #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());
    
      // 创建一个block添加到Add1F
      BasicBlock* BB = BasicBlock::Create(*Context, "entry", Add1F);
    
      // 构建器接下来的指令将插入到BB
      builder.SetInsertPoint(BB);
    
      Argument* p1 = Add1F->getArg(0); // 获取参数
      p1->setName("p1"); // 设置arg name
      
      // p1 < 5, 返回 1 or 0
      auto _cmp = builder.CreateICmpSLT(p1, builder.getInt32(5), "cmp");
      
      BasicBlock* ThenBB = BasicBlock::Create(*Context, "then", Add1F);
      BasicBlock* ElseBB = BasicBlock::Create(*Context, "else", Add1F);
    
      // 条件跳转
      builder.CreateCondBr(_cmp, ThenBB, ElseBB);
    
      // 填充then block
      builder.SetInsertPoint(ThenBB);
      builder.CreateRet(builder.getInt32(1));
    
      // 填充else block
      builder.SetInsertPoint(ElseBB);
      builder.CreateRet(builder.getInt32(2));
    
      // 打印出所有生成的代码
      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(-1) = " << _fun(-1) << "
    "; // 1
      outs() << "fun(5) = " << _fun(5) << "
    "; // 2
    
      return 0;
    }
    

    或者:

    define i32 @fun(i32 %p1) {
    entry:
      %cmp = icmp slt i32 %p1, 5
      br i1 %cmp, label %then, label %else
    
    then:                                             ; preds = %entry
      br label %return
    
    else:                                             ; preds = %entry
      br label %return
    
    return:                                           ; preds = %else, %then
      %0 = phi i32 [ 1, %then ], [ 2, %else ]
      ret i32 %0
    }
    
    ThreadSafeModule createTSM() {
     ...
      
      BasicBlock* ThenBB = BasicBlock::Create(*Context, "then", Add1F);
      BasicBlock* ElseBB = BasicBlock::Create(*Context, "else", Add1F);
      BasicBlock* ReturnBB = BasicBlock::Create(*Context, "return", Add1F);
    
      // 条件跳转
      builder.CreateCondBr(_cmp, ThenBB, ElseBB);
    
      // 填充then block
      builder.SetInsertPoint(ThenBB);
      auto ThenVal = builder.getInt32(1);
      // 无条件跳转
      builder.CreateBr(ReturnBB);
    
      // 填充else block
      builder.SetInsertPoint(ElseBB);
      auto ElseVal = builder.getInt32(2);
      // 无条件跳转
      builder.CreateBr(ReturnBB);
    
      builder.SetInsertPoint(ReturnBB);
      PHINode* PN = builder.CreatePHI(Type::getInt32Ty(*Context), 2);
      PN->addIncoming(ThenVal, ThenBB);
      PN->addIncoming(ElseVal, ElseBB);
      
      builder.CreateRet(PN);
    
      // 打印出所有生成的代码
      M->print(errs(), nullptr);
    
      // 返回线程模块
      return ThreadSafeModule(std::move(M), std::move(Context));
    }
    
  • 相关阅读:
    模块化+定制化,PIX赋能多种行业实现低速无人车商业化
    支持Apollo、Autoware,PIX推出自动驾驶开发套件PIXKIT
    专为自动驾驶开发者打造的线控底盘——PIXLOOP
    甄别信息、病毒追踪、无人配送...这9个全球开源工具助力疫情抗击
    PIX无损线控改装——全系列车型及性能介绍
    PIX线控改装技术连载二 | 车辆组成模块之间的共同语言
    PIX入选Autodesk硅谷技术中心,以生成设计和金属增材制造落地L4自动驾驶通用底盘
    线控CRV,最高性价比的自动驾驶开发平台
    线控改装技术连载一之——线控开端和车辆组成
    CSS 创建
  • 原文地址:https://www.cnblogs.com/ajanuw/p/14839090.html
Copyright © 2020-2023  润新知