SSE2指令--使用SSE2的整型内存操作和初始化:设置(Set)

本文详细介绍了SSE2指令集中的关键指令,如_mm_set_epi32与_mm_setr_epi32等,这些指令用于设置不同长度的数据到__m128i变量,并通过实例对比了正序与反序设置的区别。

       SSE2指令使用下面三种数据类型: __m128__m128i, 和 __m128d ,但是安腾处理器家族( Itanium Processor Family,IPF)处理器并不支持这三种数据类型;

      x64的处理器不支持任何使用 __m64 数据类型的SSE2指令。

     所有的SSE2指令的声明都在emmintrin.h头文件中可以找得到。

    1.__m128i _mm_set_epi64 ( __m64 q1, __m64 q0);

     指令名: __m128i _mm_set_epi64 (__m64 q1, __m64 q0);

         说明:使用两个__m64(64bits)变量来设置__m128i变量

     返回值:如果返回值__m128i,分为r0,r1,返回值规则如下:                   

              r0 := q0
          r1 := q1
 2. __m128i _mm_set_epi32(int i3, int i2,int i1, int i0);

     指令名:__m128i _mm_set_epi32(int i3, int i2,int i1, int i0);

      说明:使用4个int(32bits)变量来设置__m128i变量

     返回值:如果返回值__m128i,分为r0,r1,r2,r3返回值规则如下:                   

              r0 := i0         
          r1 := i1
          r2 := i2
          r3 := i3
 3.__m128i _mm_set_epi16(short w7,short w6,short w5,short w4,short w3,
                         short w2,short w1, short w0);
     指令名: __m128i _mm_set_epi16(short w7,short w6,short w5,short w4,
 short w3,short w2,short w1, short w0);         
  说明:使用8个short(16bits)变量来设置__m128i变量
     返回值:如果返回值__m128i,分为r0,r1,....,r7返回值规则如下:                   
                  r0 := w0         
           r1 := w1
             ....
           r7 := w7
 4. __m128i _mm_set_epi8(char b15,char b14,char b13,char b12,char b11,char b10,
                         char b9,char b8, char b7,char b6,char b5,char b4,
                         char b3,char b2,char b1,char b0);
     指令名:__m128i _mm_set_epi8(char b15,char b14,char b13,char b12,char b11,
 char b10,char b9,char b8,char b7,char b6,
                                char b5,char b4,char b3,char b2,char b1,char b0);
         
 说明:使用16个char(8bits)变量来设置__m128i变量
     返回值:如果返回值__m128i,分为r0,r1,....,r15返回值规则如下:                   
                  r0 := b0         
            r1 := b1
              ....
            r7 := b15
 5. __m128i _mm_set1_epi64 ( __m64 q1, __m64 q);
     指令名: __m128i _mm_set1_epi64 ( __m64 q);
       说明:使用1个__m64(64bits)变量来设置__m128i变量的高低62位值
     返回值:如果返回值__m128i,分为r0,r1,返回值规则如下:                   
                  r0 := q
            r1 := q
 6. __m128i _mm_set1_epi32(int i);
     与上面5类似,这个指令是使用1个i,来设置__m128i,将__m128i看做4个32位的部分,则每个部分都被赋为i;
 7. __m128i _mm_set1_epi16(short w);
 与上面5类似,这个指令是使用1个w,来设置__m128i,将__m128i看做8个16位的部分,则每个部分都被赋为w
 8. __m128i _mm_set1_epi8(char b);
     与上面5类似,这个指令是使用1个b,来设置__m128i,将__m128i看做16个8位的部分,则每个部分都被赋为b;
 9. __m128i _mm_setr_epi64 ( __m64 q1, __m64 q0);
     指令名: __m128i _mm_setr_epi64 ( __m64 q0, __m64 q1);
      说明:使用两个__m64(64bits)变量来反序设置__m128i变量
     返回值:如果返回值__m128i,分为r0,r1,返回值规则如下:                   
              r0 := q0
          r1 := q1
     大家要注意这个和1的差别,在参数中,指令9和1的参数顺序正好相反;
10. __m128i _mm_setr_epi32(int i0, int i1,int i2, int i3);
     这个同2相比,也是反序来设置__m128i数值;
11. __m128i _mm_setr_epi16(short w7,short w6,short w5,short w4,short w3,
 short w2,short w1, short w0);
      这个同3相比,也是反序来设置__m128i数值;
12. __m128i _mm_setr_epi8(char b15,char b14,char b13,char b12,char b11,
 char b10,char b9,char b8, char b7,char b6,char b5,
                          char b4,char b3,char b2,char b1,char b0);
    这个同4相比,也是反序来设置__m128i数值;
13. __m128i _mm_setzero_si128 ();
    指令名:__m128i _mm_setzero_si128 ();
      说明:__m128i 型数值设置为0
    返回值:如果__m128i 型看做一个整体的话,则有
           r0=0x0;
下面是我使用_mm_set_epi32_mm_setr_epi32来做设置时的比较:
    源码为:
         __declspec(align(16)) __m128i xx1=_mm_set_epi32(0x01020304,0x05060708,0x090a0b0c,0x0d0e0f00);
        __declspec(align(16)) __m128i xx2=_mm_setr_epi32(0x01020304,0x05060708,0x090a0b0c,0x0d0e0f00);

      图一:_mm_set_epi32,可以观察返回值的内部结构(图中标号1处)和在内存中的排列结构(图中标号2处)

              

