为什么这个三元组比等效的 if 生成更多的 Assembly?

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

所以论坛上有人问为什么要使用这个 C 函数(我添加了

const
restrict
,以防万一):

void foo(int *const restrict dest, const int *const restrict source) {
    *dest = (*source != -1) ? *source : *dest;
}

使用最新的 gcc 和 clang 编译器生成此程序集,并使用

-Os
优化 godbolt 上的大小 :

foo: mov eax, dword ptr [rsi] cmp eax, -1 jne .LBB0_2 mov eax, dword ptr [rdi] .LBB0_2: mov dword ptr [rdi], eax ret
这个看似相同的函数却在 godbolt 上少生成一条指令

void foo(int *const restrict dest, const int *const restrict source) { if (*source != -1) { *dest = *source; } }

foo:
        mov     eax, dword ptr [rsi]
        cmp     eax, -1
        je      .LBB0_2
        mov     dword ptr [rdi], eax
.LBB0_2:
        ret
也许我遗漏了一些东西,或者也许我低估了编译器优化它的难度。我希望编译器能够检测到 
*dest = *dest

不会有任何副作用,因为我没有将其标记为

volatile
,因此允许将三元优化为 if 语句版本。我在 Stack Overflow 上找到了类似问题的其他答案,这些答案通常归结为 GCC 在一种情况下比 Clang 有优势,反之亦然,但奇怪的是,这两种情况对我来说似乎都没有优化这种情况。
    

c assembly x86-64 compiler-optimization conditional-operator
1个回答
0
投票

void foo(int *const restrict dest, const int *const restrict source) { *dest = (*source != -1) ? *source : *dest; }

代码片段2:

void foo(int *const restrict dest, const int *const restrict source) { if (*source != -1) { *dest = *source; } }

代码片段 1 和代码片段 2 实际上在逻辑上并不匹配,这就是汇编代码不同的原因。

    代码片段 1 中提出的是,
  • ' 如果

    *source != -1

    那么

    *dest = *source;
    否则

    *dest = *dest;

    '

    
    

  • 代码片段2中提出的是,
  • ' 如果

    *source != -1

    那么

    *dest = *source;
    '
    
    

  • 为了匹配逻辑,代码片段 2 可以更改为以下内容:

void foo(int *const restrict dest, const int *const restrict source) { if (*source != -1) { *dest = *source; } else{ *dest = *dest; } }

在 if-else 条件上使用三元:
https://www.tutorialspoint.com/ternary-operator-vs-if-else-in-c-cplusplus

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