GCC/Clang 未优化静态全局变量

发布于 2025-01-19 07:44:01 字数 1174 浏览 1 评论 0原文

GCC 似乎无法跟踪和优化在 C/C++ 中读/写全局变量的程序,即使它们是静态的,这应该允许它保证其他编译单元不会改变变量。

编译代码时

static int test = 0;

int abc() {
  test++;
  if (test > 100) \
    return 123;
  --test;
  return 1;
}

int main() {
  return abc();
}

使用 GCC 版本使用标志 -Os(以生成更短且更具可读性的程序集)和 -fwhole-program-flto 11.2 我希望将其优化为 return 1 或以下程序集:

main:
        mov     eax, 1
        ret

这实际上是如果 test 是局部变量时生成的结果。但是,会生成以下内容:

main:
        mov     eax, DWORD PTR test[rip]
        mov     r8d, 1
        inc     eax
        cmp     eax, 100
        jle     .L1
        mov     DWORD PTR test[rip], eax
        mov     r8d, 123
.L1:
        mov     eax, r8d
        ret

示例: https://godbolt.org/z/xzrPjanjd

这GGC 和 Clang 以及我尝试过的所有其他编译器都会发生这种情况。我希望现代编译器能够跟踪程序的流程并删除检查。是否有一些我没有考虑到的东西可能会允许程序外部的东西影响变量,或者这只是尚未在任何编译器中实现?

相关:为什么 gcc 不优化全局变量?那里给出的答案提到了外部函数和线程,两者都不适用于此

GCC does not seem to be able to trace and optimize programs that read/write global variables in C/C++, even if they're static, which should allow it to guarantee that other compilation units won't change the variable.

When compiling the code

static int test = 0;

int abc() {
  test++;
  if (test > 100) \
    return 123;
  --test;
  return 1;
}

int main() {
  return abc();
}

with the flags -Os (to produce shorter and more readable assembly) and -fwhole-program or -flto using GCC version 11.2 I would expect this to be optimized to return 1, or the following assembly:

main:
        mov     eax, 1
        ret

This is in fact what is produced if test is a local variable. However, the following is produced instead:

main:
        mov     eax, DWORD PTR test[rip]
        mov     r8d, 1
        inc     eax
        cmp     eax, 100
        jle     .L1
        mov     DWORD PTR test[rip], eax
        mov     r8d, 123
.L1:
        mov     eax, r8d
        ret

Example: https://godbolt.org/z/xzrPjanjd

This happens with both GGC and Clang, and every other compiler I tried. I would expect modern compilers to be able to trace the flow of the program and remove the check. Is there something I'm not considering that may allow something external to the program to affect the variable, or is this just not implemented in any compilers yet?

Related: Why gcc isn't optimizing the global variable? but the answer given there mentions external functions and threads, neither of which apply here

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

ヅ她的身影、若隐若现 2025-01-26 07:44:01

我认为您对大多数编译器的要求有点过高。虽然编译器可能被允许根据 as-if 规则< /a> 在标准中,它显然没有在许多编译器中实现,就像您为 GCC 和 Clang 所说的那样。

我能想到的两个原因是:

  • 在您的示例中,显然链接时间优化决定内联 abc 函数,但没有优化掉 test 变量。为此,需要对 test 变量的读/写语义进行分析。以通用方式做到这一点非常复杂。在您提供的简单情况下可能是可能的,但任何更复杂的情况都会非常困难。

  • 此类优化的用例很少见。全局变量最常用于表示某些共享的全局状态。我没有任何意义去优化它。与大多数程序的好处相比,在编译器/链接器中实现此类功能的工作量会很大。

添加
显然,如果您只读访问该变量,GCC 会优化该变量。如果编译以下内容:

static int test = 0;

int abc() {
  int test_ = test;
  test_++;
  if (test_ > 100) \
    return 123;
  --test_;
  return 1;
}

int main() {
  return abc();
}

将变量读入局部变量一次并且从不写入它,它会被优化为:(

main:
    mov     eax, 1
    ret

请参阅 此处进行演示
然而,使用这样的局部变量会破坏全局变量的全部意义。如果你从不写它,你不妨定义一个常量。

I think you are asking a little bit too much for most of the compilers. While the compiler is probably allowed to optimize the static variable away according to the as-if rule in the standard, it is apparently not implemented in many compilers like you stated for GCC and Clang.

Two reasons I could think of are:

  • In your example obviously the link time optimization decided to inline the abc function, but did not optimize away the test variable. For that, an analysis of the read/write semantics of the test variable would be needed. This is very complex to do in a generic way. It might be possible in the simple case that you provided, but anything more complex would be really difficult.

  • The use case of such optimizations is rare. Global variables are most often used to represent some shared global state. I makes no sense to optimize that away. The effort for implementing such a feature in a compiler/linker would be large compared to the benefit for most programs.

Addition
Apparently GCC optimizes away the variable if you read-only access it. If you compile the following:

static int test = 0;

int abc() {
  int test_ = test;
  test_++;
  if (test_ > 100) \
    return 123;
  --test_;
  return 1;
}

int main() {
  return abc();
}

Where you read the variable once into a local variable and never write to it, it gets optimized away to:

main:
    mov     eax, 1
    ret

(See here for a demo)
However using such a local variable would defeat the whole point of having a global variable. If you never write to it, you might as well define a constant.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文