编译器如何通过分支和多个return语句内联函数?

时间:2019-05-04 19:18:28

标签: compiler-construction inline

如果内联函数以结尾处的单个返回结尾,那么从概念上简单地用函数体替换调用者代码是微不足道的。

inline int foo(int i) {
    return i - 1;
}

// prior to inline
int result = foo(k);
// => after inline
int result = k - 1;

如果有分支机构并且有多个回报,该怎么办?编译器如何生成正确的代码?简单的替换显然是不够的。

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;

2 个答案:

答案 0 :(得分:1)

您可以看到inline temp编译器之后的输出。进行实验,您会看到它是如何完成的https://godbolt.org/z/0MkWLs

答案 1 :(得分:1)

允许编译器在编译期间进行各种形式的代码转换。对于您的示例,编译器可以将函数foo转换为

int foo(int i)
{
  int rv;
  if (i > 0)
  {
    rv = i - 1;
    goto end;
  }

  rv = i + 1;
end:
  return rv;
}

然后可以将此代码插入到调用方中。在插入期间,编译器会引入变量来处理参数和内联函数的返回值。结果看起来像下面的代码。

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:
}