【发布时间】:2011-07-20 21:01:57
【问题描述】:
我正在为 ARM9 处理器编写一些日志记录 C 代码。如果存在动态模块,此代码将记录一些数据。该模块通常不会出现在生产版本中,但日志代码将始终被编译进去。想法是如果客户遇到错误,我们可以加载此模块,日志代码将转储调试信息。
当模块不存在时,日志记录代码的影响必须最小,因此每个周期都很重要。通常,日志记录代码如下所示:
__inline void log_some_stuff(Provider *pProvider, other args go here...)
{
if (NULL == pProvider)
return;
... logging code goes here ...
}
启用优化后,RVCT 4.0 生成的代码如下所示:
ldr r4,[r0,#0x2C] ; pProvider,[r0,#44]
cmp r4,#0x0 ; pProvider,#0
beq 0x23BB4BE (usually taken)
... logging code goes here...
... regular code starts at 0x23BB4BE
此处理器没有分支预测器,我的理解是,每当采用分支时都会有 2 个周期的惩罚(如果不采用分支则不会受到惩罚)。
我希望将NULL == pProvider 的常见情况作为快速情况,即不采用分支。如何让 RVCT 4.0 生成这样的代码?
我尝试使用__builtin_expect,如下所示:
if (__builtin_expect(NULL == pProvider, 1))
return;
很遗憾,这对生成的代码没有影响。我是否错误地使用了__builtin_expect?还有其他方法吗(希望没有内联汇编)?
【问题讨论】:
-
这段代码没有意义。如果 pProvider 是第一个 arg 并且在没有取消引用的情况下检查 NULL,则编译器将不需要 ldr,因为 pProvider 已经在 r0 中。看起来您正在查看 Provider 类型的偏移量。
-
@Variable Length Coder,日志函数是内联的,不用担心参数。 ldr 指令正在从某些数据结构中获取 pProvider。如果函数没有内联,这将在调用之前发生。
-
作为参考,RVCT 3.0 文档表明支持__builtin_expect
标签: c optimization embedded arm arm9