问题标签 [compiler-optimization]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
4 回答
2606 浏览

c++ - Visual Studio C++ 编译器优化破坏代码?

我在这里有一个特殊的问题,VS2005 和 2010 都发生了这种情况。我有一个 for 循环,其中调用了一个内联函数,本质上是这样的(C++,仅用于说明目的):

然后在另一个函数中循环:

现在发生的事情是在调试构建中一切正常。在打开了所有优化的发布版本中,根据反汇编,编译后i直接使用而没有* 10,比较a > 100变成a > 9,而我想应该是a > 10. 你有什么线索可以让编译器认为这a > 9是正确的方法吗?有趣的是,即使是周围代码中的微小更改(例如调试打印输出)也会使编译器使用i * 10并将其与文字值 100 进行比较。

我知道这有点含糊,但我会感谢任何旧想法。

编辑:

这是一个有望重现的案例。我不认为它太大而不能粘贴在这里,所以这里是:

我在我的机器上使用 VS2010 对此进行了测试,它的表现似乎与我遇到问题的原始代码一样糟糕。我在发布配置中使用 IDE 的默认空 C++ 项目模板编译并运行了它。如您所见,决不应该触发中断 (37 * 16 = 592)。请注意,删除i < 4使这项工作,就像在原始代码中一样。

0 投票
1 回答
697 浏览

compiler-optimization - 编译器代码生成——条件块内的寄存器分配

我正在为一门课程编写编译器。我遇到了一些优化问题,我不确定如何以最佳方式处理这些问题。假设输入语言中有一个使用 N 个局部变量的 while 循环,这些局部变量必须保存在寄存器中(或者应该保存在寄存器中,以便快速计算)。假设 N > K,寄存器的数量。有可能在 while 循环结束时更改条件寄存器。

例如,假设 x 的寄存器(比如 i386 上的 %eax)在以下语句之前确定:

在 more statements 代码中,x 可能会溢出回堆栈。当代码跳回到 while 循环的开头重新计算 x 时,它会尝试使用 %eax——但这现在可能甚至没有保存 x 的值。所以我们可以有类似的东西

我正在使用的一种解决方案是强制代码在 while 语句之前溢出所有已修改的寄存器(因此从代码生成器的角度来看,寄存器被视为空)。在 while 循环的标签之后,代码必须根据需要将所有内容加载到寄存器中。

我的解决方案是这样的:

似乎我的解决方案有点多余或不必要。我在这里忘记了一些一般的优化技巧吗?

编辑:我还想指出类似的情况也发生在 if 和 if else 等条件句中。这发生在他们身上,因为可以为条件块内的变量分配一个寄存器,但代码生成器假定它被移到那里用于之后的所有其他事情。我处理这种情况的方法几乎相同。

0 投票
2 回答
2815 浏览

visual-c++ - 在 VC++ 中,/O2 编译器选项的#pragma 等效项是什么(优化速度)

根据msdn

/O2(最大化速度)

相当于

/Og/Oi/Ot/Oy/Ob2/Gs/GF/Gy

并再次根据msdn,以下pragma

#pragma optimize("[优化列表]", {on | off} )

在其“优化列表”中使用与 /O 编译器选项相同的字母。实用程序的可用字母是:

  • g -启用全局优化。
  • p -提高浮点一致性。
  • s 或 t -指定机器代码的短或快序列。
  • y -在程序堆栈上生成帧指针。

我应该使用哪些与 /O2 具有相同的含义?

0 投票
4 回答
427 浏览

c++ - 为什么编译器不能优化这两条语句?

即使我在 Visual C++ 中打开了完全优化,编译器是否有任何理由无法在 main 中优化以下 2 条语句?访问内存中的 int 变量有什么副作用吗?

0 投票
4 回答
3698 浏览

c++ - gcc 优化导致应用程序失败

在启用优化的情况下,我在使用 GCC for ARM 时遇到了一个非常奇怪的问题。在没有优化的情况下编译我的 C++ 应用程序会生成一个在运行时输出预期结果的可执行文件。一旦我打开优化 - 即 -O1 - 我的应用程序就无法产生预期的结果。我尝试了几天来发现问题,但我一无所知。我从我的代码中消除了任何未初始化的变量,我纠正了严格别名可能导致问题的地方,但我仍然没有得到正确的结果。

我正在为 ARM 使用 GCC 4.2.0(处理器是 ARM926ej-s)并在 Montavista Linux 发行版上运行该应用程序。

以下是我正在使用的标志:

只要我去掉 -O1 标志并重新编译/重新链接应用程序,我就会得到正确的输出结果。正如您从标志中看到的那样,我试图禁用任何优化,我认为它可能会导致问题,但仍然没有运气。

