Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

修正代码优化部分公式 #62

Merged
merged 1 commit into from
Nov 25, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion docs/tutorials/09-code-optimization.md
Original file line number Diff line number Diff line change
Expand Up @@ -208,15 +208,21 @@ define i32 @main() {
我们还是举个例子辅助理解:CFG图中沿着节点4向下走,5是被4支配的(如果程序要进行到节点5一定经过4),而接着到7节点的时候,我们发现4不再支配7了。由此我们便说4的支配边界是7。

类似J操作,我们对集合也可以定义DF操作, $DF(S)=\bigcup_{s{\in}S}DF(s)$ 。DF还可以进一步迭代,即

$$
\begin{align*}
DF_1(S)=DF(S)\\
DF_{i+1}(S)=DF_{i}(S)\\
DF_{i+1}(S)=DF(S \cup DF_{i}(S))\\
DF^{+}(S)=DF_{i->\infty}
\end{align*}
$$

还记得我们想要求的 $J(Def)$ 嘛?事实上:

$$
DF^{+}(S)=J(S\ \cup\ entry)
$$

这里的entry是程序的入口基本块。在SSA原文默认的程序中,我们需要在entry基本块中定义所有使用的变量,因此在没有entry基本块的基本块集合中,会有可能出现变量未被定义的情况。而在我们课程组推荐的llvm架构中,没有这样纯定义变量的entry块,因此可以大致理解为 $DF^{+}(S)=J(S)$ 。

那么任务就很明确了,对于每个变量v,求出 $DF^{+}(Def_v)$ 就知道了需要插入phi函数的位置。
Expand Down Expand Up @@ -750,10 +756,12 @@ BB4:
本阶段的主要任务是通过数据流分析方法,计算在每条指令执行时同时活跃的临时变量,该集合的每一对临时变量两两形成一条边加入冲突图中,

构造阶段的主要工作是进行数据流分析,数据流分析我们建议分为两个阶段,首先是进行基本块的数据流分析,分析的数据流方程如下(两个阶段的数据流分析均使用同一个方程)

$$
in[m] = use[m]\cup(out[n] - def[n])\newline
out[n] = \mathop{\cup}_{s \in succ[n]}in[s]
$$

第二阶段是进行指令间的数据流分析,得到冲突图,指令冲突的条件是在变量定义处所有出口活跃的变量和定义的变量是互相冲突的,以及同一条指令的出口变量互相之间是冲突的,例如下面的代码

```assembly
Expand Down Expand Up @@ -819,13 +827,17 @@ add $4, $5, $6
#### 2. 除法优化

除法优化的思路是将除法指令转化为乘法指令和移位指令,即如下公式:

$$
quotient = \frac{dividend}{divisor} = (dividend * multiplier) >> shift
$$

该公式先乘一个较大的常数,然后用右移*shift*位得到最终的答案,使用该式子计算除法的核心是如何得到*multiplier*,另外由于mips架构是32位的,还必须要考虑溢出的问题。mips在执行乘法的时候会将结果保存到hi和lo寄存器当中,在被除数乘*multiplier*之后,很容易就会超过32位,这个就会出现一部分答案在hi寄存器中,一部分答案在lo寄存器当中,所以我们需要使*multiplier*尽量大(超过$2^{32}$),能够使答案的部分在hi寄存器当中。所以最终的公式可以写为如下形式

$$
quotient = \lfloor \frac{n}{d}\rfloor = \lfloor\frac{m * n}{2^{N + l}} \rfloor
$$

其中N是机器码长度32,最终获得答案的公式为$SRL(MULUH(m,n), shift)$,$MULUH$表示乘法之后取HI寄存器。

论文当中提出了一种*mutiplier*和*shift*的获得方法,具体证明可以同学们可以查阅论文
Expand Down