联系我们:010-58426662

llvm之旅第四站 - 编写Pass

2015-04-21 15:52:10

©娜迦 charme版权所有

版权声明:未经许可,请勿转载

什么是pass


LLVM 的Pass框架是LLVM系统的一个很重要的部分。LLVM的优化和转换工作就是由很多个Pass来一起完成的。类似流水线操作一样,每个pass完成特定的优化工作。 


在一些特殊的情况下,新插入的pass可能会与其他现有的pass有一定的关联性,所谓的关联体现之一就是:在运行此pass之前必须先运行某pass。类似这种情况,都有相应的接口可以实现。具体参考 Specifying interactions between passes


另外一种特殊情况就是,我们需要一种更高level的抽象去控制pass,比如将特定功能的一些pass进行分组。一个pass可以被重复注册到不同的分组中。具体参考 Implementing Analysis Groups


了解了上述两个特殊情况,你可以也就能够理解,为什么我说“类似流水线”了。


但总而言之,llvm Pass架构的可重用性和可控制性都非常好,这允许我们嵌入自己开发的pass或者关闭一些默认提供的pass。

单个pass的开发及调试也很独立,因此你不必担心破坏llvm整体的源码结构,只需要学会操作llvm ir即可实现自己的pass。这些过程都将在本文的后面及以后的系列文章中提及。



pass的分类


所有的pass大致可以分为两类:分析和转换

分析类的pass以提供信息为主,转换类的会修改中间代码。


可以实现的具体的pass类型如下:



通过继承指定的类实现相关的虚函数即可。

以上链接对每一种pass的作用范围及实现途径做了简单的介绍。


如果想更为清晰的掌握LLVM Pass,以下的一些源码文件是你需要简单的浏览一下的。 他们都是与pass相关的一些源码文件,你以后的学习过程中肯定也会有需求去翻阅它们。




编写pass


这一篇文章中我仅仅是按部就班的完成一个pass的示例,让大家对pass有一个宏观的初步认识,至于内部实现细节以及后续的拓展,现在还不必太在意,我们后续会提到。


在官方的文档以及源码中提供了一个简单的hello pass,在此,我提供一个略微复杂一点的pass作为示例。


  1. 在llvm src/lib/Transforms/ 目录下创建Test目录

  2. 转到Test目录,创建三个文件

      CMakeLists.txt

add_llvm_loadable_module( LLVMTest
    Test.cpp
)



      Makefile

LEVEL = ../../..
LIBRARYNAME = LLVMTest
LOADABLE_MODULE = 1
USEDLIBS =
include $(LEVEL)/Makefile.common



     Test.cpp

#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 "test"

namespace {
    struct Test : public FunctionPass {
        static char ID; // Pass identification, replacement for typeid
        
        Test() : 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 Test::ID = 0;

// 注册pass 命令行选项显示为test
static RegisterPass<Test> X("test", "Test Pass”);

3.  终端下面直接 make ,生成的LLVMTest.dylib存放在最终工具链旁边的lib目录下。



运行pass


  1.   加载pass

./opt -load ../lib/LLVMTest.dylib -help

 

3.png    

4.png


  2.    作用pass到bc文件上(如何生成bc文件,查看这里

./opt -load ../lib/LLVMTest.dylib -test < test.bc > charge_test.bc

 

5.png




最终效果如下:

6.png



上述的例子跟自带的示例一样简单,与自带示例不同的是它实现了一个转换性质的pass。

下一站,针对pass还需要做很多的功课,这一节仅仅是一个开始。



参考文献:

Writing an LLVM Passhttp://llvm.org/docs/WritingAnLLVMPass.html

LLVM’s Analysis and Transform Passeshttp://llvm.org/docs/Passes.html




标签: llvm clang

热度  14860 回应  7 收藏  0

  • 蓝旭晨枫
    你好,很感谢您得这么好的文章...我是初学者,有个疑问,生成LLVMTest.dylib文件是在哪个目录下执行make呢?能大致说一下LLVMTest.dylib这个文件的生成步骤吗?非常感谢~
    回应 2016-06-20 14:44:32
  • 玩命
    @charme 用刀,我怕你吃亏~
    回应 2015-04-21 19:25:10
  • charme
    @ThomasKing 多谢大神支持。。。。有错误和建议提出来。我改进。
    回应 2015-04-21 18:50:00
  • 玩命
    @charme 发扬一下 程序员精神嘛~~~ 调程序的时候也没见你有多闲麻烦啊。
    回应 2015-04-21 18:37:37
  • ThomasKing
    挺喜欢llvm的,多谢连载,收藏了。
    回应 2015-04-21 18:33:33
  • 玩命
    必须让邹老师,加个浏览次数 否则真不知道有没有人浏览。 文章我是没看了,但是有时你把重点词和关键字用不同的字体标出 人们看的时候有错落感,眼睛不难受。 继续坚持,慢慢就有人气了。
    回应 2015-04-21 17:25:03
llvm之旅第四站 - 编写Pass

作者信息

  • charme
  • 2015-03-30日入驻

收藏 0

文章 7

进入个人主页

娜迦,守护10亿移动用户安全! 免费体验