Die Indizes von Nicht-Null-Bytes eines SSE / AVX-Registers
Wenn der Wert eines SSE / AVX-Registers so ist, dass alle seine Bytes entweder 0 oder 1 sind, gibt es eine Möglichkeit, die Indizes aller Nicht-Null-Elemente effizient abzurufen?
Zum Beispiel, wenn der xmm-Wert | ist r0 = 0 | r1 = 1 | r2 = 0 | r3 = 1 | r4 = 0 | r5 = 1 | r6 = 0 | ... | r14 = 0 | r15 = 1 | das Ergebnis sollte ungefähr so lauten (1, 3, 5, ..., 15). Das Ergebnis sollte in eine andere _m128i-Variable oder ein anderes char [16] -Array gestellt werden.
Wenn es hilft, können wir davon ausgehen, dass der Wert des Registers so ist, dass alle Bytes entweder 0 oder ein konstanter Wert ungleich Null sind (nicht erforderlich 1).
Ich frage mich ziemlich genau, ob es eine Anweisung dafür gibt oder vorzugsweise C / C ++ intrinsic. In jedem SSE- oder AVX-Befehlssatz.
EDIT 1:
Es war richtigbeobachtet von @ zx485 Diese ursprüngliche Frage war nicht klar genug. Ich habe nach einer "aufeinanderfolgenden" Lösung gesucht.
Das Beispiel0 1 0 1 0 1 0 1...
oben sollte eine der folgenden Folgen haben:
0
wäre ein Beendigungsbyte und das Ergebnis könnte @ se002 004 006 008 010 012 014 016 000 000 000 000 000 000 000
Wenn wir annehmen, dass das negative Byte ein Abschlussbyte ist, könnte das Ergebnis @ sei001 003 005 007 009 011 013 015 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
Alles, das als aufeinanderfolgende Bytes gibt, die wir als Indizes von Nicht-Null-Elementen im ursprünglichen Wert interpretieren könnenEDIT 2:
Indeed, as@ harold und@ Peter Cordes Schlagen Sie in den Kommentaren zum ursprünglichen Beitrag vor, dass eine der möglichen Lösungen darin besteht, zuerst eine Maske zu erstellen (z. B. mitpmovmskb
) und dort Indizes ungleich Null prüfen. Das führt aber zu einer Schleife.