我撰寫了以下非常簡單的代碼,我正在 godbolt 的編譯器資源管理器中對其進行試驗:
#include <cstdint>
uint64_t func(uint64_t num, uint64_t den)
{
return num / den;
}
GCC 產生以下輸出,這是我所期望的:
func(unsigned long, unsigned long):
mov rax, rdi
xor edx, edx
div rsi
ret
然而,Clang 13.0.0 產生以下內容,包括移位和跳躍:
func(unsigned long, unsigned long): # @func(unsigned long, unsigned long)
mov rax, rdi
mov rcx, rdi
or rcx, rsi
shr rcx, 32
je .LBB0_1
xor edx, edx
div rsi
ret
.LBB0_1:
xor edx, edx
div esi
ret
使用 uint32_t 時,clang 的輸出再次“簡單”并且符合我的預期。
似乎這可能是某種優化,因為 clang 10.0.1 產生與 GCC 相同的輸出,但是我無法理解發生了什么。為什么 clang 會生產這個更長的組件?
uj5u.com熱心網友回復:
程式集似乎通過右移 32 位然后檢查結果數是否為 0來檢查num或den是否大于 2**32。根據決定,64 位除法 ( div rsi) 或 32 位除法 ( div esi) 進行。
據推測,生成這段代碼是因為編譯器撰寫者認為額外的檢查和潛在的分支超過了進行不必要的 64 位除法的成本。
uj5u.com熱心網友回復:
如果我理解正確,它只是檢查是否有任何運算元大于 32 位,并為“最多”32 位和更大的 div 使用不同的 div。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/377381.html
