C ++优化器:除法

问题描述

假设我有2条if语句:

if (frequency1_mhz > frequency2_hz * 1000) {// some code}

if (frequency1_mhz / 1000 > frequency2_hz ) {// some code}

我猜想这两个函数功能完全相同,但是我猜测带有乘法的第一个语句比除法更有效。

C ++编译器会对此进行优化吗?还是在设计代码时应该考虑的一件事

解决方法

是,不是。

  1. 代码不同:
  • 由于四舍五入,结果可能有所不同(例如frequency1_mhz=1001frequency2_hz=1
  • 第一个版本可能比第二个版本早溢出。例如frequency2_hz等于1000000000会使int溢出(并导致UB)
  1. 仍然可以使用乘法进行除法。

不确定时,只需查看生成的程序集即可。

Here's为两个版本生成的程序集。第二个更长,但仍然没有除法。

version1(int,int):
        imul    esi,esi,1000
        xor     eax,eax
        cmp     esi,edi
        setl    al
        ret
version2(int,int):
        movsx   rax,edi
        imul    rax,rax,274877907     ; look ma,no idiv!
        sar     edi,31
        sar     rax,38
        sub     eax,edi
        cmp     eax,esi
        setg    al
        movzx   eax,al
        ret
,

不,它们不是等效的状态参数,因为除法不是浮点数或整数乘法的精确逆。

  • 整数除法将正整数舍入
int f1=999;
int f2=0;

static_assert(f1>f2*1000);

static_assert(f1/1000==f2);
  • 倒数并不精确:
static_assert(10.0!=10*(1.0/10));
,

如果它们是使用-O3构建的浮动,则GCC会生成相同的程序集(无论好坏)

bool first(float frequency1_mhz,float frequency2_hz) {
    return frequency1_mhz > frequency2_hz * 1000;
}

bool second(float frequency1_mhz,float frequency2_hz) {
    return frequency1_mhz / 1000 > frequency2_hz;
}

The assembly

first(float,float):
        mulss   xmm1,DWORD PTR .LC0[rip]
        comiss  xmm0,xmm1
        seta    al
        ret
second(float,float):
        divss   xmm0,xmm1
        seta    al
        ret
.LC0:
        .long   1148846080