C++は、コンピュータメモリの理論モデルに対する操作の面で指定され、その上に龍との素敵な本があります。
また、「まるで」のルールとして知られている機能があります。これは、全体的な観察可能な効果が、あなたが書いたコードが文字通りメモリモデルに対する操作に変換されているかのようなものであれば、コンパイラが好きなコードを生成できることを意味します。
a(int): # @a(int)
push rbp
mov rbp, rsp
mov dword ptr [rbp - 4], edi
mov edi, dword ptr [rbp - 4]
shl edi, 1
mov dword ptr [rbp - 8], edi
mov eax, dword ptr [rbp - 8]
pop rbp
ret
と、次の呼び出しのコードを与えられた:最適化されていないコードでは
は、生成アセンブラは、例えばgccがあなたの関数のために以下のコードを生成可能性があるため、コードで表現操作に非常に近い現実である
extern void foo(int x);
int main()
{
foo(a(2));
}
次のコードが生成されることがあります。
main: # @main
push rbp
mov rbp, rsp
mov edi, 2
call a(int)
mov edi, eax
call foo(int)
xor eax, eax
pop rbp
ret
この単純なプログラムでは、コードの観察可能な効果は、値が4の引数でfoo
が呼び出されることです。a
の呼び出しには、観察可能な副作用が1つしかありません。つまり、戻り値はその入力値の2倍です。
戻り値はfoo
に直接渡され、どこにも格納されないため、foo
を呼び出してa
を呼び出すことによるすべての副作用が完全に消費されたと言えるでしょう。
したがって、コンパイラがa
の処理内容を知っている場合、それを呼び出すコードを生成する必要はありません。 foo
を呼び出すことができます。値は 'like as'の場合はa(2)
です。
実際に、最適化を追加することは私たちにこれを与える:
main: # @main
push rax
mov edi, 4 # note: 'as if' a(2)
call foo(int)
xor eax, eax
pop rcx
ret
a
の実装、この場合、(gccの上で)、次のとおりです。
a(int): # @a(int)
# 'as if' we created a variable and did some arithmetic,
# stored the result and then returned the result
lea eax, [rdi + rdi]
ret
呼び出し関数はEAX(またはどこでも)を使用します – Caleth
最適化されていないケースで何が起こるか知りたいですか?十分なコンパイラが 'int foo = a(2);'を 'foo'を' 4 'で直接初期化できるので、私は尋ねます。 – NathanOliver
コンパイラに関数のアセンブリ言語を出力するように指示します。 –