具有内在函数的前导零计算

lor*_*ova 4 embedded bit-manipulation inline-assembly intrinsics windows-ce

我正在尝试优化在嵌入式系统中工作的一些代码(FLAC解码,Windows CE,ARM 926 MCU).

默认实现使用宏和查找表:

/* counts the # of zero MSBs in a word */
#define COUNT_ZERO_MSBS(word) ( \
 (word) <= 0xffff ? \
  ( (word) <= 0xff? byte_to_unary_table[word] + 24 : \
              byte_to_unary_table[(word) >> 8] + 16 ) : \
  ( (word) <= 0xffffff? byte_to_unary_table[word >> 16] + 8 : \
              byte_to_unary_table[(word) >> 24] ) \
)

static const unsigned char byte_to_unary_table[] = {
    8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
    3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
Run Code Online (Sandbox Code Playgroud)

但是,大多数CPU已经bsr在x86和clzARM(http://www.devmaster.net/articles/fixed-point-optimizations/)上有一个专用指令,应该更有效率.

在Windows CE上,我们有内部函数_CountLeadingZeros,它应该只调用该值.然而,它比宏观慢4倍(在1000万次迭代中测量).

(应该)依赖于专用ASM指令的内部函数有可能慢4倍?

Igo*_*sky 5

检查拆卸.你确定编译器插入了指令吗?在备注部分有这样的文字:

可以通过调用运行时函数来实现此函数.

我怀疑这就是你的情况.

请注意,CLZ指令仅在ARMv5及更高版本中可用.您需要告诉编译器您是否需要ARMv5代码:

/QRarch5 ARM5 Architecture
/QRarch5T ARM5T Architecture
Run Code Online (Sandbox Code Playgroud)

(Microsoft错误地使用"ARM5"而不是"ARMv5")