编译器如何使用分支和多个 return 语句内联函数?
How does compiler inline a function with branches and multiple return statements?
如果内联函数最后以单个 return 结束,从概念上讲,用函数体简单地替换调用者代码是微不足道的。
inline int foo(int i) {
return i - 1;
}
// prior to inline
int result = foo(k);
// => after inline
int result = k - 1;
如果有分支和多个return怎么办?编译器如何生成正确的代码?简单的替换显然是不够的。
inline int foo(int i) {
if (i > 0)
return i - 1;
return i + 1;
}
// prior to inline
int result = foo(k);
// => after inline
int result;
if (k > 0)
result = k - 1;
result = k + 1;
您可以看到内联临时编译器输出后。实验一下,你就会知道它是如何完成的https://godbolt.org/z/0MkWLs
允许编译器在编译期间对代码进行各种转换。对于您的示例,编译器可以将函数 foo
转换为
int foo(int i)
{
int rv;
if (i > 0)
{
rv = i - 1;
goto end;
}
rv = i + 1;
end:
return rv;
}
然后可以将此代码插入调用方。在插入期间,编译器引入变量来处理内联函数的参数和 return 值。结果类似于下面的代码。
int foo_rv;
int foo_param_i = k;
{
int i = foo_param_i;
if (i > 0)
{
rv = i - 1;
goto end:
}
rv = i + 1;
end:
foo_rv = rv
}
int result = foo_rv;
此代码随后可以由编译器进一步优化,生成以下代码
{
if (k > 0)
{
result = k - 1;
goto end:
}
result = k + 1;
end:
}
如果内联函数最后以单个 return 结束,从概念上讲,用函数体简单地替换调用者代码是微不足道的。
inline int foo(int i) {
return i - 1;
}
// prior to inline
int result = foo(k);
// => after inline
int result = k - 1;
如果有分支和多个return怎么办?编译器如何生成正确的代码?简单的替换显然是不够的。
inline int foo(int i) {
if (i > 0)
return i - 1;
return i + 1;
}
// prior to inline
int result = foo(k);
// => after inline
int result;
if (k > 0)
result = k - 1;
result = k + 1;
您可以看到内联临时编译器输出后。实验一下,你就会知道它是如何完成的https://godbolt.org/z/0MkWLs
允许编译器在编译期间对代码进行各种转换。对于您的示例,编译器可以将函数 foo
转换为
int foo(int i)
{
int rv;
if (i > 0)
{
rv = i - 1;
goto end;
}
rv = i + 1;
end:
return rv;
}
然后可以将此代码插入调用方。在插入期间,编译器引入变量来处理内联函数的参数和 return 值。结果类似于下面的代码。
int foo_rv;
int foo_param_i = k;
{
int i = foo_param_i;
if (i > 0)
{
rv = i - 1;
goto end:
}
rv = i + 1;
end:
foo_rv = rv
}
int result = foo_rv;
此代码随后可以由编译器进一步优化,生成以下代码
{
if (k > 0)
{
result = k - 1;
goto end:
}
result = k + 1;
end:
}