C 为什么大多数编译器可以';做模数计算组合优化?

C 为什么大多数编译器可以';做模数计算组合优化?,c,gcc,compiler-construction,compiler-optimization,C,Gcc,Compiler Construction,Compiler Optimization,编译器结果: 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; } 尝试过GCC、msvc、clang、Java C2、C

编译器结果:

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;
}
尝试过GCC、msvc、clang、Java C2、C#JIT
我认为
num%5==0&&num%3==0
可以优化为
num%15==0
,但大多数编译器不会这样做。
是否有任何情况会使这些比较不同,或者只是没有人去想它


这肯定不是一个全面的答案,但请记住,C语言中的布尔运算符使用。这意味着对于
如果(A和&B)
,如果
A
为false,则永远不会计算
B
,因为整个条件永远不会为true。类似地,对于
如果(A | | B)
,如果
A
为真,则永远不会计算
B
,因为整个条件永远不会为假


在您的特定情况下,这意味着如果
num%5==0
为false,则它永远不必计算
num%3==0
,因为整个条件永远不可能为true。

不要发布代码图像。以文本形式发布。您可以发布一个指向godbolt的链接:可能这只是一个非常不常见的模式,因此编译器无法将其识别为可优化模式。如果我们将除数更改为
4L
8L
,则。这证明优化不存在语义障碍,也不存在排序、可观察或未定义行为的问题。因此,正如Eugene Sh.所说,原因很可能只是该模式不常见,因此希望将其添加到编译器中,而不是出现这种情况。@EricPostphil抱歉,重读我的评论,它看起来很粗鲁,这不是我的目标。关键是,我们每天都有问题问编译器为什么不执行优化,答案几乎总是他们不执行,因为没有人实现它。如果人们关心这个优化,并且不能自己实现它,他们可以提交一个bug/增强报告。如果他们真的想要它,他们可以花钱让人来实现它。如果我将&&to&,godbolt会显示相同的编译结果:这根本不是原因。在这种情况下,所谓的短路规则并不是优化的障碍,因为代码具有相同的语义,无论正确的操作数是被计算并丢弃还是从未计算过。啊,好吧,是的,我不确定这是否相关。但我认为这是值得指出的。也许作为一个评论会更好,但我在这方面还没有足够的声誉。如果
%3
%5
%15
便宜,这将是一个原因。但看起来他们不是
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