总结
LLVM Pass简单总结:对IR进行遍历、优化的逻辑,例如:
代码语言:javascript复制opt --help
...
...
Optimizations available (use '-passes=' for the new pass manager)
...
...
--loop-deletion - Delete dead loops
--memcpyopt - MemCpy Optimization
--print-callgraph - Print a call graph
...
...
opt提供了很多pass,例如检测代码中的死循环、对代码中的memcpy优化、遍历全部函数分析调用关系等等。
上述都是pass可实现的功能,llvm工程中给出了一个实例:
hello pass实例
LLVM version 16.0.6
库中位置:llvm/lib/Transforms/Hello/Hello.cpp
代码语言:javascript复制//===- Hello.cpp - Example code from "Writing an LLVM Pass" ---------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements two versions of the LLVM "Hello World" pass described
// in docs/WritingAnLLVMPass.html
//
//===----------------------------------------------------------------------===//
#include "llvm/ADT/Statistic.h"
#include "llvm/IR/Function.h"
#include "llvm/Pass.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
#define DEBUG_TYPE "hello"
STATISTIC(HelloCounter, "Counts number of functions greeted");
namespace {
// Hello - The first implementation, without getAnalysisUsage.
struct Hello : public FunctionPass {
static char ID; // Pass identification, replacement for typeid
Hello() : FunctionPass(ID) {}
bool runOnFunction(Function &F) override {
HelloCounter;
errs() << "Hello: ";
errs().write_escaped(F.getName()) << 'n';
return false;
}
};
}
char Hello::ID = 0;
static RegisterPass<Hello> X("hello", "Hello World Pass");
namespace {
// Hello2 - The second implementation with getAnalysisUsage implemented.
struct Hello2 : public FunctionPass {
static char ID; // Pass identification, replacement for typeid
Hello2() : FunctionPass(ID) {}
bool runOnFunction(Function &F) override {
HelloCounter;
errs() << "Hello: ";
errs().write_escaped(F.getName()) << 'n';
return false;
}
// We don't modify the program, so we preserve all analyses.
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesAll();
}
};
}
char Hello2::ID = 0;
static RegisterPass<Hello2>
Y("hello2", "Hello World Pass (with getAnalysisUsage implemented)");
这个pass会跟着工程编译,无需自己编译了。
生成的so位置:pathto/llvm-project/build/lib/LLVMHello.so
如何使用pass?
pass需要分析IR,先生成一个IR:
t3.cpp
代码语言:javascript复制int g_var = 0;
int factorial(int val);
int factorial(int val)
{
g_var = 1;
if (val <= 2)
return 1;
return factorial(val - 1) factorial(val - 2);
}
int factorial_iter(int val)
{
int temp = 1;
for (int i = 2; i <= val; i)
temp *= i;
return temp;
}
int main(int argc, char **argv)
{
return factorial(2) * 7 == 42;
}
生成IR
$ clang -O0 -emit-llvm t3.cpp -c -o t3.bc
用pass分析t3.bc
代码语言:javascript复制$ opt -load pathto/llvm-project/build/lib/LLVMHello.so -enable-new-pm=0 -hello t3.bc
Hello: _Z9factoriali
Hello: _Z14factorial_iteri
Hello: main