内联汇编中的 sse 约束不起作用

Posted

技术标签:

【中文标题】内联汇编中的 sse 约束不起作用【英文标题】:sse constraint in inline assembly not working 【发布时间】:2013-03-13 13:08:31 【问题描述】:

我在编译下面的代码 sn-p 时遇到了一些问题。

#include <iostream>
#include <cstdint>

using namespace std;

union mxcsr 
    uint32_t v;
    struct 
        uint32_t  ie : 1;
        uint32_t  de : 1;
        uint32_t  ze : 1;
        uint32_t  oe : 1;
        uint32_t  ue : 1;
        uint32_t  pe : 1;
        uint32_t daz : 1;
        uint32_t  im : 1;
        uint32_t  dm : 1;
        uint32_t  zm : 1;
        uint32_t  om : 1;
        uint32_t  um : 1;
        uint32_t  pm : 1;
        uint32_t  rn : 1;
        uint32_t  rp : 1;
        uint32_t  fz : 1;
        uint32_t rs0 : 15;
    ;
;

std::ostream& operator<<(std::ostream& ostr, mxcsr &m)
    ostr << std::hex << std::showbase;
    ostr << "mxcsr=" << m.v;
    ostr << std::dec << std::noshowbase;
    ostr << " [ie=" << m.ie << ",de=" << m.de
         << ",ze=" << m.ze << ",oe=" << m.oe << ",ue=" << m.ue
         << ",pe=" << m.pe << ",daz=" << m.daz << ",im=" << m.im
         << ",dm=" << m.dm << ",zm=" << m.zm << ",om=" << m.om
         << ",um=" << m.um << ",pm=" << m.pm << ",r-=" << m.rn
         << ",r+=" << m.rp << ",fz=" << m.fz << "] ";
    return ostr;


typedef union __attribute__((aligned(16))) vec_t 
    double       f64[2];
    float        f32[4];
    uint64_t     u64[2];
    uint32_t     u32[4];
    uint16_t     u16[8];
    uint8_t      u8[16];
    int64_t      i64[2];
    int32_t      i32[4];
    int16_t      i16[8];
    int8_t       i8[16];
  vec_t;


float add_vec_32f(float ra, float rb, mxcsr &f)
    vec_t va, vb;
    va.f32[0] = ra; vb.f32[0] = rb;
    asm("addps %[vb], %[va];"
        "stmxcsr %[f];"
        : [va] "+x" (va), [f] "=m" (f)
        : [vb] "xm" (vb)
        :
    );
    return va.f32[0];


int main()

    mxcsr val;

    float b = add_vec_32f(3.4, 5.6, val);

    std::cout << "b=" << b << " val=" << val << std::endl;
    return 0;

编译器报此错误“'asm' 中的不可能约束”。为了验证这一点,我浏览了 ADDPS 指令的描述。它说的是这样的:-

添加 xmm1, xmm2/m128 将压缩的单精度浮点值从 xmm2/m128 添加到 xmm1。

所以,源可以是内存地址或 xmm 寄存器,但目标必须是 xmm 寄存器。我想我的约束有点同意这一点。 谁能指出我这里可能存在的问题?

谢谢。

【问题讨论】:

“'asm' 中的不可能约束”听起来不像是汇编指令格式错误,而是您的约束格式错误。 请参阅gcc.gnu.org/onlinedocs/gcc/Vector-Extensions.html,了解 gcc 如何声明矢量类型(或包括 并使用 __m128d 或其他类型之一)。 【参考方案1】:

所以我不确定为什么使用union 不起作用,但使用 SIMD 向量指令确实有效,尽管您需要在union 中添加一个。我能够让它像这样工作:

typedef double xmmd __attribute__ ((vector_size (16)));

typedef union __attribute__((aligned(16))) 
vec_t 
    xmmd         xmm ;
    double       f64[2];
    float        f32[4];    
    uint64_t     u64[2];
    uint32_t     u32[4];
    uint16_t     u16[8];
    uint8_t      u8[16];
    int64_t      i64[2];
    int32_t      i32[4];
    int16_t      i16[8];
    int8_t       i8[16];
  vec_t;

float add_vec_32f(float ra, float rb, mxcsr &f)
    vec_t va, vb;
    va.f32[0] = ra; vb.f32[0] = rb;


     asm("addps %[v2], %[v1];"
        "stmxcsr %[f];"
        : [v1] "+x" (va.xmm), [f] "=m" (f)
        : [v2] "xm" (vb.xmm)
        :
    );

    return va.f32[0];

【讨论】:

谢谢,这样就可以了。看起来 gcc 不允许将联合声明为向量类型,所以这是最明智的做法。 @vikasC 是的,内联汇编通常很难完全理解这篇文章帮助我更好地理解locklessinc.com/articles/gcc_asm 如果你能接受我的回答,我将不胜感激

以上是关于内联汇编中的 sse 约束不起作用的主要内容,如果未能解决你的问题,请参考以下文章

在 cpp 文件中使用内联命名空间中的类型在 MSVS 中不起作用

内联汇编约束修饰符 = 和 +

Spring boot:SSE 服务器发送的事件不起作用

带引号的Thymeleaf内联javascript不起作用

UITableViewCell 中的约束不起作用

MySQL 中的 CHECK 约束不起作用