是否有编译器能够建议绝对需要程序员批准的优化?

时间:2011-12-01 20:18:02

标签: compilation compiler-optimization compiler-theory logical-operators short-circuiting

如果我们将人保持在循环中,编译器可以做的不仅仅是严格的语义等效优化吗?

有一些潜在的优化被编译器彻底驳回,因为它们可能在语义上不等同。

然而,他们可能也可以,所以为什么不尝试检测并建议它们呢?检测可能涉及两个阶段的过程:编译时分析阶段和运行时分析阶段。

错误,警告和......建议?

编译器已经做了类似于“警告”的事情,因为它们在每次编译时被汇集,并且永远坐在列表中,直到你满足编译器的满意度。为什么不能以类似的方式运行“建议”或“建议的优化”部分,并且有可能提高应用程序的性能?

如果编译器要分析布尔表达式的复杂性,估计的运行时间,单个操作数的真实性与错误的可能性等等,那么它可以创建一个建议列表,例如表达式操作数的更好顺序,以及将建议作为列表提供给程序员。然后程序员可以单独解决它们,并决定忽略它们,或让代码编辑器实现该建议。

优化布尔表达式操作数顺序

考虑“短路逻辑表达式的优化”。因为操作数的顺序影响哪个操作数可能被“短路”(即未被调用),所以简单布尔表达式(即A&& B& C)中的操作数的顺序是(我认为)编译器保持不受影响,以避免在任何操作数有副作用时引入未知的副作用。

考虑一下:

char c = reader.ReadChar(); //Stream bs; const string NEWLINE;
while (!IsStringPresent( c, bs, NEWLINE ) && c != ',')

由于比较一个字符(更快/更简单),它应该首先出现在表达式中,这样短路逻辑可以避免在遇到逗号时调用IsStringPresent。在这种情况下,也可以比新行序列更频繁地遇到逗号(每行很多)。

char c = reader.ReadChar(); //Stream bs; const string NEWLINE;
if (c != ',' && !IsStringPresent( c, bs, NEWLINE )) //faster for short-circuit; plus ',' is encountered more often than newline

摘要

客观地,可以基于“A是假而B与B触发短路的频率”和“计算A与B的成本,有利于”来确定任何表达“A&& B”的最佳操作数顺序。短缺更昂贵的一个“。如果编译器可以在编译时,运行时或两者中确定其中任何一个的近似值,那么它可以确定特定表达式可能是次优的,并且它可以创建建议的更改以供程序员实现

今天有任何编译器做这样的事吗?如果没有,为什么?

3 个答案:

答案 0 :(得分:0)

我的观点是,允许优化器短路函数调用只是因为程序员认为它没问题,是一个无法解决的错误的配方。在每次编译期间都会询问吗?我不知道;听起来像这样的事情会有很多问题。

答案 1 :(得分:0)

我的回答是“可能”,但“这是我们真正想做的事情吗?”

也许你建议编译器检测到一个可能的同构,它不确定是同构,所以它要求程序员“这是一个同构”,但无论如何“如果是这样,如果我应用它,将会它会导致代码更快,你觉得呢?“

然而,我的想法更像是这样:“嘿程序员,如果我们能做到这一点,我们会得到更快的代码,但是,语义是不同的!我们必须加强这个函数的前提条件做这个优化。那可以吗?“

加强先决条件可能没问题,哎呀,程序员可能甚至没有写出先决条件。如果程序员说“当然,那没关系”并且程序员错了,那么运气测试就会发现“前置条件失败”的问题。

答案 2 :(得分:0)

你问的主要是程序员的任务。在某种程度上,有一些工具,如静态分析工具或重构工具,可以扩展到完成你想要的工作。

编译器任务是在标准规则内尽可能地发挥作用(尽可能多)。对于某些(激进的)优化,编译器会提供特定的标志,可以传递这些标志以启用/禁用它们 例如矢量化,内联,程序间等 - 这些优化很难手工完成。

重新排序(在您提到的示例中)受C,C ++标准的限制,因为它们可能会更改程序的语义。如果操作没有副作用,可以对它们进行重新排序,编译器会在指令调度期间执行此类操作(在clang ++和g ++中使用-O2)但我不确定有多少其他编译器会这样做。