1

32 ビット値のビット 0、8、16、24 をそれぞれビット 0、1、2、3 に移動したいと考えています。入力と出力の他のすべてのビットはゼロになります。

明らかに、私は次のようにそれを行うことができます:

c = c>>21 + c>>14 + c>>7 + c;
c &= 0xF;

しかし、より高速な (命令が少ない) 方法はありますか?

4

3 に答える 3

2
c = (((c&BITS_0_8_16_24) * BITS_0_7_14_21) >> 21) & 0xF;

または、これらすべてを 1 つの命令 (pext) で実行する Intel Haswell プロセッサを待ちます。

アップデート

を考慮clarified constraintsして仮定32-bit unsigned valuesすると、コードは次のように簡略化できます。

c = (c * BITS_7_14_21_28) >> 28;
于 2012-01-10T12:26:29.177 に答える
1

移植性を気にせず、SSE 命令を使用できる場合は、PMOVMSKB命令とそのコンパイラ組み込みを調べてください。[あなたのビット位置は、32 ビット ワードを構成する 4 バイトの最上位 (符号) ビットであることに気付きました。]

于 2012-01-10T12:27:35.257 に答える
0

難読化された 1 行のグーを書く代わりに、移植性と保守性を最大限に高めるために、以下のコードを記述します。それが最も効果的なコードであるかどうかをオプティマイザーに心配させます。

#include <stdint.h>
#include <limits.h>
#include <stdio.h>

#define BITS_TO_MOVE  4

static const uint32_t OLD_MASK [BITS_TO_MOVE] =
{
  0x0008u,
  0x0080u,
  0x0800u,
  0x8000u
};

static const uint32_t NEW_MASK [BITS_TO_MOVE] =
{
  0x1000u,
  0x2000u,
  0x4000u,
  0x8000u
};


int main()
{
  uint32_t  c     = 0xAAAAu;
  uint32_t  new_c = 0;
  uint8_t   i;

  printf("%.4X\n", c);


  for(i=0; i<BITS_TO_MOVE; i++)
  {
    if ( (c & OLD_MASK[i]) > 0 )
    {
      new_c |= NEW_MASK[i];
    }
  }


  printf("%.4X\n", new_c);
  getchar();

  return 0;
}
于 2012-01-10T12:47:48.917 に答える