如何让GCC优化长XOR链

whhtz7ly  于 2023-10-19  发布在  其他
关注(0)|答案(3)|浏览(135)

我有一个循环像这样:

uint32_t result = 0;

for ( int i = 0; i < CONSTANT; ++i )
{
    result ^= expr;
}
return result;

总的来说,GCC在这段代码上做得很好。它完全展开循环并为expr生成最佳代码。但是,它执行result XOR CONSTANT次。它可以累积部分结果并分层地将它们异或在一起。
我怀疑如果我用宏手动展开它,我可以手动完成它(CONSTANT并不大),但我想知道为什么它看不到这一点,或者如果我做了一些阻止它由于一些《双城之战》 C++ 规则。

xa9qqrwz

xa9qqrwz1#

在这里积累部分结果可能没有好处。如果你使用分治策略(XOR偶数与奇数减半大小,然后重复,每次将操作数减半),你仍然会完成O(CONSTANT)的工作(一半的工作加上四分之一的工作加上八分之一的工作,等等,最终执行CONSTANT - 1操作)。
在块中累积部分结果的行为相同。基本上,你必须有CONSTANT - 1 XOR操作。由于这些是固定宽度的寄存器,而不是增长任意精度的整数,因此每个XOR的工作是相同的。除非将expr工作并行化,否则您不太可能从更复杂的方法中获得任何好处。

xbp102n0

xbp102n02#

对于你的循环,要么expr不依赖于i,在这种情况下gcc应该完全优化掉循环,要么gcc可以 * 仍然 * 优化掉它(因为循环边界是恒定的,整个循环可以预先计算)。
好像是fails in the latter case,除非你optimize for-march=haswell。这看起来很奇怪,但我确实见过这种behavior before
在任何情况下,您提到expr编译为两条指令。为xor添加3条指令,循环增量和测试指令,您已经为这个循环添加了5条指令,这甚至超过了高端x86 CPU的退休率,因此在这里寻找额外的指令级并行性没有任何好处(除非您正在编译一个具有更高宽度的非x86 arch?).
1..
2.我们只能猜测,因为你确实紧紧地守护着expr的秘密。

3duebb1j

3duebb1j3#

在严格的XOR计算中,从技术上讲,XOR计算中不会有超过两个值,因为它在逻辑上没有意义,并且只有当我们在像var1 ^ var2 ^ var3这样的链中超过两个XOR值时,才会告诉我们所有数字的组合奇偶性,因此从技术上讲,通过使用两个以上的值,你应该只能告诉它的奇偶性,无论结果是偶数还是奇数。
然而,在大多数编程语言中,编译器会自动创建一系列级联的XOR操作,每次只处理两个值,然后将该结果与下一个值进行XOR,直到处理完所有值,所以实际上不可能有真正的批量XOR链或列表作为表达式,尽管我们可以以这种方式编写它们,编译器处理细节。

相关问题