LLVM学习日志2——PASS尝试

我主要是学习修改,而不是学习LLVM IR

所以我先学习的是LLVM的pass

pass分analysis pass, transform pass和Utility Passes。

pass有很多种类,用法也不同,详细的可以看官方说明http://llvm.org/docs/Passes.html#introduction

先尝试自己编写一个transform  pass,具体也可以看官方教材http://llvm.org/docs/WritingAnLLVMPass.html

在/llvm/lib/Transforms/下面有很多文件夹,这些是LLVM自带的pass,比如官方例子Hello。

先复制整个Hello文件夹,修改名称为Readd

接着修改CMakeLists.txt,增加一行,作用是编译时候编译Readd文件夹

add_subdirectory(Readd)

进入Readd文件夹,可以看到三个文件。

先修改CMakeList.txt,将里面的hello改成Readd

if( NOT LLVM_REQUIRES_RTTI )
  if( NOT LLVM_REQUIRES_EH )
    set(LLVM_EXPORTED_SYMBOL_FILE ${CMAKE_CURRENT_SOURCE_DIR}/Readd.exports)
  endif()
endif()

if(WIN32 OR CYGWIN)
  set(LLVM_LINK_COMPONENTS Core Support)
endif()

add_llvm_loadable_module( LLVMReadd
  Readd.cpp

  DEPENDS
  intrinsics_gen
  PLUGIN_TOOL
  opt
  )

主要的是修改hello.cpp,先修改文件名为Readd.cpp。这里面是pass的功能,是将加法改成减去被加数的负数。

#include "llvm/IR/Function.h"
#include "llvm/Pass.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/Instructions.h"
 
using namespace llvm;
 
#define DEBUG_TYPE "readd"
 
namespace {
    struct readd : public FunctionPass {
        static char ID; // Pass identification, replacement for typeid
         
        readd() : FunctionPass(ID) {}
         
        bool runOnFunction(Function &F) override {
            Function *tmp = &F;
            // 遍历函数中的所有基本块
            for (Function::iterator bb = tmp->begin(); bb != tmp->end(); ++bb) {
                // 遍历基本块中的每条指令
                for (BasicBlock::iterator inst = bb->begin(); inst != bb->end(); ++inst) {
                    // 是否是add指令
                    if (inst->isBinaryOp()) {
                        if (inst->getOpcode() == Instruction::Add) {
                            ob_add(cast<BinaryOperator>(inst));
                        }
                    }
                }
            }
             
            return false;
        }
         
        // a+b === a-(-b)
        bool ob_add(BinaryOperator *bo) {
            BinaryOperator *op = NULL;
             
            if (bo->getOpcode() == Instruction::Add) {
                // 生成 (-b)
                op = BinaryOperator::CreateNeg(bo->getOperand(1), "", bo);
                // 生成 a-(-b)
                op = BinaryOperator::Create(Instruction::Sub, bo->getOperand(0), op, "", bo);
                 
                op->setHasNoSignedWrap(bo->hasNoSignedWrap());
                op->setHasNoUnsignedWrap(bo->hasNoUnsignedWrap());
            }
             
            // 替换所有出现该指令的地方
            bo->replaceAllUsesWith(op);
        }
    };
}
 
char readd::ID = 0;

static RegisterPass<readd> X("readd", "Readd Pass");

第三个文件是Hello.exports,修改名称为Readd.exports就行,这个我还不是很明白,这个空文件夹有什么作用。

修改完毕,需要重新编译,在llvm/build中重新make(这里我不知道要不要make install,因为我安装了两个llvm,一个make install了,一个没有,修改的是那没有的。)

然后在llvm/build/lib/中出现了LLVMReadd.so,这个名称在之前那个cmakelist中修改。

下面来测试一下,先建个.c文件里面是整数加法


#include <stdio.h>
int main() {
 
int a=1,b=2;
int c;
c=a+b;
  return 0;
}

先编译成.bc文件,注意,优化不要太高

clang -O0 -emit-llvm test.c -c -o test.bc

下面这句是使用哪个pass -readd是根据之前的那个Readd.cpp里这句中(static RegisterPass<readd> X("readd", "Readd Pass");)X括号里的确定的,是说用pass里那个功能,因为一个pass可以有多个功能,而这个只有一个。

opt -load ../build/lib/LLVMReadd.so -readd <test.bc> chtest.bc    

转化成可视的.ll

llvm-dis chtest.bc

可以从LLVM IR看到变化。

如果编写的是全局的pass,而不是opt调用的,那就需要增加几个步骤。

首先是初始化,llvm/InitializePasses.h的头文件中增加自己的pass

void initializeMYADCEPass(PassRegistry&);

然后在include/llvm-c/scalar.h/Transform/scalar.h文件下添加Pass的条目

void LLVMAddMYAggressiveDCEPass(LLVMPassManagerRef PM);

在include/llvm/Transform/scalar.h文件中,在llvm命名空间添加Pass的条目:
FunctionPass *createMYAggressiveDCEPass();

在lib/Transforms/Scalar/scalar.cpp文件的两个地方添加Pass的条目,并在void llvm::initializeScalarOpts(PassRegistry &Registry)函数中添加如下代码:

initializeMergedLoadStoreMotionPass(Registry); //已存在于文件
initializeMYADCEPass(Registry); //增加此行
initializeNaryReassociatePass(Registry); //已存在于文件
...
...
void LLVMAddMemCpyOptPass(LLVMPassManagerRef PM) {
unwrap(PM)->add(createMemCpyOptPass());
}

// 增加以下代码
void LLVMAddMYAggressiveDCEPass(LLVMPassManagerRef PM) {
unwrap(PM)->add(createMYAggressiveDCEPass());
}
void LLVMAddPartiallyInlineLibCallsPass(LLVMPassManagerRef PM) {
unwrap(PM)->add(createPartiallyInlineLibCallsPass());
}

 

 

 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值