为什么编译器不能(总是?)优化具有GOTO的代码?

时间:2013-07-19 11:20:09

标签: compiler-construction goto

我已经编写了一些PL / SQL程序,我发现GOTO很有帮助,比如跳出嵌套循环等等。

我一直在想,如果在其他语言中使用gotos真是个坏主意。 (例如C ++。)

我发现了这些问题:

GOTO still considered harmful?

effect of goto on C++ compiler optimization

答案是:"编译器通常无法优化包含gotos的代码。"

而在另一个中:"然而,有可能生成一个带有gotos的流程图,这些流图不能由任何正常的流控制语句(循环,开关等)产生&# 34;

我已经被告知过了邪恶,但是没有人告诉我为什么,除了带有gotos的代码很难阅读。好吧,如果没有人学习,了解如何使用它们,因为它们是“邪恶的”,没有人可以阅读它们。

当编译器CAN和CAN不优化包含GOTO的代码时会出现什么情况?为什么?

1 个答案:

答案 0 :(得分:2)

大胖子免责声明:

  

我一直在想,如果在其他语言中使用gotos真是个坏主意。 (例如C ++。)

除了一个与大量纪律相结合的例外(C,如下所述),它几乎从来都不是一个好主意。这是依赖于语言的,所以请问你当地的大师,但是你找到一个好的用例的可能性相当小。呃谨慎一点。机会有一种更惯用和更清晰的方式来做任何你倾向于使用goto的事情。


这不是一个“不能永远”或停止 - 问题 - 不可能的情况,因为“只是不切实际”。有时,特别是如果你只是通过手动编写等效的goto来隐藏你的循环(这是一个愚蠢的事情!),它可能是偶然的。在其他时候,特别是如果控制流图类似于意大利面条或者奇怪/异常,编译器可能无法管理优化任何内容。

只有这么多时间和思考才能创建优化传递,并且编译器只需花费很多时间来运行优化传递。专注于大多数语言(while循环,具有已知起始行程计数,早期return,{{1}的循环,广泛使用,易于理解的控制流模式更有意义。 },switch的链等。即使优化发生在仅 支持else if - esque控制流的IR上,这些模式也会导致可预测的,容易识别的伪装,并且优化被调整为寻找那些。这就是你引用的第二句话。如果代码以一种完全不同于循环的方式来回跳转,那么循环展开将不会给它一天中的时间,即使它实际上是一种聪明的(不好的聪明)写作方式“这样做四次”

到目前为止,我假设goto类似于标准C中的那个 - 也就是说,目标标签是静态已知的并且仅限于遵守其他语言结构(例如,仅在一个函数内跳转)。存在允许跳转到任意动态选择的目标(例如“计算的转到”)的扩展。这些很难分析(并因此优化),可能与函数指针在同一个球场中。

  

我被告知这是邪恶的,但没有人告诉我为什么,除了带有gotos的代码是可怕的阅读。好吧,如果没有人学习,了解如何使用它们,因为它们是“邪恶的”,没有人可以阅读它们。

那些告诉你的人做得不好。这不是问题所在,所以我会保持简短:99%的控制流程适合很少的类别,这些类别需要专门的控制流程结构。对于所有这些情况,使用单个构造GOTO模糊了意图,代码更多,并且需要更长时间才能理解代码正在做什么。您可以亲身体验一下:编写一些相当复杂的> 100行批处理文件(那种可怕的古老Windows脚本语言)。

啊,还有一件事:

  

我发现GOTO很有帮助,比如跳出嵌套循环

这可能是一种很好的用途,但大多数语言提供了更清晰的方法。或者,将循环展平(例如使用Python的goto)和itertools.combinations,或者将嵌套循环放入单独的函数(在许多情况下无论如何都是好主意)和break

此外,这些 return的良好用途。例如,C语言中的错误处理。这些用例通常也符合一个简单的模式,但是没有内置到语言中的模式,所以必须要做到这一点。