图一:_mm_setr_epi32,可以观察返回值的内部结构(图中标号1处)和在内存中的排列结构(图中标号2处)

      通过上面两张图的对比,我们就可以了解这对应的两个Set的区别了;
<think>好的,我现在要解决的问题是用户遇到的编译错误:error: assigning to '__m128i' (vector of 2 'long long' values) from incompatible type 'int'。用户希望通过调整编译选项来解决这个问题,但不确定具体该怎么做。 首先,我需要理解这个错误的根本原因。根据错误信息,用户在尝试将一个int类型的值赋值给__m128i类型的变量。__m128i是SSE指令集中的一个数据类型,通常用于处理128位的向量数据,比如包含两个long long元素的向量。显然,直接将int赋值给这种向量类型是不允许的,因为类型不匹配。 接下来,我需要考虑可能的原因。可能的情况是代码中存在隐式类型转换,或者某些宏定义在特定编译选项下被改变。例如,某些编译器选项可能会影响数据类型的大小或对齐方式,导致原本正确的代码出现类型错误。比如,用户提到的-fshort-enums选项可能会影响枚举类型的大小,但这里的问题涉及__m128iint,可能与枚举无关。不过,用户提供的引用内容提到了-fno-strict-aliasing,但这也类型别名有关,而不是直接的类型赋值问题。 然后,我需要思考如何通过编译选项来解决这个问题。通常,处理类型不匹配的问题需要代码层面的修改,比如显式转换或使用正确的初始化函数。但用户希望调整编译选项,这可能涉及到放宽某些编译器的严格检查,或者启用特定的扩展支持。 查看GCC的编译选项,可能相关的有:-fpermissive,这个选项可以让编译器将某些错误降级为警告,允许代码编译通过,尽管可能存在类型不匹配的问题。不过,这样做可能掩盖潜在的错误,不是最佳实践。 另一个可能性是用户使用的代码中使用了某些宏或内联函数,这些可能需要特定的编译器扩展或指令集支持。例如,使用SSE指令需要启用相应的指令集,如-msse4.1或-mavx等。如果代码中使用了SIMD内在函数,但没有启用对应的指令集支持,编译器可能无法正确识别相关类型,导致类型错误。 因此,用户可能需要检查是否在编译时添加了适当的指令集选项。例如,在GCC中使用-msse2来启用SSE2支持,因为__m128i类型通常需要SSE2或更高版本的指令集支持。 此外,还需要确认代码中是否正确使用了SIMD内在函数的头文件,如#include <emmintrin.h>(SSE2)或其他相关头文件。缺少这些头文件可能导致编译器无法识别__m128i类型,从而引发错误。 如果用户确实在代码中错误地将int赋值给__m128i变量,那么即使调整编译选项,也可能无法解决问题,必须修改代码。例如,正确的方式是使用_mm_set_epi32或类似的函数来初始化__m128i变量,而不是直接赋值整数。 总结可能的解决方案步骤: 1. 确保代码中包含正确的头文件,如<emmintrin.h>。 2. 检查是否启用了必要的指令集选项,如-msse2。 3. 修改代码中的错误赋值,使用SIMD初始化函数。 4. 如果必须通过编译选项绕过错误,可以考虑使用-fpermissive,但需谨慎。 最后,需要向用户解释这些步骤,并建议优先修改代码而不是依赖编译选项,因为后者可能导致未定义行为或隐藏更深层次的问题。</think>针对将`int`类型赋值给`__m128i`类型的编译错误,解决方案需要从编译选项代码规范两方面入手: --- ### 1. 编译选项调整 #### a. **启用SSE指令集支持** `__m128i`是SSE指令集的128位整型向量类型,需确保编译器启用了对应的指令集支持: ```bash gcc -msse2 -march=native your_code.c ``` - `-msse2`:强制启用SSE2指令集(基础支持128位向量操作- `-march=native`:自动适配当前CPU支持的指令集扩展[^1] #### b. **关闭严格别名优化(备用方案)** 若错误与类型别名(Type Aliasing)冲突相关,可尝试禁用严格别名优化: ```bash gcc -fno-strict-aliasing your_code.c ``` 此选项允许不同类型指针指向同一内存地址,但可能降低性能优化效果[^1]。 --- ### 2. 代码规范修复 #### a. **使用SSE内置函数初始化** 避免直接赋值`int`,改用SIMD初始化函数: ```c #include <emmintrin.h> // SSE2头文件 __m128i vec = _mm_set_epi32(0, 0, 0, 0); // 用4个int初始化向量 // 或 __m128i vec = _mm_setzero_si128(); // 初始化为全0向量 ``` #### b. **显式类型转换** 若需从标量值构建向量,需明确数据类型转换逻辑: ```c int value = 42; __m128i vec = _mm_set1_epi32(value); // 将单个int复制到4个32位通道 ``` --- ### 3. 错误原因分析 编译器报错`incompatible type 'int'`表明: 1. 代码中存在非法类型转换(如`__m128i vec = 0;`) 2. 未包含SSE指令集头文件 3. 编译时未启用SSE指令集支持 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值