推測された段階的な手順は、コンパイルされた出力に関して正しくありません。 CLRはスタックマシンであり、4つすべてを一度に追加するコードでは、中間合計を名前付き変数として個別に割り当てる必要がないため、実行中の合計をその場で更新します(または先頭のスタック要素をポップしてプッシュします)。
ステップバイステップのバージョンでは、実際の操作と同じ数の操作が必要です。単項加算バージョンでは、ローカル変数の割り当てを1つ少なくするだけです。
以下は、4つの入力複素数を加算する3つの異なる方法により生成される実際のILあります。私のバージョンでは、Complexクラス(How to: Use Operator Overloading to Create a Complex Number Class (C# Programming Guide)から離したと仮定します)にint
の代わりに2つのdouble
の値を保持するように変更しました。私は簡潔にするためにC#とILコードの両方でc1..c4の宣言を省略しました。要するに、推論された段階的アプローチの両方は、2つの余分なもの(変数リストに値をプッシュする)と、ldloc.s
(変数リストから値を取得する)
オリジナル:
C番号:
Complex csum = c1 + c2 + c3 + c4;
IL:
// MultipleAdd : 5 Locals, maxstack 3
IL_0068: nop
IL_0069: ldloc.0
IL_006a: ldloc.1
IL_006b: call valuetype Test.Complex Test.Complex::op_Addition(valuetype Test.Complex,
valuetype Test.Complex)
IL_0070: ldloc.2
IL_0071: call valuetype Test.Complex Test.Complex::op_Addition(valuetype Test.Complex,
valuetype Test.Complex)
IL_0076: ldloc.3
IL_0077: call valuetype Test.Complex Test.Complex::op_Addition(valuetype Test.Complex,
valuetype Test.Complex)
IL_007c: stloc.s csum
IL_007e: ret
推論1:三バイナリ加算
C#の行のすべての4つの追加:
Complex ct1 = c1 + c2;
Complex ct2 = ct1 + c3;
Complex csum = ct2 + c4;
IL:
// BinaryAdd : 7 Locals, maxstack 3
IL_0068: nop
IL_0069: ldloc.0
IL_006a: ldloc.1
IL_006b: call valuetype Test.Complex Test.Complex::op_Addition(valuetype Test.Complex,
valuetype Test.Complex)
IL_0070: stloc.s ct1
IL_0072: ldloc.s ct1
IL_0074: ldloc.2
IL_0075: call valuetype Test.Complex Test.Complex::op_Addition(valuetype Test.Complex,
valuetype Test.Complex)
IL_007a: stloc.s ct2
IL_007c: ldloc.s ct2
IL_007e: ldloc.3
IL_007f: call valuetype Test.Complex Test.Complex::op_Addition(valuetype Test.Complex,
valuetype Test.Complex)
IL_0084: stloc.s csum
IL_0086: ret
推論2:単項加算
C番号:
Complex ct = c1 + c2;
ct += c3;
Complex csum = ct + c4;
IL:
// UnaryAdd : 6 Locals, maxstack 3
IL_0068: nop
IL_0069: ldloc.0
IL_006a: ldloc.1
IL_006b: call valuetype Test.Complex Test.Complex::op_Addition(valuetype Test.Complex,
valuetype Test.Complex)
IL_0070: stloc.s ct
IL_0072: ldloc.s ct
IL_0074: ldloc.2
IL_0075: call valuetype Test.Complex Test.Complex::op_Addition(valuetype Test.Complex,
valuetype Test.Complex)
IL_007a: stloc.s ct
IL_007c: ldloc.s ct
IL_007e: ldloc.3
IL_007f: call valuetype Test.Complex Test.Complex::op_Addition(valuetype Test.Complex,
valuetype Test.Complex)
IL_0084: stloc.s csum
IL_0086: ret
**コンパイラ**の仕事ではありません。 _compiler_はコンパイル時に魔法ですか?メモリ割り当ては実行時に 'CLR' /' JIT'ジョブ... – gdoron
gdoron、コンパイラはこれをどのようにしてコードを生成するのでしょうか?あなたは好きです。 – MetallicPriest
最適化されたバージョンではc4を忘れてしまいます。 –