【问题标题】:GCC changes less than to less than or equal toGCC 变化小于等于小于等于
【发布时间】:2013-03-30 11:28:27
【问题描述】:

我有以下简单的程序,我用它来刷新我对 GDB 的记忆(我已经很多年没有接触过)。

#include <stdio.h>

int main()
{
  int i;

  for (i = 0; i < 10; i++)
  {
    printf("Hello World\n");
  }

  return 0;
}

我用gcc -g for-test.c -o for-test 编译这个。根据手册页,我不希望使用任何优化,因为我没有指定任何优化。

当我将它加载到 GDB 并运行 disassemble main 时,i &lt; 10 比较会生成以下内容:

cmp    DWORD PTR [rbp-0x4],0x9
jle    0x4004fe <main+10>

这似乎有效地改变了i &lt; 10i &lt;= 9 的比较。鉴于这些是整数比较,应该没有区别,但我想知道 GCC 是否有任何理由输出这个程序集,而不是与 10 比较并在小于 (JL) 时跳转?

编辑:这是在具有 64 位处理器的机器上,运行带有 GCC 4.6.3 和 GDB 7.4-2012.04 的 Ubuntu。

【问题讨论】:

  • 两种方式 100% 相同(相同的行为、相同的代码大小、每个 CPU 的相同速度)。我不了解 GCC 的内部结构,所以我猜不出它为什么这样做。更有趣的是,我认为您没有启用优化(否则它将使用寄存器而不是 i 的局部变量)。
  • 也许这就是标准化比较的方式..
  • 如果两者有任何不同的可能性,如果没有优化它就不会这样做。例如if (a + 1 &gt; 1) 将通过优化简化为 if (a &gt; 0),但它可能不安全,因此不会这样做。

标签: c gcc assembly gdb


【解决方案1】:

执行速度应该没有差异。我认为 gcc 通常会为此类比较发出 jle,并为生成的程序集保持一致性。

【讨论】:

  • 似乎确实如此。有趣的是,我在 clang 中尝试了相同的代码,结果恰恰相反——它将“如果小于则继续循环”转换为“如果大于或等于则中断循环”。我不确定为什么这两个编译器选择了不同的路径,或者一个本质上是否比另一个更有效。
【解决方案2】:

只要可观察到的行为相同,编译器就可以执行优化。这称为 As-If rule。由于这两种情况的可观察行为是相同的,因此允许编译器在两者中的任何一种中生成汇编代码。即使您没有启用任何优化也是如此。

【讨论】:

  • +1。它甚至可以展开循环(它实际上是用-O3 完成的)。而且,也许,甚至可以打印一个包含 10 个原始副本的字符串。
  • 不过,这并不是真正的优化,除非与 9 比较,如果小于或等于则跳转比与 10 比较更快(或内存效率更高,或其他一些措施)比与 10 比较,如果小于则跳转比。
【解决方案3】:

这不是有效的优化,只是另一种写法。使用 -O 标志编译会产生更复杂的优化。

【讨论】:

    猜你喜欢
    • 2011-01-25
    • 2012-09-11
    • 1970-01-01
    • 2013-09-02
    • 1970-01-01
    • 1970-01-01
    • 2017-06-16
    • 2017-12-02
    • 1970-01-01
    相关资源
    最近更新 更多