Skip to content

Commit

Permalink
rename passes
Browse files Browse the repository at this point in the history
  • Loading branch information
Gemini321 committed Apr 24, 2024
1 parent d738e75 commit 706d767
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 29 deletions.
52 changes: 26 additions & 26 deletions docs/task4_doc/framework.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,52 +2,52 @@

本次实验的框架主要分为以下两部分:

* 注册优化pass:在`main.cpp`中注册需要使用的优化pass,并指定优化顺序
* 实现优化pass:在optimizor.hpp中定义需要使用的优化pass类,并在其他文件中实现定义的优化pass的函数
* 注册Transform Pass:在`main.cpp`中注册需要使用的Transform Pass,并指定优化顺序
* 实现Transform Pass:在optimizor.hpp中定义需要使用的Transform Pass类,并在其他文件中实现定义的Transform Pass的函数

### 注册优化pass和分析pass
### 注册Transform Pass和Analysis Pass

注册优化pass的代码主要在`main.cpp``opt`函数中:
注册Transform Pass的代码主要在`main.cpp``opt`函数中:

```C++
void
opt(llvm::Module& mod, llvm::raw_fd_ostream &logFile)
{
// 定义分析pass的管理器
// 定义Analysis Pass的管理器
LoopAnalysisManager LAM;
FunctionAnalysisManager FAM;
CGSCCAnalysisManager CGAM;
ModuleAnalysisManager MAM;
ModulePassManager MPM;

// 注册分析pass的管理器
// 注册Analysis Pass的管理器
PassBuilder PB;
PB.registerModuleAnalyses(MAM);
PB.registerCGSCCAnalyses(CGAM);
PB.registerFunctionAnalyses(FAM);
PB.registerLoopAnalyses(LAM);
PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);

// 添加分析pass到管理器中
// 添加Analysis Pass到管理器中
MAM.registerPass([]() { return sysu::StaticCallCounter(); });

// 添加优化pass到管理器中
// 添加Transform Pass到管理器中
MPM.addPass(sysu::HelloWorldPass(logFile));
MPM.addPass(sysu::StaticCallCounterPrinter(logFile));

// 运行优化pass
// 运行Transform Pass
MPM.run(mod, MAM);
}
```
以上代码的注释清晰地呈现了LLVM IR优化pass和分析pass的注册过程
以上代码的注释清晰地呈现了LLVM IR中Transform Pass和Analysis Pass的注册过程
* 优化pass:使用`MPM.addPass(sysu::optPass())`函数添加
* 分析pass:使用`MAM.registerPass([]() { return sysu::analysisPass(); })`函数添加
* Transform Pass:使用`MPM.addPass(sysu::optPass())`函数添加
* Analysis Pass:使用`MAM.registerPass([]() { return sysu::analysisPass(); })`函数添加
需要注意的是优化pass的执行顺序与第三部分添加优化pass的顺序相同,因此在优化前需要考虑优化次序对优化结果的影响;而分析pass只会在被使用时执行,因此添加分析pass的顺序不影响执行顺序。实例化优化pass时我们传入了`logFile`变量,该变量能让我们在pass中将中间结果输出到`output.log`文件中,方便同学们进行调试(调试方法见[调试方法](./overview.md#调试方法)一节)。
需要注意的是Transform Pass的执行顺序与第三部分添加Transform Pass的顺序相同,因此在优化前需要考虑优化次序对优化结果的影响;而Analysis Pass只会在被使用时执行,因此添加Analysis Pass的顺序不影响执行顺序。实例化Transform Pass时我们传入了`logFile`变量,该变量能让我们在pass中将中间结果输出到`output.log`文件中,方便同学们进行调试(调试方法见[调试方法](./overview.md#调试方法)一节)。
### 实现优化pass
### 实现Transform Pass
以常量折叠优化`ConstantFolding`为例,其定义需要添加到`optimizor.hpp`中:
Expand All @@ -64,7 +64,7 @@ private:
};
```

由于本实验基于LLVM 17,因此不支持旧版本LLVM提供的基于`ModulePass``FunctionPass`等类继承的优化pass实现,新旧版本Pass机制的区别请阅读[Legacy Pass](#legacy-pass)一节。按照上述方式定义的Pass需要继承`PassInfoMixin`类,该类会接受模板参数中优化pass名称为pass进行初始化。每个优化pass都需要实现`run`函数,在该函数内同学们能够对生成的LLVM IR进行分析与变换,最终返回优化后的IR。常量折叠的`run`函数主体代码如下:
由于本实验基于LLVM 17,因此不支持旧版本LLVM提供的基于`ModulePass``FunctionPass`等类继承的Transform Pass实现,新旧版本Pass机制的区别请阅读[Legacy Pass](#legacy-pass)一节。按照上述方式定义的Pass需要继承`PassInfoMixin`类,该类会接受模板参数中Transform Pass的名称为pass进行初始化。每个Transform Pass都需要实现`run`函数,在该函数内同学们能够对生成的LLVM IR进行分析与变换,最终返回优化后的IR。常量折叠的`run`函数主体代码如下:

```C++
llvm::PreservedAnalyses
Expand All @@ -90,7 +90,7 @@ sysu::ConstantFolding::run(llvm::Module &M, llvm::ModuleAnalysisManager &MAM) {
上述代码展示了如何通过循环遍历`llvm::Module`中所有指令,以上遍历方法可以作为大部分指令优化的框架。使用该框架只需要将算法针对单条指令的处理逻辑填入`...`所处的代码块中,再辅以对指令的操作(例如对操作数的替换、指令的插入移动与删除等)即可完成优化算法的实现。
### 实现分析pass
### 实现Analysis Pass
以分析函数调用次数的`StaticCallCounter`为例,其定义需要添加到`optimizor.hpp`中:
Expand All @@ -101,18 +101,18 @@ public:
Result run(llvm::Module &module, llvm::ModuleAnalysisManager &);
private:
// 分析pass中必须包含"static llvm::AnalysisKey Key"
// Analysis Pass中必须包含"static llvm::AnalysisKey Key"
static llvm::AnalysisKey Key;
friend struct llvm::AnalysisInfoMixin<StaticCallCounter>;
};
```

分析pass和优化pass在定义时的区别在于
Analysis Pass和Transform Pass在定义时的区别在于

* 分析pass的继承对象`AnalysisInfoMixin`继承于优化pass的继承对象`PassInfoMixin`
* 分析pass需要声明`static llvm::AnalysisKey Key`因为其将作为分析pass区别于其他pass的唯一标识符被`AnalysisInfoMixin::ID()`函数返回
* 分析pass需要声明`friend struct llvm::AnalysisInfoMixin<passName>`,否则`llvm::AnalysisKey Key`会因为是`AnalysisInfoMixin`的私有变量而报错
* 分析pass的run函数返回自定义的结果而非`llvm::PreservedAnalyses`
* Analysis Pass的继承对象`AnalysisInfoMixin`继承于Transform Pass的继承对象`PassInfoMixin`
* Analysis Pass需要声明`static llvm::AnalysisKey Key`因为其将作为Analysis Pass区别于其他pass的唯一标识符被`AnalysisInfoMixin::ID()`函数返回
* Analysis Pass需要声明`friend struct llvm::AnalysisInfoMixin<passName>`,否则`llvm::AnalysisKey Key`会因为是`AnalysisInfoMixin`的私有变量而报错
* Analysis Pass的run函数返回自定义的结果而非`llvm::PreservedAnalyses`

实现`StaticCallCounter`的主体代码如下:

Expand Down Expand Up @@ -143,7 +143,7 @@ sysu::StaticCallCounter::run(Module &module, ModuleAnalysisManager &) {
AnalysisKey sysu::StaticCallCounter::Key;
```
注意`static llvm::AnalysisKey Key`是一个静态成员变量,在实现时需要额外声明,否则会出现静态变量未声明的报错。定义和实现分析pass后,我们需要在其他pass中调用该pass。下面的`StaticCallCounterPrinter`调用了定义、实现、注册好的`StaticCallCounter`,将分析结果以表格的形式输出到文件中:
注意`static llvm::AnalysisKey Key`是一个静态成员变量,在实现时需要额外声明,否则会出现静态变量未声明的报错。定义和实现Analysis Pass后,我们需要在其他pass中调用该pass。下面的`StaticCallCounterPrinter`调用了定义、实现、注册好的`StaticCallCounter`,将分析结果以表格的形式输出到文件中:
```C++
PreservedAnalyses
Expand All @@ -169,7 +169,7 @@ sysu::StaticCallCounterPrinter::run(Module &module,
}
```

需要调用分析pass时,可以通过`run()`函数传入的`ModuleAnalysisManager &MAM`进行调用在`MAM`中注册过的分析pass(注册方法见[注册优化pass和分析pass](#注册优化pass和分析pass)小节),返回类型为分析pass的`run()`函数中自定义的返回类型。通过分析pass和优化pass的灵活组合,同学们可以实现许多代码优化算法。
需要调用Analysis Pass时,可以通过`run()`函数传入的`ModuleAnalysisManager &MAM`进行调用在`MAM`中注册过的Analysis Pass(注册方法见注册Transform Pass和Analysis Pass小节),返回类型为Analysis Pass的`run()`函数中自定义的返回类型。通过Analysis Pass和Transform Pass的灵活组合,同学们可以实现许多代码优化算法。

### Legacy Pass

Expand All @@ -179,8 +179,8 @@ sysu::StaticCallCounterPrinter::run(Module &module,
* 定义:
* 旧Pass机制需要声明ID,该ID将作为区分不同pass的唯一标识符,同时ID作为静态成员变量需要在结构体定义外初始化;新Pass机制通过继承`PassInfoMixin`时传入的模板名作为区分pass的标识符。
* 旧Pass机制需要调用`initialize...`函数进行初始化,该函数需要通过预定义的宏传入参数生成;新Pass机制则不需要额外初始化。
* 旧Pass机制若需要使用分析pass,需要定义`getAnalysisUsage`函数并手动通过`AU.addRequired<...>()`添加分析pass;新Pass机制只需要在run函数中传入`FunctionAnalysisManager &FAM`即可在函数内使用在FAM注册过的分析pass
* 实现:旧Pass机制使用`runOnFunction`函数实现优化,该函数返回值表示当前pass是否修改过传入参数的内容;新Pass机制使用`run`函数实现优化,该函数返回值表示当前pass是否会改变某些分析pass的结果
* 旧Pass机制若需要使用Analysis Pass,需要定义`getAnalysisUsage`函数并手动通过`AU.addRequired<...>()`添加Analysis Pass;新Pass机制只需要在run函数中传入`FunctionAnalysisManager &FAM`即可在函数内使用在FAM注册过的Analysis Pass
* 实现:旧Pass机制使用`runOnFunction`函数实现优化,该函数返回值表示当前pass是否修改过传入参数的内容;新Pass机制使用`run`函数实现优化,该函数返回值表示当前pass是否会改变某些Analysis Pass的结果
* 注册:旧Pass机制需要使用预定义的宏生成`initialize...`函数,并定义新的`PassInfo`后注册;新版本Pass机制只需要通过`FPM.addPass()`注册。

`FlattenCFGPass`为例,两者的pass定义和实现代码如下:
Expand Down
6 changes: 3 additions & 3 deletions docs/task4_doc/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

## 任务描述

本次实验的实验内容是实现一个LLVM IR优化器,对中间代码生成的结果进行优化。实验的输入与输出均为LLVM IR,要求同学们在保证代码正确性的基础上面向给定测试样例进行代码优化。在LLVM中,中端优化函数以优化pass的形式存在,其作用是对输入的LLVM IR进行分析与变换,并输出变换后的LLVM IR。每个优化由一个或多个优化pass实现,不同优化的pass之间相互独立。在本次实验没有标准答案,同学们可以自由发挥,借助任何可能的优化方法提升程序的运行效率,并通过测评系统测评。
本次实验的实验内容是实现一个LLVM IR优化器,对中间代码生成的结果进行优化。实验的输入与输出均为LLVM IR,要求同学们在保证代码正确性的基础上面向给定测试样例进行代码优化。在LLVM中,中端优化函数以Transform Pass的形式存在,其作用是对输入的LLVM IR进行分析与变换,并输出变换后的LLVM IR。每个优化由一个或多个Transform Pass实现,不同优化的pass之间相互独立。在本次实验没有标准答案,同学们可以自由发挥,借助任何可能的优化方法提升程序的运行效率,并通过测评系统测评。

## 评分标准

Expand All @@ -15,12 +15,12 @@
本次实验不允许出现以下行为,若出现以下行为将视为作弊与抄袭:

* 面向测例编程,包括但不限于:通过识别文件名、输入、特定代码段等手段进行代码优化
* 直接调用LLVM内置的**优化pass**或者直接复制LLVM提供的优化pass代码
* 直接调用LLVM内置的**Transform Pass**或者直接复制LLVM提供的Transform Pass代码

我们允许以下行为:

* 在理解LLVM优化源代码的基础上将其简化移植
* 使用LLVM提供的**分析pass**获取优化所需的信息(优化pass和分析pass的区别是前者执行后会修改LLVM IR,而后者仅返回信息不改变IR)
* 使用LLVM提供的**Analysis Pass**获取优化所需的信息(Transform Pass和Analysis Pass的区别是前者执行后会修改LLVM IR,而后者仅返回信息不改变IR)
* 鼓励同学们添加实验测例中未涉及到的优化并提供相应测例(可在实验报告中说明,我们将在分析优化效果与优化实现难度后酌情加分)

## 调试方法
Expand Down

0 comments on commit 706d767

Please sign in to comment.