【问题标题】:Why are the variables "i" and "j" considered dead in the control flow graph?为什么变量“i”和“j”在控制流图中被认为是死的?
【发布时间】:2021-07-08 22:05:24
【问题描述】:

我在看红龙书归纳变量消除的题目,遇到了下面这个例子。

考虑下面的控制流程图:

图。 1 : 原始控制流图

现在作者对上图应用强度折减得到下图:

图 2:应用强度折减后的控制流程图

示例 10.4。在将强度降低应用于B2B3 周围的内部循环之后,ij 的唯一用途是确定块B4 中的测试结果。我们知道it2的值满足t2 = 4*i的关系,而jt4的值满足t4 = 4* j的关系,所以测试t2>=t4等价于i> = j一旦替换完成,块B2 中的i 和块B3 中的j 成为死变量,并且在这些块中对它们的赋值成为可以消除的死代码,导致在如下图3所示的流程图中。 □

图3:归纳变量消除后的流程图

我没有得到的是“iB2jB3 成为死变量”的说法。但是,如果我们沿着图 2 中的绿色路径考虑下图:

变量 ij 可能分别在块 B2B3 中存在,如果我们沿着绿色的路径走,如图所示并计入 ij 的使用(在他们各自的块中)在他们分配的右侧。这种特殊用途是

【问题讨论】:

    标签: loops optimization compiler-construction intermediate-language control-flow-graph


    【解决方案1】:

    变量不再有效,因为它们没有可观察到的影响。

    它们会递增和递减,但绝不会出于任何目的查询这些值。它们没有打印出来。没有控制流依赖于它们。没有其他变量是使用它们的值计算的。如果它们不增加和减少,没有人会注意到。

    消除它们不会以任何方式影响程序输出。所以他们应该被淘汰。


    作为活性的更正式定义,我们可以从以下内容开始:

    • 如果变量的值变得可观察(通过在程序执行之外可见,见下文),则该变量是有效的(在程序中的某个点)。

    • 如果变量的当前值用于计算活动值,则该变量也是活动的。

    该递归定义排除了将未使用的变量仅用于计算其自身或其他非实时变量的值的使用。这只是我在答案第一部分所说的更精确的说法:如果消除它不会对程序的执行产生明显的影响,那么分配是无关紧要的。

    “可观察效果”的精确定义将根据计算模型而有所不同,但它基本上意味着该值以某种方式在程序执行之外传递给世界。例如,如果值在控制台上打印或写入文件(包括用作要创建的文件的名称,因为文件目录也是文件),则该值是活动的。如果它存储在数据库中,或者导致指示灯闪烁,则它是实时的。 C 标准包括在可观察行为类别中读取和写入易失性内存,这是一种封装 CPU 的方式,CPU 使用特定内存地址的加载和存储作为从外围设备发送和接收数据的方式。

    有一个古老的哲学谜语:如果一棵树倒在无人居住的森林里,它会发出声音吗? 如果我们忽略这个问题的人类中心性,回答“不”似乎是合理的,就像许多 19 世纪的科学家一样。他们说,“声音”不仅仅是空气的振动,而是大气振动引起耳朵神经反应的结果。 (当然,可以想象一片森林根本没有任何有生命的生命,而不仅仅是人类生命,所以哲学家可以在这种防御中避难。)这基本上就是这种计算活性模型的最终结果:计算是可观察的,如果某人可以观察到它。 [注1]

    现在,这仍然可以解释,因为 某人 可能,例如,通过测量计算所花费的时间来“观察”计算。从这个意义上说,所有优化都应该是可观察的,因为如果不缩短计算时间,它们就毫无意义。

    如果我们将其视为可观察行为的一部分,则不可能进行有用的优化。所以在大多数情况下,这不是可观察性的特别有用的定义。但是有极少数用例需要保留计算使用的时间量。典型的此类案例是对抗安全攻击,该攻击通过计时值的各种不同用途来推断应该是秘密变量的值。如果您正在编写旨在维护高度机密的代码(例如,访问银行帐户所需的密码密钥),那么您可能希望在某些控制流中包含循环,这些循环没有任何计算目的,而是有意为之花费与使用相同秘密值的不同控制流完全相同的时间。

    举一个更有趣的例子,当我年轻得多并且计算机使用更多的电力来执行更慢的计算时,我们注意到您可以通过调整收音机来“收听”程序的执行以接收电磁振动由 CPU 产生。然后你可以编写不同类型的无意义循环来制作不同的音符或节奏人工制品。这种无意义的循环可以在微控制器中使用,以产生闪烁的显示,甚至直接驱动音频扬声器。因此,在某些情况下,您肯定希望编译器不消除“无用”代码。

    尽管如此,拒绝所有优化技术以实现可预测的执行时间可能不是一个好主意。大多数时候,我们真的希望我们的程序尽可能快地运行,或者消耗最少的不可再生能源;换句话说,避免做不必要的工作。但是由于在某些用例中优化会影响通常认为不可观察的行为,因此编译器需要为程序员提供一种机制来关闭特定代码段的优化。这些不是 Aho&c 正在讨论的案例,并且有充分的理由。


    注意事项:

    1. 乔治·伯克利,写于 1710 年:

      ……似乎同样明显的是,印在感官上的各种感觉或想法,无论是如何混合或组合在一起(即,无论它们构成什么对象),都只能存在于感知它们的心灵中……

      当时的一些哲学家提出了无所不知的上帝存在的必要性,以避免伯克利引起的混乱,在这种混乱中,当他闭上眼睛并重新创造时,他写作工作室中的物体突然不复存在。当他再次打开它们时眨眼。在这个论点中,不断看到一切的上帝保证了伯克利主教工作室中物体的连续性。我一直觉得这是一个神灵特别卑微的目的。 (她当然可以将这种平凡的任务委派给下属。)但每个人都是自己的。

      如需更多参考资料和小讨论,您可以开始here on Wikipedia。或者只听Bruce Cockburn's beautiful environmental anthem

    【讨论】:

    • The variables are no longer live because they have no observable effect. 但从实际定义的变量来看,正如文本所说,在重新定义之前应该沿着任何路径使用变量。所以,在上面的例子中,我们的路径回到了相同的定义,并且在重新定义之前在 rhs 上有一个使用,不应该考虑这种使用吗?我的意思是我们作为程序员是聪明的,但是如果编译器要按照定义消除死代码,那么 ij 不应该被它认为是活的。
    • 我明白了你的回答,一开始我也有同样的想法,但是live variable的定义让我很烦恼......
    • @abhishekGhosh:“可观察效果”的概念直接来自 C 标准,它明确允许编译器消除程序中没有可观察效果的任何部分。所以就是这样。如果某些未来可观察到的效果取决于该变量,则该变量是有效的。为变量赋值不会使变量生效。相反,如果变量是活动的(也就是说,将来会使用该变量),则计算变量的新值只是一种使用(无论它使用什么)。这是一个递归定义,但活性是递归的。
    • @AbhishekGhosh:好的,我在答案中添加了所有这些。我希望有人觉得它有用,或者至少很有趣。
    • 我不知道这个关于可观察效果的活性概念,这就是为什么我很难理解它。谢谢你..
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-02-28
    • 2018-09-06
    • 1970-01-01
    • 2013-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多