2016-11-14 50 views
4

這是我的C#代碼:如何強制編譯器使用ldc.i8 IL指令而不是ldc.i4加conv.i8?

const long pSize = 20; 

不管,如果我使用的x64或任何CPU建立它在發行模式下,我得到如下MSIL指令:

IL_0010: ldc.i4.s 20 
    IL_0012: conv.i8 

然而,MSIL有最不發達國家。 i8指令。如何讓編譯器使用它?

+2

爲什麼你想要做什麼編譯器通常負責? – Sinatr

+0

所以你想強制編譯器生成比必要的更長的代碼? – hvd

+2

您正在詢問如何使MSIL *效率更低,ldc.i8需要4個字節。毫無意義。 –

回答

24

MSIL有ldc.i8指令。如何讓編譯器使用它?

你不知道。那會是更糟糕的代碼。

ldc.i4.s 20 
conv.i8 

是三個字節的代碼:兩個用於指令,一個用於常量。而

ldc.i8 20 

是九個字節:一個用於指令,八個用於常量。

編譯器足夠聰明,可以避免六個不必要的字節。請記住,代碼速度可能會受到加載到內存中所需的頁面錯誤數量的不利影響;生成的代碼比它需要的大三倍大。有違這個目標。

但是等等,還有更多,而且都很糟糕。

代碼的基本塊越大,圍繞它的分支越可能長於緊湊分支指令格式的長度。這意味着這種去優化可以使分支指令變大,這又使得它們的基本塊更大,並且現在可能分支約它們不緊湊,並且整個事情可以滾雪球。

它不只是六個額外的字節;這是所有這六個額外字節的後果,使其他代碼更大;你也必須考慮到這個成本。

編譯器做得很好。讓它做它的工作。

如果您的心臟設置爲使編譯器生成較差的代碼,則編譯器的源代碼可用。如果您出於某種原因真的需要編譯器,請隨時編寫一個去優化編譯器。

+0

指令「conv.i8」的實際效果是什麼?我的C#代碼想把20看作'long',然後再乘以另一個很長的數字。我認爲conv.i8將20個字節轉換爲long。 – Sheen

+1

@Sheen:操作碼語義清楚地記錄在案;做一些研究。另外,我覺得有些不安,你問如何強制編譯器生成一個替代的指令序列*而不知道當前的實際指令序列指令做了什麼*。 C#的設計使您可以瞭解C#的語義,從而推導出您的代碼;不要擔心IL。生成的IL是正確的。 –

+0

埃裏克,謝謝你的建議。我閱讀MSDN頁面。它說3個步驟: 1.值被推入堆棧。 2.從堆棧彈出值並嘗試轉換操作。 3.如果轉換成功,則將結果值壓入堆棧。 所以在運行時,將int64直接放在堆棧上更好嗎? – Sheen