如何让GCC优化长XOR链

How to get GCC to optimize long XOR chain

本文关键字:XOR 优化 GCC      更新时间:2023-10-16

我有一个类似的循环

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

总的来说,GCC在这个代码方面做得很好。它完全展开循环并为expr生成最佳代码。然而,它执行result异或CONSTANT次。它可以是累积部分结果,并按层次将它们异或在一起。

我怀疑,如果我用宏手动展开它,我可以手动完成(CONSTANT不是很大),但我想知道为什么它看不到这一点,或者我是否正在做一些由于某些晦涩的C++语言规则而阻止它的事情。

在这里积累部分结果可能没有任何好处。如果你使用一种分而治之的策略(XOR与赔率持平,将大小减半,然后重复,每次将操作数减半),你最终仍然会做O(CONSTANT)的功(一半的功加四分之一的功加八分之一的工,等等,最终执行CONSTANT - 1运算)。

将部分结果累积为块的行为相同。从根本上讲,您必须具有CONSTANT - 1XOR操作。由于这些都是固定宽度的寄存器,不会增长任意精度的整数,所以每个XOR的工作都是相同的。除非并行化expr工作,否则您不太可能从更复杂的方法中获得任何收益。

对于您的循环,要么expr不依赖于i,在这种情况下gcc应该完全优化掉循环1,要么它确实这样做,在这种情形下gcc仍然可以优化掉它(因为循环边界是恒定的,所以可以预先计算整个循环)。

不过,在后一种情况下,它似乎失败了,除非您为-march=haswell进行了优化。这看起来真的很奇怪,但我以前确实见过这种行为。

在任何情况下2,您提到expr编译为两条指令。为xor、循环增量和测试指令添加3条指令,您已经为该循环添加了5条指令,这甚至超过了高端x86 CPU的退役率,因此在这里寻求额外的指令级并行性没有任何好处(除非您正在编译到宽度更高的非x86架构?)。


1。。。无论如何,在-O3,它通常是这样做的。

2我们只能在这里猜测,因为你真的在严密地保守expr的秘密。