@@ -208,15 +208,21 @@ define i32 @main() {
208
208
我们还是举个例子辅助理解:CFG图中沿着节点4向下走,5是被4支配的(如果程序要进行到节点5一定经过4),而接着到7节点的时候,我们发现4不再支配7了。由此我们便说4的支配边界是7。
209
209
210
210
类似J操作,我们对集合也可以定义DF操作, $DF(S)=\bigcup_ {s{\in}S}DF(s)$ 。DF还可以进一步迭代,即
211
+
211
212
$$
213
+ \begin{align*}
212
214
DF_1(S)=DF(S)\\
213
- DF_{i+1}(S)=DF_{i}(S)\\
215
+ DF_{i+1}(S)=DF(S \cup DF_{i}(S) )\\
214
216
DF^{+}(S)=DF_{i->\infty}
217
+ \end{align*}
215
218
$$
219
+
216
220
还记得我们想要求的 $J(Def)$ 嘛?事实上:
221
+
217
222
$$
218
223
DF^{+}(S)=J(S\ \cup\ entry)
219
224
$$
225
+
220
226
这里的entry是程序的入口基本块。在SSA原文默认的程序中,我们需要在entry基本块中定义所有使用的变量,因此在没有entry基本块的基本块集合中,会有可能出现变量未被定义的情况。而在我们课程组推荐的llvm架构中,没有这样纯定义变量的entry块,因此可以大致理解为 $DF^{+}(S)=J(S)$ 。
221
227
222
228
那么任务就很明确了,对于每个变量v,求出 $DF^{+}(Def_v)$ 就知道了需要插入phi函数的位置。
@@ -750,10 +756,12 @@ BB4:
750
756
本阶段的主要任务是通过数据流分析方法,计算在每条指令执行时同时活跃的临时变量,该集合的每一对临时变量两两形成一条边加入冲突图中,
751
757
752
758
构造阶段的主要工作是进行数据流分析,数据流分析我们建议分为两个阶段,首先是进行基本块的数据流分析,分析的数据流方程如下(两个阶段的数据流分析均使用同一个方程)
759
+
753
760
$$
754
761
in[m] = use[m]\cup(out[n] - def[n])\newline
755
762
out[n] = \mathop{\cup}_{s \in succ[n]}in[s]
756
763
$$
764
+
757
765
第二阶段是进行指令间的数据流分析,得到冲突图,指令冲突的条件是在变量定义处所有出口活跃的变量和定义的变量是互相冲突的,以及同一条指令的出口变量互相之间是冲突的,例如下面的代码
758
766
759
767
``` assembly
@@ -819,13 +827,17 @@ add $4, $5, $6
819
827
#### 2. 除法优化
820
828
821
829
除法优化的思路是将除法指令转化为乘法指令和移位指令,即如下公式:
830
+
822
831
$$
823
832
quotient = \frac{dividend}{divisor} = (dividend * multiplier) >> shift
824
833
$$
834
+
825
835
该公式先乘一个较大的常数,然后用右移* shift* 位得到最终的答案,使用该式子计算除法的核心是如何得到* multiplier* ,另外由于mips架构是32位的,还必须要考虑溢出的问题。mips在执行乘法的时候会将结果保存到hi和lo寄存器当中,在被除数乘* multiplier* 之后,很容易就会超过32位,这个就会出现一部分答案在hi寄存器中,一部分答案在lo寄存器当中,所以我们需要使* multiplier* 尽量大(超过$2^{32}$),能够使答案的部分在hi寄存器当中。所以最终的公式可以写为如下形式
836
+
826
837
$$
827
838
quotient = \lfloor \frac{n}{d}\rfloor = \lfloor\frac{m * n}{2^{N + l}} \rfloor
828
839
$$
840
+
829
841
其中N是机器码长度32,最终获得答案的公式为$SRL(MULUH(m,n), shift)$,$MULUH$表示乘法之后取HI寄存器。
830
842
831
843
论文当中提出了一种* mutiplier* 和* shift* 的获得方法,具体证明可以同学们可以查阅论文
0 commit comments