为什么 GCC 无法减少增加同一缓冲区两个位置的循环?

问题描述 投票:0回答:1

这是一个有界循环,它递增同一缓冲区的两个位置。

unsigned int getid();
void foo(unsigned int *counter, unsigned int n) {
        unsigned int A = getid();
        unsigned int B = getid();
        for (unsigned int i = 0; i < n; i++) {
            ++counter[A];
            ++counter[B];
        }
}

根据编译器资源管理器(https://godbolt.org/z/b1sjf5669)的结果,即使在-O3优化级别,程序仍然存在涉及

add 1
命令的循环。

相反,如果去掉

++counter[B]
,编译器可以减少循环,将程序优化为
counter[A] += n
。 (https://godbolt.org/z/4YoPcz5rT

为什么编译器是保守的,即在这种情况下不将代码转换为

counter[A] += n, counter[B] += n

我知道一些别名问题会导致循环减少失败。然而,这里只有一个缓冲区,即使

A=B
,优化代码也不会改变结果。

c++ assembly gcc optimization compiler-construction
1个回答
0
投票

正如评论中已经说过的,增量实际上是 3 个操作数:加载、添加、存储。

保守地说,不允许编译器重新排序

MayAlias
内存操作。 为了做你想做的事,编译器必须证明计算结果不依赖于内存别名,这在一般情况下是不平凡的。

我认为这个优化的范围太小,实施起来不合理。

© www.soinside.com 2019 - 2024. All rights reserved.