Compilation 是否有编译器能够建议绝对需要程序员批准的优化? 如果我们让人处于循环中,编译器能做的不仅仅是严格的语义等价优化吗?

Compilation 是否有编译器能够建议绝对需要程序员批准的优化? 如果我们让人处于循环中,编译器能做的不仅仅是严格的语义等价优化吗?,compilation,compiler-optimization,compiler-theory,logical-operators,short-circuiting,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 != ',')
由于比较字符(更快/更不复杂),因此应将其放在表达式的第一位,以便短路逻辑可以避免在遇到逗号时调用ISSTRINGPRENT。在这种情况下,逗号(每行多个)比新行序列更频繁地出现也是事实

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”的最佳操作数顺序都可以根据“A为假而B为触发短路的频率”和“计算A与B的成本,有利于成本较高的表达式短路”来确定。如果编译器可以在编译时、运行时或两者中确定其中一个的近似值,那么它可以确定某个特定表达式可能是次优的,并且可以创建一个建议的更改供程序员实现


今天有编译器做过类似的事情吗?如果没有,原因是什么?

我的观点是,仅仅因为程序员认为函数调用可以,就允许优化器短路函数调用,这会导致无法追踪的错误。它在每次编译时都会问吗?我不知道;听起来像这样的事情会有很多问题。

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

也许你是建议编译器检测到一个可能的同构,它不确定它是否是同构,因此它会问程序员“这是同构吗”,但在任何情况下,“如果是,如果我应用它,它会导致更快的代码吗,你认为?”

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


加强一个前置条件可能没问题,见鬼,程序员可能甚至没有编写一个前置条件。如果程序员说“当然,没问题”,而程序员错了,那么幸运的话,测试将揭示“前置条件失败”的问题。

你问的主要是程序员的任务。在某种程度上,有一些工具,如静态分析工具或重构工具,它们可以扩展以实现您想要的功能

编译器的任务是在标准规则范围内(尽可能地)发挥作用。对于某些(激进的)优化,编译器确实提供了特定的标志,可以通过这些标志来启用/禁用它们 e、 向量化、内联、过程间等——这些优化很难手工完成


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

噢,不。假设短路总是发生,例如在C#中。我所说的“决定是否短路”是指“特定操作数”,即决定在表达式中对其进行第一或第二次排序。第二个表达式将被短路,而第一个表达式总是被计算的。当然,它会在每次编译期间检查潜在的优化,并将它们集中在一个列表中,就像编译“警告”一样。如果程序员做出了建议的更改,那么在下一次编译过程中显然不会检测到它。否则,它会像现在一样永远坐在那里。是的,所以我说。。。“短路表达式优化”是确定操作数的最佳顺序,方法是将最快/最有可能触发短路的操作数放在后一个操作数的前面,并将运行速度较慢/更希望短路的操作数放在最后,编译器的问题是IsStringPresent可能有副作用,不这样做是不正确的。因此,是的,编译器必须询问。它必须写下一个假设列表,你必须回顾它。一旦这个列表变长了,它就会成为bug的来源:假设改变了,你不会注意到