为什么大多数编译器不能进行模运算组合优化?

3
unsigned long f1(unsigned long num) {
    if (num % 5L == 0 && num % 3L == 0) { return 1000; }
    return 0;
}

unsigned long f2(unsigned long num) {
    if (num % 15L == 0) { return 1000; }
    return 0;
}

编译器结果:

f1(unsigned long):
        movabs  rdx, -3689348814741910323
        mov     rax, rdi
        mov     rcx, rdi
        mul     rdx
        mov     rax, rdx
        and     rdx, -4
        shr     rax, 2
        add     rdx, rax
        mov     rax, rdi
        sub     rcx, rdx
        movabs  rdx, -6148914691236517205
        mul     rdx
        mov     rax, rdx
        and     rdx, -2
        shr     rax
        add     rdx, rax
        sub     rdi, rdx
        or      rdi, rcx
        cmp     rdi, 1
        sbb     rax, rax
        and     eax, 1000
        ret
f2(unsigned long):
        movabs  rax, -1229782938247303441
        imul    rdi, rax
        movabs  rax, 1229782938247303441
        cmp     rax, rdi
        sbb     rax, rax
        not     rax
        and     eax, 1000
        ret

尝试了GCC、MSVC、clang、Java C2和C# JIT。
我认为num % 5 == 0 && num % 3 == 0可以优化成num % 15 == 0,但大多数编译器都不会这么做。
有没有情况会导致这些比较不同或只是没有人考虑过?

作者:icebp,godbolt链接在此


1
你可以发布Godbolt链接:https://godbolt.org/z/Po1Tsq - icebp
看起来对我来说就像是FizzBuzz :-) - Steve Friedl
2
也许这只是一种相当罕见的模式,因此编译器无法将其识别为可优化的。 - Eugene Sh.
3
如果我们把除数改成 4L8L,那么 GCC 会合并测试。这证明了进行这种优化没有语义障碍——不涉及顺序、可观察或未定义行为的问题。因此,正如 Eugene Sh. 提出的那样,原因很可能只是该模式不常见,因此没有将其添加到编译器中的需求出现。 - Eric Postpischil
2
@EricPostpischil 抱歉,重新阅读我的评论,它看起来很粗鲁,这不是我的目的。重点是,我们每天都会有人问为什么编译器不执行某个优化,而答案几乎总是因为没有人实现它。如果人们关心这种优化并且无法自己实现它,他们可以提交错误/增强报告。如果他们真的想要它,他们可以付钱请人来实现它。 - Marc Glisse
显示剩余6条评论
1个回答

0

这当然不是一份全面的答案,但请记住C语言中的布尔运算符使用短路求值。这意味着对于 if (A && B),如果A为假,则B永远不会被评估,因为整个条件永远不可能为真。同样地,对于if(A || B),如果A为真,则B永远不会被评估,因为整个条件永远不可能为假。

在你的特定情况下,这意味着如果num % 5 == 0为假,则它永远不需要评估num % 3 == 0,因为整个条件永远不可能为真。


如果我将 && 改为 &,godbolt 会显示相同的编译结果:https://godbolt.org/z/chss5n - Cyl18
8
这根本不是一个理由。所谓的“短路规则”在这种情况下并不会阻碍优化,因为代码在右操作数被评估和丢弃或者永远不被评估的情况下具有相同的语义。 - Eric Postpischil
啊好的,是的,我不确定这是否相关。但我觉得指出这一点是值得的。也许最好作为评论,但我还没有足够的声望。 - Dillon
1
如果%3%5%15便宜,那么这将是一个原因。但看起来它们不是。 - Eugene Sh.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接