c++ - 计算 sse var 最大掩码的最佳方法

标签 c++ assembly x86 bit-manipulation sse

(我只对前三个组件感兴趣)

例如:
[ 1 2 3 ? ] 应该生成 [ 0 0 -1 ? ]

此外,只设置一个“位”很重要,这样:
[ 1 2 2 ? ] 不应该产生 [ 0 -1 -1 ? ]
而是
[ 0 -1 0 ? ][ 0 0 -1 ? ](哪个无关紧要)

后来的(坏的)解决方案是可能的,例如通过提取水平最大值并与原始的进行比较:

__m128 abcd; // input
__m128 ccac           = _mm_shuffle_ps(abcd, abcd, 0x8A);
__m128 abcd_ccac      = _mm_max_ps(abcd, ccac);
__m128 babb           = _mm_shuffle_ps(abcd, abcd, 0x51);
__m128 abcd_ccac_babb = _mm_max_ps(abcd_ccac, babb);
__m128 mask           = _mm_cmpeq_ps(abcd, abcd_ccac_babb);

也许一些位运算来摆脱重复的设置位?

更新:

跟进,我做了另一个(坏的)解决方案。
关键是将每个组件与另一个组件进行比较,避免等式(没有 a >= bb >= a 在另一个地方)。

a > b & a >= c
b > c & b >= a
c > a & c >= b

产生:

([ a b c ? ] > [ b c a ? ]) & ([ a b c ? ] >= [ c a b ? ])

在代码中:

__m128 abcd; // input
__m128 bcad = _mm_shuffle_ps(abcd, abcd, 0xC9);
__m128 gt   = _mm_cmpgt_ps(abcd, bcad);
__m128 cabd = _mm_shuffle_ps(abcd, abcd, 0xD2);
__m128 ge   = _mm_cmpge_ps(abcd, cabd);
__m128 mask = _mm_and_ps(gt, ge);

[ x x x ? ](生成 [ 0 0 0 ? ])。

接近:-)

有什么想法吗?

更新:

我现在使用以下解决方案:

__m128  abcd; // input
__m128  bcad = _mm_shuffle_ps(abcd, abcd, 0xC9);
__m128  gt   = _mm_cmpgt_ps(abcd, bcad);
__m128  cabd = _mm_shuffle_ps(abcd, abcd, 0xD2);
__m128  ge   = _mm_cmpge_ps(abcd, cabd);
__m128  and  = _mm_and_ps(gt, ge);
__m128i bits = _mm_setr_epi32(_mm_movemask_ps(and), -1, -1, -1);
__m128i dirt = _mm_cmpeq_epi32(bits, _mm_setzero_si128());
__m128i mask = _mm_or_si128(dirt, _mm_castps_si128(and));

最佳答案

我没有测试过这个,但我相信它只会在最大值的第一次(最高阶)出现时让你 -1:

__m128 abcd; // input
__m128 ccac = _mm_shuffle_ps( abcd,abcd,0x8A );
__m128 abcd_ccac = _mm_max_ps( abcd,ccac );
__m128 babb = _mm_shuffle_ps( abcd,abcd,0x51 );
__m128 abcd_ccac_babb = _mm_max_ps( abcd_ccac,babb );
__m128 mask = _mm_cmpeq_ps( abcd,abcd_ccac_babb );

// set the '?' position in mask to zero
mask = _mm_blend_ps( mask,_mm_setzero_ps(),0x08 );
// shift mask left 32 bits shifting in zeros
__m128 maskSrl32 = _mm_shuffle_ps( mask,mask,_MM_SHUFFLE( 3,1,0,3 ) );
// shift mask left 64 bits shifting in zeros
__m128 maskSrl64 = _mm_shuffle_ps( mask,mask,_MM_SHUFFLE( 3,0,3,3 ) );
// andnot the shifted masks with mask
// in doing so, the higher order set bits will suppress any set bits which follow
mask = _mm_andnot_ps( maskSrl32,mask );
mask = _mm_andnot_ps( maskSrl64,mask );
// select -1 using the final mask
__m128 result = _mm_and_ps( mask,_mm_set1_ps( -1.0f ) );

反转移动方向以在最低阶最大位置产生 -1。

关于c++ - 计算 sse var 最大掩码的最佳方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30325247/

相关文章:

c++ - 读取较大文件时出现未处理的异常

组装emu8086对角线

assembly - 两个 16 位数字的 GCD(最大公约数)

assembly - printf 在 x86-64 上是否需要额外的堆栈空间?

gcc - 如何以编程方式编辑二进制文件 (x86)?

assembly - 汇编中的 LONG 和 FAR 跳转之间有什么区别(如果有的话)?

c++ - boost zlib 过滤器在 Windows 中不起作用

c# - 从 C# 应用程序调用 C++ 函数。尝试读取或写入 protected 内存

c++ - 了解复制构造函数的工作

assembly - AX、AH、AL如何映射到EAX?