是否有一個屬性可用於告訴編譯器必須始終優化一個方法,即使全局/o+
編譯器開關未設置?我可以強制編譯器優化特定方法嗎?
我問的原因是因爲我正在根據現有方法的IL代碼動態創建一個方法,當代碼被優化時,我想要做的操作相當容易,但由於編譯器生成的額外指令,在非優化代碼中變得非常困難。
編輯:關於打擾我的非優化的詳細信息...
讓我們看看下面的實現階乘函數:
static long FactorialRec(int n, long acc)
{
if (n == 0)
return acc;
return FactorialRec(n - 1, acc * n);
}
(注:我知道有是更好的方法來計算階乘,這只是一個例子)
IL優化生成啓用我個相當簡單:
IL_0000: ldarg.0
IL_0001: brtrue.s IL_0005
IL_0003: ldarg.1
IL_0004: ret
IL_0005: ldarg.0
IL_0006: ldc.i4.1
IL_0007: sub
IL_0008: ldarg.1
IL_0009: ldarg.0
IL_000A: conv.i8
IL_000B: mul
IL_000C: call UserQuery.FactorialRec
IL_0011: ret
但沒有優化的版本是完全不同的
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.0
IL_0003: ceq
IL_0005: ldc.i4.0
IL_0006: ceq
IL_0008: stloc.1
IL_0009: ldloc.1
IL_000A: brtrue.s IL_0010
IL_000C: ldarg.1
IL_000D: stloc.0
IL_000E: br.s IL_001F
IL_0010: ldarg.0
IL_0011: ldc.i4.1
IL_0012: sub
IL_0013: ldarg.1
IL_0014: ldarg.0
IL_0015: conv.i8
IL_0016: mul
IL_0017: call UserQuery.FactorialRec
IL_001C: stloc.0
IL_001D: br.s IL_001F
IL_001F: ldloc.0
IL_0020: ret
它被設計成只有一個出口點,在最後。要返回的值存儲在局部變量中。
爲什麼這是一個問題?我想動態生成一個包含尾部呼叫優化的方法。通過在遞歸調用之前添加tail.
前綴,可以很容易地修改優化的方法,因爲在除ret
之外的通話之後沒有任何內容。但是對於未優化的版本,我不太確定......遞歸調用的結果存儲在本地變量中,然後有一個無用的分支跳轉到下一條指令,本地變量被加載並返回。所以我沒有簡單的方法來檢查遞歸調用是否是最後的指令,所以我不能確定是否可以應用尾部調用優化。
AFAIK,no - 這是不可能的 – 2012-03-13 10:56:01
JIT編譯器將始終優化每個方法。 – Steven 2012-03-13 11:01:39
@Steven,如果你不告訴它(例如使用'MethodImplAttribute'中的'NoOptimization'標誌)。但無論如何,我的問題是關於編譯器優化,而不是JIT優化,因爲我對生成的IL代碼感興趣。 – 2012-03-13 11:17:34