14.9.6内嵌函数
ARM编译器支持函数内嵌功能。使用关键字“_inline”声明函数,可以使函数内嵌。下面的例子显示了如何使用函数内嵌功能。
程序源文件如下。
__inlineintsquare(intx)
{
returnx*x;
}
#include<math.h>
doublelength(intx,inty)
{
returnsqrt(square(x)+square(y));
}
编译结果如下所示。
length
STMDBsp!,{lr}
MULa3,a1,a1
MLAa1,a2,a2,a3
BL_dflt
LDMIAsp!,{lr}
Bsqrt
使用函数内嵌有以下好处:
·减少了函数调用开销(如寄存器的压栈保护);
·减少了参数传递开销;
·进一步提高了编译器对代码优化的可能性(如编译器可将ADD和MUL指令合并为一条MLA指令)。
但使用函数内嵌将增加代码尺寸。也正是处于这种原因,armcc和tcc都没有提供函数自动内嵌的编译选项。
一般来说,只有对性能影响较大的重要函数才使用关键字_inline进行内嵌。
14.9.7函数定义
使用函数时要先定义后调用是ARM编程的基本规则之一。在函数调用之前定义函数,编译器可以检查被调用函数的寄存器使用情况,从而对其进行进一步的优化。
首先来看下面的例子。
intsquare(intx);
intsumsquares1(intx,inty)
{
returnsquare(x)+square(y);
}
/*square函数可以在本文件中定义,也可以在其他源文件中定义*/
intsquare(intx)
{
returnx*x;
}
intsumsquares2(intx,inty)
{
returnsquare(x)+square(y);
}
编译的结果如下所示。
sumsquares1
STMDBsp!,{v1,v2,lr}
MOVv1,a2
BLsquare
MOVv2,a1
MOVa1,v1
BLsquare
ADDa1,v2,a1
LDMIAsp!,{v1,v2,pc}
square
MOVa2,a1
MULa1,a2,a2
MOVpc,lr
sumsquares2
STMDBsp!,{lr}
MOVa3,a2
BLsquare
MOVa4,a1
MOVa1,a3
BLsquare
ADDa1,a4,a1
LDMIAsp!,{pc}
从编译的结果可以看出,将square函数定义放在sumsquares函数前,编译器可以判断寄存器a3和a4并未使用,所有在调用函数入口处并未将其压栈。这样,减少了内存访问,提高了代码执行效率。