【问题标题】:g++ handling of copying a std::complexg++ 处理复制 std::complex
【发布时间】:2017-04-08 17:54:21
【问题描述】:

作为自学项目的一部分,我研究了 g++ 如何处理std::complex - 类型,并对这个简单的函数感到困惑:

#include <complex>  
std::complex<double> c;

void get(std::complex<double> &res){
    res=c;
}

g++-6.3 -O3(或-Os)为Linux64编译我得到了这个结果:

    movsd   c(%rip), %xmm0
    movsd   %xmm0, (%rdi)
    movsd   c+8(%rip), %xmm0
    movsd   %xmm0, 8(%rdi)
    ret

因此它将实部和虚部分别移动为 64 位浮点数。但是,我希望程序集使用两个 movups 而不是四个 movsd,即将实部和虚部作为 128 位包同时移动:

    movups  c(%rip), %xmm0
    movups  %xmm0, (%rdi)
    ret

这不仅在我的机器(Intel Broadwell)上是 movsd-version 的两倍,而且只需要 16 个字节,而 movsd-version 需要 36 个字节。

g++ 用movsd 创建程序集的原因是什么?

  1. 还有一个额外的编译器标志来触发movups 的使用,我应该在-O3 旁边使用它吗?
  2. 我不知道使用movups 有哪些缺点?
  3. g++ 在这里没有产生最优的组装?
  4. 还有别的吗?

更多上下文:我尝试比较两个可能的函数签名:

std::complex<double> get(){
    return c;
}

void get(std::complex<double> &res){
    res=c;
}

由于 SystemV ABI,第一个版本必须将实部和虚部放入不同的寄存器(xmm0xmm1)。但是对于第二个版本,可以尝试利用适用于 128 位的 SSE 操作的一些优势,但它不适用于我的 g++ 版本。


编辑:正如 kennytm 的回答所暗示的,g++ 似乎产生了非最佳程序集。它总是使用 4 movsd 将 std::complex 从一个内存位置复制到另一个内存位置,例如

void get(std::complex<double> *res){
    res[1]=res[0];
}

现在有一个bug-report 提交给 gcc-bugzilla..

【问题讨论】:

  • 我有 movsd c+8(%rip), %xmm1; movsd c(%rip), %xmm0 使用 gcc.godbolt.org
  • 有趣的是,godbolt.orgoutput 与您的略有不同。这也可能是您的解释:由于这两个值都在不同的寄存器中返回,因此使用 movups 是没有意义的。

标签: c++ gcc assembly


【解决方案1】:

3。 g++ 在这里不会产生最佳组装。

clangicc 都只使用一个 SSE 寄存器。可以在https://godbolt.org/g/55lPv0查看编译后的代码。

get(std::complex<double>&):
        movups    c(%rip), %xmm0
        movups    %xmm0, (%rdi)  
        ret

【讨论】:

    猜你喜欢
    • 2012-01-18
    • 1970-01-01
    • 2016-08-29
    • 2020-05-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-28
    相关资源
    最近更新 更多