有没有人对我如何进一步解决这个问题有任何指示?

谢谢

0 投票
6 回答
2407 浏览

c++ - 如何强制编译器生成的类的复制构造函数*不*被编译器内联?

替代问题的标题是: 如何明确地让编译器为特定翻译单元中的编译器生成的构造函数生成代码?

我们面临的问题是,对于一个代码路径,如果一个对象的 copy-ctor 调用没有被内联,即如果这个构造函数是手动实现的,那么结果——经过彻底测量——性能会更好(大约 5%) 。(我们注意到这一点是因为在代码清理期间,删除了该类(17 个成员)的多余显式实现的复制 ctor。)

编辑:请注意,我们已经检查了生成的汇编代码,并确保内联和代码生成正在发生,正如我为两个不同的代码版本所描述的那样。

我们现在面临的选择是直接将手动 copy-ctor 代码放回原处(它与编译器生成的代码完全相同)或找到任何其他内联此类的 copy-ctor 的方法。

是否有任何方法(对于 Microsoft Visual C++)在特定翻译单元中显式实例化编译器生成的类函数,或者它们是否总是内联在使用它们的每个翻译单元中?(也欢迎对 gcc 或其他编译器发表评论,以更好地了解情况。)


由于前 2 个答案显示了一些误解:编译器生成的类函数只有在用户既没有声明也没有定义的情况下才由编译器本身生成。因此,不能对它们应用任何修饰符,因为源代码中不存在这些函数。

A有一个默认和复制 ctor、一个 dtor 和一个复制运算符。这些函数都不能通过一些 declspec 修改,因为它们不存在于代码中。

B现在有一个用户提供的副本 ctor 并且用户必须实现它。编译器不会为它生成代码。


怀疑者的更多背景:-) ...

此代码是使用 MS Visual C++ 编译的,但它是为嵌入式(类似)(实时)系统而链接的。性能是通过在这个系统上计时来衡量的,因此我认为计时的人会有一些不错的数字。

通过比较两个代码版本来执行测试,其中唯一的区别是这一类的内联与非内联复制ctor。内联代码的时间差了大约 5%。


进一步检查发现我有一个错误:编译器将为复杂的复制构造函数生成单独的函数。它将自行决定执行此操作,并且还取决于优化设置。所以在我们的例子中,编译器在我们的特定情况下做错了事情。从到目前为止的答案来看,我们似乎无法告诉编译器。:-(

0 投票
3 回答
11420 浏览

c++ - 编译器如何优化我们的代码?

当我回答另一个人的问题时,我遇到了这个问题。编译器如何优化代码?像 const, ... 这样的关键字有帮助吗?除了 volatiles 和 inline 函数以及如何自己优化代码之外!

0 投票
1 回答
294 浏览

compiler-construction - 在什么情况下乱序执行会产生更高效的代码

我试图了解内存屏障是如何工作的,为什么要使用它以及在什么情况下应该使用它。但是我不完全确定在什么情况下安排指令的顺序会更有效,谁能给我一个例子?

0 投票
3 回答
4177 浏览

c++ - 我的编译器在做什么?(优化memcpy)

我正在使用 VC++2010 中的以下设置编译一些代码: /O2 /Ob2 /Oi /Ot

但是我在理解生成的程序集的某些部分时遇到了一些麻烦,我在代码中提出了一些问题作为注释。

另外,现代cpus一般推荐什么预取距离?我可以在我自己的 cpu 上进行测试,但我希望有一些值可以在更广泛的 cpu 上运行良好。也许可以使用动态预取距离?

<--编辑:

我感到惊讶的另一件事是编译器不会以某种形式交错 movdqa 和 movntdq 指令?因为这些指令在某种意义上与我的理解是异步的。

这段代码在预取时也假设有 32 字节的缓存线,但是似乎高端 cpu 有 64 字节的缓存线,所以可能会删除 2 个预取。

-->

原始代码:

0 投票
2 回答
445 浏览

gcc - 展开 gcc 编译器优化

我有兴趣查看 gcc 实际优化代码的代码。我有办法吗?

我经历过其他一些类似的问题,我尝试过以下几件事,

  1. -Wa,ahl=filename.lst :- 这个选项真的很好,可以浏览代码和对应的机器码,但是我开启O3选项就不行了。
  2. 转储优化树:- 我确信 gcc 给了我大量的调试信息。但我不知道如何破译它。如果有人能指出任何可用的信息,我会很高兴。

还有其他更好的方法来找出 gcc 优化的代码部分吗?

谢谢,马杜尔