当前位置:网站首页>LLVM - 生成 if-else 以及 PH

LLVM - 生成 if-else 以及 PH

2022-04-23 14:11:00 Mrpre

1、生成函数
2、函数有4个basic block,一个entry,一个 if-then 另一个 if-else,最后一个是因为需要使用ph,所以创建一个merge。
3、创建ph来处理if-else,相关概念 http://en.wikipedia.org/wiki/Static_single_assignment_form

4、使用jit运行
5、本例中KaleidoscopeJIT源码在./llvm-8.0.1.src/examples/Kaleidoscope/include/KaleidoscopeJIT.h

#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 mycmp(double a, double b) *{ * if (a < b) { * return 1; * * } else { * return 2; * } * *} * */
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;

    //mycmp has 2 args
    ArgNames.push_back(string("a"));
    ArgNames.push_back(string("b"));

    //make the 2 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, "mycmp", 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);
    }

    //4 blocks
    
    //fitst is function's entry
    BasicBlock *BB = BasicBlock::Create(TheContext, "entry", TheFunction);

    //generate llvm function body:control-flow
    //At least three blocks(MergeBB is not necessary)
    //if's cond if(a > b)
    //the if expression belongs to BB
    
	//BB:
	// if xxx then
	// then-logic
	// else
	// else-logic
    Builder.SetInsertPoint(BB);
    Value *cond = Builder.CreateFCmpULT(innerargs[0], innerargs[1], "cmptmp");

    //then block
    BasicBlock *ThenBB = BasicBlock::Create(TheContext, "then", TheFunction);
    //else block
    BasicBlock *ElseBB = BasicBlock::Create(TheContext, "else");

    //after control block
    BasicBlock *MergeBB = BasicBlock::Create(TheContext, "ifcont");

    //join three block
    Builder.CreateCondBr(cond, ThenBB, ElseBB);

    //then expression
    //then:
    // then-logic = ThenV
    // goto MergeBB
    Builder.SetInsertPoint(ThenBB);
    Value *ThenV = ConstantFP::get(TheContext, APFloat(1.0));

    //Builder.CreateRet(ThenV);
    //We also could just CreateRet not CreateBr.
    Builder.CreateBr(MergeBB);

    //ElseBB has not been inserted because ElseBB doesn't 
    //created by Thefunction
    TheFunction->getBasicBlockList().push_back(ElseBB);

    //else expression and goto MergeBB
    //else:
    // else-logic = ElseV
    // goto MergeBB
    Builder.SetInsertPoint(ElseBB);
    Value *ElseV = ConstantFP::get(TheContext, APFloat(2.0));
    //Builder.CreateRet(ElseV);
    Builder.CreateBr(MergeBB);

    //MergeBB has not been inserted
    TheFunction->getBasicBlockList().push_back(MergeBB);

	
    //newly created code will go into the “merge” block
    //ifcont
    // ph
    Builder.SetInsertPoint(MergeBB);

    //need to construct MergeBB
    PHINode *PN = Builder.CreatePHI(Type::getDoubleTy(TheContext), 2, "iftmp");

	// if from ThenBB then ph is ThenV
	// if from ElseBB then ph is ElseV
    PN->addIncoming(ThenV, ThenBB);
    PN->addIncoming(ElseV, ElseBB);

    Builder.CreateRet(PN);

    //print LLVM IR
    TheFunction->print(errs());

    //using jit to run this code
    auto H = TheJIT->addModule(std::move(TheModule));
    auto ExprSymbol = TheJIT->findSymbol("mycmp");
    double (*mycmp)(double, double) = (double (*)(double, double))(intptr_t)cantFail(ExprSymbol.getAddress());
    cout <<mycmp(30, 40)<<endl;
}

也可以不用ph,因为if else的值比较简单,所以也可以直接使用,Builder.CreateRet(ThenV);或者Builder.CreateRet(ElseV);创建返回值。

#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 mycmp(double a, double b) *{ * if (a < b) { * return 1; * * } else { * return 2; * } * *} * */
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;

    //mycmp has 2 args
    ArgNames.push_back(string("a"));
    ArgNames.push_back(string("b"));

    //make the 2 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, "mycmp", 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);
    }

    //4 blocks
    BasicBlock *BB = BasicBlock::Create(TheContext, "entry", TheFunction);

    //generate llvm function body:control-flow
    //At least three blocks(MergeBB is not necessary)
    //if's cond if(a > b)
    //the if expression belongs to BB
    Builder.SetInsertPoint(BB);
    Value *cond = Builder.CreateFCmpULT(innerargs[0], innerargs[1], "cmptmp");

    //then block
    BasicBlock *ThenBB = BasicBlock::Create(TheContext, "then", TheFunction);
    //else block
    BasicBlock *ElseBB = BasicBlock::Create(TheContext, "else", TheFunction);

    //after control block
    BasicBlock *MergeBB = BasicBlock::Create(TheContext, "ifcont");

    //join three block
    Builder.CreateCondBr(cond, ThenBB, ElseBB);

    //then expression and goto MergeBB
    Builder.SetInsertPoint(ThenBB);
    Value *ThenV = ConstantFP::get(TheContext, APFloat(1.0));

    Builder.CreateRet(ThenV);
    //We also could just CreateRet not CreateBr.
    //Builder.CreateBr(MergeBB);

    //ElseBB has been inserted
    //TheFunction->getBasicBlockList().push_back(ElseBB);

    //else expression and goto MergeBB
    Builder.SetInsertPoint(ElseBB);
    Value *ElseV = ConstantFP::get(TheContext, APFloat(2.0));
    Builder.CreateRet(ElseV);
    //Builder.CreateBr(MergeBB);

    //MergeBB has not been inserted
    //TheFunction->getBasicBlockList().push_back(MergeBB);

    //newly created code will go into the “merge” block
    //Builder.SetInsertPoint(MergeBB);

    //need to construct MergeBB
    //PHINode *PN = Builder.CreatePHI(Type::getDoubleTy(TheContext), 2, "iftmp");

    //PN->addIncoming(ThenV, ThenBB);
    //PN->addIncoming(ElseV, ElseBB);

    //Builder.CreateRet(PN);

    //print LLVM IR
    TheFunction->print(errs());

    //using jit to run this code
    auto H = TheJIT->addModule(std::move(TheModule));
    auto ExprSymbol = TheJIT->findSymbol("mycmp");
    double (*mycmp)(double, double) = (double (*)(double, double))(intptr_t)cantFail(ExprSymbol.getAddress());
    cout <<mycmp(30, 40)<<endl;
}

版权声明
本文为[Mrpre]所创,转载请带上原文链接,感谢
https://wonderful.blog.csdn.net/article/details/106900611