达到定义数据流问题的特例

时间:2011-04-14 16:53:23

标签: compiler-construction compiler-theory

达到定义的问题是数据流分析中最基本的问题之一。给定一个包含变量定义和用途的控制流图,问题将导致计算哪些变量定义可能达到特定用途。

例如,考虑流程图:

                    ____________
                 1:|   x <- ... |
                    ------------
                     |            \
                     |              __________
                     |           2:| x <- ... |
                     |              -----------
                     |            /
                    ____________    
                 3:|  ... <- x  |
                    ------------

可以从块1或块2中的任一定义达到块3中变量x的使用。

用于计算哪些定义可能达到使用的算法是经典数据流问题。使用龙编译器书(新版)中的符号来定义数据流问题如下:

域:定义集(例如{x&lt; - ..,...})
方向:前进
传递函数:fb(x)= gen(B)U(x - kill(B))其中gen(B)是块B生成和终止的定义集(B)阻止B杀死的定义集合/> 边界:OUT [ENTRY] = {}即没有用于输入函数的定义流 满足运算符:U(联合),即流向块的定义是前一个块中定义的并集 方程:OUT [B] = fb(IN [B]),IN [B] = U(P in pred)OUT [P]
初始化:OUT [B] = {}

但是,并非所有定义都相同。例如,块1中的定义可能永远不会在块3中使用,因为它可能被块2中的定义杀死。另一方面,块2中的定义,如果被执行,将保留其值,直到它在块中的使用为止。 3。

我想找到从定义到用法的任何路径上没有查找定义的用法的定义。我的问题是是否存在类似的数据流问题(可能是传播等)。如何在数据流分析方面解决。

我确实有一个可能的问题解决方案,但如果解决方案已经存在,我不想重新发明轮子。

3 个答案:

答案 0 :(得分:0)

像这样更改问题定义:

满足运算符:∩(相交),即流向块的定义是前驱块中定义的交集。

方程式:OUT [B] = fb(IN [B]),             IN [B] =∩(P in pred)OUT [P]

答案 1 :(得分:0)

以下是我解决问题的方法。它可能不是最有效的方式,但我相信它有效。我将把问题称为保留定义的问题。首先,我计算到达定义。我在由位集表示的定义集上使用迭代数据流算法。

为了做到这一点,我需要首先计算每个块的gen(B)和kill(B)。这些是分别由每个块生成和杀死的定义。请注意,kill(B)是实际kill(B)的超集,因为我不知道什么定义以及什么块实际被杀死,因为此时我没有考虑数据流。

应用到达定义后,我在控制流图中为每个块设置了REACH_IN(B)和REACH_OUT(B)。我知道保留的定义是到达定义的一个子集。为了计算它们,我需要找出从程序条目到每个块的内容永远不会被杀死的定义。我将这些集称为no kill sets,我将提供一个算法来计算图中每个块的NO_KILL_IN(B)和NO_KILL_OUT(B)。这是数据流分析方面的算法。

域:定义集(例如{x&lt; - ..,...})
方向:前进
传递函数:fb(x)= x - (kill(B)∩REACH_IN(B))其中kill(B)是阻止B杀死的定义集合,REACH_IN(B)是流入B的定义集合。 /> 边界:NO_KILL_OUT [ENTRY] = U (通用设置),即所有定义都不会从函数的输入中被杀死 遇见运算符:∩(交集),即如果没有在任何前一个块中被杀死,则不会杀死该定义 公式:NO_KILL_OUT [B] = fb(IN [B]),NO_KILL_IN [B] =∩(P in pred)NO_KILL_OUT [P]
初始化:NO_KILL_OUT [B] = U

请注意,在tranfer函数中,我们计算kill(B)∩REACH_IN(B),它是在块B中被杀死的实际定义的集合。如果我们不使用它,我们将过度持续。该算法计算在每个块之前和之后不能被杀死的定义,而不考虑它们是否已经生成。为了计算保留的定义,我们只需预先形成交集:

PRESERVE_IN(B)= REACH_IN(B)∩NO_KILL_IN(B)
PRESERVE_OUT(B)= REACH_OUT(B)∩NO_KILL_OUT(B)

答案 2 :(得分:0)

您可能希望查看时态逻辑,计算树逻辑非常适合在控制流图中定义路径上的属性。本文显示了CTL中数据流属性的一些示例:

Proving correctness of compiler optimizations by temporal logic