傳統的C/C 編譯器透過增加堆疊指標來創建局部變數(ESP)一次。然而,使用入棧/出棧指令可以產生更緊湊且可能更快的程式碼。本文探討了哪些編譯器提供此最佳化。
研究顯示所有四個主要x86 編譯器(GCC、Clang、ICC 和MSVC)目前都不使用推送/彈出來建立局部變數的指令。相反,他們更喜歡舊方法的變體,使用 sub rsp, c 來減少堆疊指標。
對局部變數使用push/pop 有幾個優點:
雖然Push/Pop可以是有益的,但不建議在所有情況下都這樣做。例如,與 [rsp x] 尋址模式混合時,它可能會導致額外的堆疊同步 uops。
考慮以下函數:
int extfunc(int *,int *); void foo() { int a=1, b=2; extfunc(&a, &b); }
使用改良的編譯push/pop:
# compiled for the x86-64 System V calling convention: # integer args in rdi, rsi (,rdx, rcx, r8, r9) push 2 # only 2 bytes lea rdi, [rsp + 4] mov dword ptr [rdi], 1 mov rsi, rsp # special case for lea rsi, [rsp + 0] call extfunc(int*, int*) pop rax # alternative to add rsp,8 ret
注意: 此範例透過將push 指令的最後4 個位元組與lea 指令的前4 個位元組重疊來優化緊湊性和速度.結論雖然push/pop指令可以為創建本地程式碼提供程式碼大小和效能優勢變量,目前主流C /C 編譯器尚未使用它們。這可能是由於可能存在額外的堆疊同步微指令以及管理堆疊偏移的複雜性。然而,隨著硬體和編譯器最佳化的發展,局部變數的推送/彈出將來可能會得到更廣泛的採用。
以上是C/C 編譯器是否使用 Push/Pop 指令來建立局部變數?的詳細內容。更多資訊請關注PHP中文網其他相關文章!