为什么变量“i”和“j”在控制流图中被认为是死的?

Why are the variables "i" and "j" considered dead in the control flow graph?

提问人:Abhishek Ghosh 提问时间:4/14/2021 更新时间:4/14/2021 访问量:282

问:

我正在阅读红龙书中的归纳变量消除主题,在那里我遇到了下面的例子。

考虑下面的控制流图:Original Control Flow Graph

图1:原始控制流图

现在,作者对上图应用强度降低,得到下图:

Control flow graph after applying strength reduction

图2:施加强度降低后的控制流程图

例 10.4.在对内环施加强度降低后,唯一的用途是确定块中的测试结果。我们知道 和 的值满足关系,而 和 的值满足关系,所以检验等价于 。一旦进行了这种替换,块 B2 中的 i 和块 B3 中的 j 就会变成死变量,并且这些块中对它们的赋值就会变成可以消除的死代码,从而产生如下图 3 所示的流图。□B2B3ijB4it2t2 = 4*ijt4t4 = 4* jt2>=t4i> = j

Flow graph after induction variable elimination

图3:感应变量消除后的流程图

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

Doubt illustration image

变量 和 可能在块中分别是活的,如果我们沿着绿色的路径走,如图所示,并计算其赋值右侧的 和 的使用(在它们各自的块中)。该特定用途是ijB2B3ij

循环 优化 编译器构造 中间语言 控制流图

评论


答:

1赞 rici 4/14/2021 #1

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

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

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


作为活体的更正式定义,我们可以从以下几点开始:

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

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

该递归定义排除了仅用于计算自身或其他非活动变量的值时未使用的变量。这只是一种更准确地表达我在答案的第一部分所说的方式:如果消除赋值不会对程序的执行产生可观察到的差异,那么赋值是无关紧要的。

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

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

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

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

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

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


笔记:

  1. 乔治·伯克利(George Berkeley)在1710年写道:

    ...同样明显的是,印在感官上的各种感觉或观念,无论如何混合或组合在一起(也就是说,无论它们构成什么对象),除了在感知它们的头脑中之外,都不能存在......

    当时的一些哲学家认为,无所不知的上帝必须存在,以避免贝克莱所召唤的混乱,即当他闭上眼睛时,他写作工作室中的物体突然不复存在,当他再次睁开眼睛时,它们会在眨眼间重新创造。在这个论点中,不断看到一切的上帝保证了伯克利主教工作室中物体存在的连续性。这一直让我印象深刻,因为对于一个神灵来说,这是一个特别卑微的目的。(当然,她可以将如此平凡的任务委托给下属。但对每个人来说都是他们自己的。

    如需更多参考资料和一些讨论,您可以从维基百科开始。或者只是听布鲁斯·科伯恩(Bruce Cockburn)优美的环保歌曲

评论

0赞 Abhishek Ghosh 4/14/2021
The variables are no longer live because they have no observable effect.但是,从要活动的变量的实际定义来看,正如文本所说,在重新定义之前,应该沿任何路径使用该变量。所以,在上面的例子中,我们路径回到了相同的定义,并且在重新定义之前对 rhs 有一个用途,难道不应该考虑这种用途吗?我的意思是,作为一个程序员,我们是聪明的,但是如果编译器要按照定义消除死代码,就不应该并被认为是活的。ij
0赞 Abhishek Ghosh 4/14/2021
我已经明白了你答案的重点,我一开始也以同样的方式思考,但它的定义让我很烦恼......live variable
1赞 rici 4/14/2021
@abhishekGhosh:“可观察效果”的概念直接来自C标准,它明确允许编译器消除程序中任何没有可观察效果的部分。所以就是这样。如果某个未来可观察到的影响取决于变量,则变量是活的。为变量赋值不会使变量处于活动状态。相反,如果变量是实时的(即变量将来有使用),则变量的新值的计算只是一种使用(无论它使用什么)。这是一个递归的定义,但活动是递归的。
1赞 rici 4/14/2021
@AbhishekGhosh:好的,我把这些都加到了答案中。我希望有人觉得它有用,或者至少很有趣。
0赞 Abhishek Ghosh 4/14/2021
我不知道这种关于可观察效果的活体概念,这就是为什么我很难理解它。谢谢。。