我正在尝试优化嵌入式系统中的一些代码(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上的clz
(http://www.devmaster.net/articles/fixed-point-optimizations/),这应该更有效。
在Windows CE上,我们有内部函数_CountLeadingZeros,它应该只调用该值。然而,它比宏观慢4倍(在1000万次迭代中测量)。
(应该)依赖专用ASM指令的内部函数有可能慢4倍?
答案 0 :(得分:5)
检查拆卸。你确定编译器插入了指令吗?在备注部分有这样的文字:
此功能可以通过以下方式实现 调用运行时函数。
我怀疑你的情况正是如此。
请注意,CLZ指令仅在ARMv5及更高版本中可用。您需要告诉编译器您是否需要ARMv5代码:
/QRarch5 ARM5 Architecture
/QRarch5T ARM5T Architecture
(Microsoft错误地使用“ARM5”而不是“ARMv5”)