函数内联pass

简介

编译器中的函数内联是一种优化技术,用于减少函数调用的开销。当函数被标记为内联时,编译器会将该函数的代码副本直接插入到每个调用该函数的地方,而不需要在运行时跳转到函数代码,这样可以提高代码的执行效率。

int add(int a,int b)
{
    return a + b;
}  
int fun()
{
    int a = 2;
    int b = 3;
    a = add(a, b);
}

内联后

int fun()
{
   int a = 2;
   int b = 3;
   a = a + b;
}

原理

调用图

调用图(call graph),就是告诉我们哪个函数调用了那个函数的图。一个程序的调用图是一个节点和边的集合,并满足
1.对程序中的每一个函数都有一个节点。
2.对于每个调用点(call site)都有一个节点。所谓调用点就是程序中调用某个函数的一个位置。
3.如果调用点c调用了函数p,就存在一条从c的节点到p的节点的边。
调用图其实是一个图结构数据。
以下是一个简单示例:

void fun0()
{
}
void fun1()
{
    fun0();
}
void fun2()
{
}
int main()
{
 fun1();
 fun2();   
}

调用图如下所示:
在这里插入图片描述

这里一共有3条边,如上图标号所示。
使用深度优先遍历:
节点id:3的from节点是fun0函数,to节点是fun1。
节点id:1的from节点是fun1函数,to节点是main。
节点id:2的from节点是fun2函数,to节点是main。
节点id:0的from节点是main函数,to节点是NULL。

实现

1.优化调用深度,对于调用深度大于3的函数块进行内联。目的是减少调用调用深度,增加程序执行效率。
2.如果函数有标志inline,那么把函数添加到候选列表。
3.如果被调用函数调用点只有一个,那么把函数添加到候选列表。
4.内联所有候选列表中的函数。

内联函数

1.将被调用者函数中的所有指令放到集合A中。
2.找到被调用者函数的调用者函数,从调用者函数中找到其中调用点call。
3.被调用者函数参数提升成全局变量,局部变量提升成调用者函数中的局部变量。
4.将调用点call改变为label指令。
5.将集合A中的所有指令插入到调用点label指令之前。
6.更新调用参数。

例子

int add(int a,int b)
{
    return a + b;
}  
int main()
{
    int a = 2;
    int b = 3;
    int c = 0;
    c = add(a, b);
}
fun add
param0 a ==> R0
param1 b ==> R1
param2 out ==> R2
LABEL0:
ADD R3, R0, R1
MOV R2, R3
RET

fun main
local a ==> R4
local b ==> R5
local c ==> R6
MOV R4, 2
MOV R5, 3
MOV R6, 0
MOV R0, R4
MOV R1, R5
CALL add
MOV R6, R2

内联后

fun main
local a ==> R4
local b ==> R5
local c ==> R6
MOV R4, 2
MOV R5, 3
MOV R6, 0
ADD R6, R4, R5
  • 6
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值