编译器如何使用分支和多个 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:
}