常见的编译器知道这些代码版本是否也这样做并使用这个事实进行优化?

时间:2014-12-01 13:30:26

标签: c++ compiler-optimization

请考虑以下代码段:

class MyClass1{
public:
  double value;
  MyClass1 &operator*=(const MyClass1 &right){
    value *= right.value;
    return *this;
  }
  friend MyClass1 operator*(const MyClass1 &left, const MyClass1 &right){
    auto result = left;
    result *= right;
    return result;
  }
};

class MyClass2{
public:
  double value;
  MyClass2(double v) : value(v){}
  MyClass2(){}
  friend MyClass2 operator*(const MyClass2 &left, const MyClass2 &right){
    return MyClass2 (left.value * right.value);
  }
};

我感兴趣的是:常见的编译器知道,运算符MyClass1 :: operator *和MyClass2 :: operator *给出了相同的结果。如果设置说,有人希望“s”具有高度优化的可执行文件,他们还会制作相同的可执行文件吗?原则上他们也会这样做。

我读了它的“未经优化的”汇编代码(由Visual C ++制作),它们看起来不同。但性能优化的汇编代码非常庞大,复杂且(对我而言)难以理解。

在非优化版本中,第二个实现速度几乎是第一个实现速度的三倍。

1 个答案:

答案 0 :(得分:2)

您的代码中存在更大的问题,但这是一个很好的在线服务,用于检查生成的程序集:

enter image description here

我会说在你知道如何使代码正确之前不要打扰优化是一个好主意。也就是说,如果一个不错的在线工具可以帮助你让烦恼得到休息,那就更好了!

演示源代码

喜欢aboe的截图是根据您的问题改编的。免责声明:它是固定的未定义行为(至少由于单位化值):

struct MyClass1{
  double value;
  MyClass1 &operator*=(MyClass1 const &right){
    value *= right.value;
    return *this;
  }
  friend MyClass1 operator*(MyClass1 const &left, MyClass1 const &right){
    auto result = left;
    result *= right;
    return result;
  }
};

class MyClass2{
public:
  double value;
  MyClass2(double v = 0.0) : value(v){}
  friend MyClass2 operator*(MyClass2 const &left, MyClass2 const &right){
    return left.value * right.value;
  }
};

template <typename T> double test() {
    T a,b;
    volatile T c = a * b;
    return c.value;
}

int main()
{
    return test<MyClass1>() + test<MyClass2>();
}

使用clang 3.4 -O3 -march = corei7-avx在我的VM上进行此演示的相应程序集是:

    .file   "test.cpp"
    .text
    .globl  main
    .align  16, 0x90
    .type   main,@function
main:                                   # @main
    .cfi_startproc
# BB#0:
    vmulsd  %xmm0, %xmm0, %xmm0
    vmovsd  %xmm0, -8(%rsp)
    vmovsd  -8(%rsp), %xmm0
    movq    $0, -8(%rsp)
    vaddsd  -8(%rsp), %xmm0, %xmm0
    vcvttsd2si  %xmm0, %eax
    ret
.Ltmp0:
    .size   main, .Ltmp0-main
    .cfi_endproc


    .ident  "Ubuntu clang version 3.4-1ubuntu3 (tags/RELEASE_34/final) (based on LLVM 3.4)"
    .section    ".note.GNU-stack","",@progbits