Compiler construction 在低级中间代码中计算数组和其他非标量的活跃度

Compiler construction 在低级中间代码中计算数组和其他非标量的活跃度,compiler-construction,compiler-theory,Compiler Construction,Compiler Theory,我很难理解计算数组活性的概念,因为它们是非标量值。所有讨论活动性的书籍和课程都只使用标量值,但非标量似乎需要以不同的方式计算其活动性,例如,当数组元素通过赋值定义时,这并不一定意味着整个数组在该点之前不再像标量值那样活动。更复杂的是,您只能在高级中间代码中访问数组的定义和使用,当我们转到较低级别时,这些信息部分消失。有人知道怎么做吗 编辑:我的最终目标是为堆栈帧的图着色生成干涉图,以最小化其大小,因此我需要精确的活动度信息或活动范围。这个问题实际上是一个由两部分组成的问题。首先,我们如何计算高级

我很难理解计算数组活性的概念,因为它们是非标量值。所有讨论活动性的书籍和课程都只使用标量值,但非标量似乎需要以不同的方式计算其活动性,例如,当数组元素通过赋值定义时,这并不一定意味着整个数组在该点之前不再像标量值那样活动。更复杂的是,您只能在高级中间代码中访问数组的定义和使用,当我们转到较低级别时,这些信息部分消失。有人知道怎么做吗

编辑:我的最终目标是为堆栈帧的图着色生成干涉图,以最小化其大小,因此我需要精确的活动度信息或活动范围。这个问题实际上是一个由两部分组成的问题。首先,我们如何计算高级中间代码中非标量值的活跃度,其次,我们如何将该解决方案转换为低级中间代码版本

编辑: 这是C语言中的一个问题示例,但在AST或高级中间代码中可能非常类似

void testFunction() {
    int n;
    int i[100]; // array is declared here

                // array is dead before this point
    i[10] = n;  // array elements are used/defined here, the array is live
    n = i[11];  // array elements are used/defined here, array is still live


    // other code here

    i[12] = n;  // array elements are used/defined here, array is still live
    i[13] = n;  // array elements are used/defined here again but for the            
                // last time, after this the array is not live
 }
不过,在低级中间代码中,这些数组访问会分解为许多指令,而在优化之后,我们可能会丢失关于这些指令的详细信息 当使用和定义数组元素时,因为指令可能会有些混乱,所以会变得有点混乱

n = i[10]
变得有点像

t0 = 10        // the element of the array we are indexing into
t1 = t0 * size // the size of each element of the array
t2 = &i        // the base address of the array named "i"
t3 = t1 + t2
n  = *t3
编辑:我想我可能只需要将元数据添加到低级解引用指令中,就可以在下面的低级中间代码中获得非标量的定义和用法

t0 = &i // this would not count as a use since it is only the 
        // address of the array i

n = *t0 // use of i
*t0 = n // definition of i
这只剩下提取非标量的活动/活动范围的问题。 标量活跃度是作为一个向后的数据流问题来计算的,当一个变量的使用被看到时,它变为活跃的,当我们遇到它的定义时,它就消失了。 对于非标量活性,它的生命周期似乎需要从第一个开始延长 在每个流上遇到最后一个定义之前遇到def或use 路径我想先计算非标量的到达定义,然后用它来计算def使用和def链,然后合并所有
将def链一起使用到一个活动范围内。我认为这将为任何非标量提供适当的活动范围,只要它的初始定义不是在函数?之外完成的,在这种情况下,它将一直活动到函数入口点。所以这对全球人来说不起作用,但他们无论如何都会被视为一直活着,不需要计算他们的活跃度。我遗漏了什么吗?有人能想出更好的方法吗?

活性分析总是一个保守的估计。“活动”变量可能永远不会被使用。(它的未来用途可能是有条件的,甚至基于可能已经确定其值的条件。)重要的是,只需保证不需要非活动变量。分析越精确,优化的可能性就越大,但有一个权衡:与可能的附加值相比,更精确的分析可能成本过高

在这种情况下,有必要问一个问题,知道数组的一部分不是活动的,可以产生什么价值。例如,只有在非常不寻常的情况下才可能回收阵列的一部分

因此,将数组视为单个实体是一种合理的方法。在这种近似情况下,如果数组中的任何元素是活动的,则数组是活动的;只有在阵列中不需要任何元素的情况下,我们才从活动集中删除阵列。很明显,这是一个保守的近似值;如前所述,它可能提供尽可能多的有用信息


知道特定数组元素的值可能很有用,但即使在那里,也通常认为能够知道整个数组不会发生变异,而不是试图跟踪单个元素的易变性就足够了。一旦知道数组是不可变的,就可以在已知索引处推断元素的值,从而允许对涉及查找表的表达式进行常量折叠。有些编译器确实做到了这一点,但在复杂性和附加值之间又有一个折衷,在很难或不可能进行完全精确分析的情况下,不需要绝对精度。

我认为,在我的情况下,将阵列视为单个实体,并说只要至少有一个元素仍在使用,它就处于活动状态,这是我需要的,只有当所有元素都不再被使用时,我们才能说它真的死了。我的目标是在所有溢出的变量、数组和其他非标量之间生成干涉图,这些非标量将存储在堆栈帧中,而不是存储在寄存器中。@binaryLust:这就是我考虑的示例。