例如,如果xmm值是
| r0 = 0 | r1 = 1 | r2 = 0 | r3 = 1 | r4 = 0 | r5 = 1 | r6 = 0 | … | r14 = 0 | r15 = 1 |
结果应该是(1,3,5,…,15).结果应放在另一个_m128i变量或char [16]数组中.
如果有帮助,我们可以假设寄存器的值是所有字节都是0或某个常量非零值(不是必需的1).
我非常想知道是否有关于那个或最好是C/C++内在的指令.在任何SSE或AVX指令集中.
编辑1:
这是正确的observed by @zx485原始问题不够清楚.我一直在寻找任何“连续”的解决方案.
上面的示例0 1 0 1 0 1 0 1 …应该导致以下任一情况:
>如果我们假设索引从1开始,则0将是终止字节,结果可能是
002 004 006 008 010 012 014 016 000 000 000 000 000 000 000 000
>如果我们假设负字节是终止字节,结果可能是
001 003 005 007 009 011 013 015 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
>任何东西,它给出一个连续的字节,我们可以将其解释为原始值中非零元素的索引
编辑2:
实际上,正如@harold和@Peter Cordes在对原始帖子的评论中所建议的那样,可能的解决方案之一是首先创建一个掩码(例如使用pmovmskb)并检查那里的非零索引.但这将导致循环.
解决方法
不连续的:
XMM0: 000 001 000 003 000 005 000 007 000 009 000 011 000 013 000 015
连续的:
XMM0: 001 003 005 007 009 011 013 015 000 000 000 000 000 000 000 000
连续方法的一个问题是:您如何确定它是索引0还是终止值?
我正在为第一个非连续方法提供一个简单的解决方案,它应该非常快:
.data ddqZeroToFifteen db 0,1,2,4,6,7,8,9,10,11,12,13,14,15 ddqTestValue: db 0,1 .code movdqa xmm0,xmmword ptr [ddqTestValue] pxor xmm1,xmm1 ; zero XMM1 pcmpeqb xmm0,xmm1 ; set to -1 for all matching pandn xmm0,xmmword ptr [ddqZeroToFifteen] ; invert and apply indices
仅仅为了完整性:第二个是连续的方法,在这个答案中没有涉及.