3

たとえば、次の関数がある場合:

void foo(DoThisSometimes, DoThisAlways)
{
  if (DoThisSometimes == 1)
    {
      //Do stuff
    }
  //Do other stuff
{

そして、インライン化されたコードは、この関数をDoThisSometimes0として呼び出します。コードのこの部分をインライン化された関数から削除するコンパイラーはありますか?

if (DoThisSometimes == 1)
    {
      //Do stuff
    }
4

2 に答える 2

6

まともなコンパイラは確かにその最適化を行うべきであり、GCCはそうします。次のソース:

#include <cstdio>

inline void foo(bool maybe)
{
    if (maybe) {
        printf("Maybe\n");
    }
    printf("Always\n");
}

int main()
{
    foo(true);
    foo(false);
}

(最適化を使用して-O3)コンパイルして次のようにします。

0000000000400410 <main>:
  400410:   48 83 ec 08             sub    $0x8,%rsp
  400414:   bf e4 05 40 00          mov    $0x4005e4,%edi
  400419:   e8 d2 ff ff ff          callq  4003f0 <puts@plt>
  40041e:   bf ea 05 40 00          mov    $0x4005ea,%edi
  400423:   e8 c8 ff ff ff          callq  4003f0 <puts@plt>
  400428:   bf ea 05 40 00          mov    $0x4005ea,%edi
  40042d:   e8 be ff ff ff          callq  4003f0 <puts@plt>
  400432:   31 c0                   xor    %eax,%eax
  400434:   48 83 c4 08             add    $0x8,%rsp
  400438:   c3                      retq   
  400439:   0f 1f 00                nopl   (%rax)

puts無条件に3回呼び出す。

于 2013-02-19T19:04:39.457 に答える
1

はい、おそらく。コンパイラーが値を理解できる場合、多くの場合、ifステートメントのすべてまたは一部が削除されます。

の一部とは、あなたがそうする場合を意味します:

 if (DoThisSometimes == 1 || foo == 0)

コンパイラは、インライン化ポイントで既知の値を持っていない可能性があるためDoThisSometimes==1、おそらくfoo == 0一部を削除することはできますが、削除することはできません。foo

これはコンパイラの実装の詳細であるため、コンパイラはステートメントを削除することを保証されていません。また、値が何であるかを理解できない場合は、間違いなくそうなりません。また、関数が長すぎると考えられるため、ifステートメントがある場合は関数をインライン化しないことを決定する場合があります。その後、ifステートメントがなくなった場合は、インライン化しても問題ありません。したがって、これが発生することは予想できますが、超臨界の場合は、これに依存しないでください。その場合は、「DoThisSometimes ==1」用と「DoThisSometimes!=1」用の2つの関数を作成します。

于 2013-02-19T18:58:11.740 に答える