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

时间:2010-10-28 16:02:56

标签: embedded windows-ce bit-manipulation inline-assembly intrinsics

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

default implementation使用宏和查找表:

/* 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
};

但是,大多数CPU已经有一条专用指令,x86上的bsr和ARM上的clzhttp://www.devmaster.net/articles/fixed-point-optimizations/),这应该更有效。

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

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

1 个答案:

答案 0 :(得分:5)

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

  

此功能可以通过以下方式实现   调用运行时函数。

我怀疑你的情况正是如此。

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

/QRarch5 ARM5 Architecture
/QRarch5T ARM5T Architecture

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