Intel Sandy Bridge/Ivy Bridge架構/微架構/流水線 (6) - 流水線前端微熔合/巨集熔合
Micro Fusion
微熔合將來自於同一條x86指令的多條微指令熔合成單條複雜的微指令.這條複雜的微指令可以被分發到亂序執行核任意多次,就好象沒有進行過微熔合一樣(即亂序執行核並不能感知到微熔合機制的存在)。
微熔合機制使得程式設計師可以使用“儲存器到暫存器”這樣的操作方式(這種操作在複雜指令集計算機中很常見),來編寫程式而不需擔心會損失前端譯碼頻寬。微熔合可以整體提升指令從譯碼到退役的頻寬,同時節省電力。
過多的使用單微指令的x86指令來編寫程式會增加程式碼長度,降低傳統譯碼流水線的取指頻寬。
下面是一些微熔合的示例,可以被所有的譯碼器處理。
- 所有的寫存操作,包括寫立即數到儲存器。在處理器內部,寫存操作是兩個獨立的操作:儲存目標地址,和儲存資料。
例如,MOV [5000H], 1234H,這條指令將立即數1234H寫到儲存器地址5000H中(假設基地址是0)。沒有微熔合機制的情況下,這條指令會對應兩條微指令,儲存目標地址5000H,儲存資料1234H。有了微熔合機制,這條指令譯碼後只對應單條的複雜微指令。TODO:這個理解是否正確。
- 所有的讀存加計算操作型別(load + op)都可以微熔合為一條微指令,例如
ADDPS XMM9, OWORD PTR [RSP+40]; todo: how long for OWORD PTR?
FADD DOUBLE PTR [RDI+RSI*8];
XOR RAX, QWORD PTR [RBP+32]
- 所有的讀存加跳轉操作型別(load + jump),例如
JMP [RDI+200]
RET ; load instruction pointer and jump
- CMP/TEST指令使用儲存器定址和立即數
例如,CMP [5000H], 1234H
使用RIP相對定址的指令在如下的情況下無法進行微熔合:
- 有一個額外的立即數,例如
CMP [RIP+400], 27
MOV [RIP+3000], 142
- 控制流指令使用間接目標且目標是RIP相對定址方式,例如
JMP [RIP+500000000];
對於不能實施微熔合的情況,x86指令只能由複雜譯碼器進行譯碼,生成兩條微指令;這樣會稍微降低譯碼頻寬。
在64位程式碼中,RIP相對定址方式經常用於定址全域性資料。由於沒有微熔合機制,當移植32位程式到64位上時,頻繁訪問全域性資料的程式碼效能可能會有所下降。
Macro-Fusion
巨集熔合可以將兩條x86指令熔合,譯碼後只生成單條微指令。在Intel Core微架構中,這個硬體優化機制是有較大限制的,只能針對符合特定條件的指令對進行熔合。
- 第一條指令修改標誌暫存器且滿足一定條件(參下):
- Nehalem微架構:CMP, TEST
- Sandy Bridge微架構:CMP, TEST, ADD, SUB, AND, INC, DEC
- 具備巨集熔合條件的上述指令必須符合以下格式
- 第一個源/目標運算元是暫存器
注:TEST指令只有兩個源運算元;ADD指令第一個是目的運算元,第二個是源運算元;INC只有一個目的運算元。
-
-
- 第二個源運算元(如果存在)是以下任一:立即數,暫存器數,非RIP相對定址的儲存器數
-
- 第二條指令是條件轉移指令。下表描述了每條指令可以與之熔合的分支指令。
Instructions (2nd↓ \ 1st →) |
TEST |
AND |
CMP |
ADD |
SUB |
INC |
DEC |
JO/JNO |
Y |
Y |
N |
N |
N |
N |
N |
JC/JB/JAE/JNB |
Y |
Y |
Y |
Y |
Y |
N |
N |
JE/JZ/JNE/JNZ |
Y |
Y |
Y |
Y |
Y |
Y |
Y |
JNA/JBE/JA/JNBE |
Y |
Y |
Y |
Y |
Y |
N |
N |
JS/JNS/JP/JPE/JNP/JPO |
Y |
Y |
N |
N |
N |
N |
N |
JL/JNGE/JGE/JNL/JNG/JG/JNLE |
Y |
Y |
Y |
Y |
Y |
Y |
Y |
如果第一條指令結束於快取行的63位元組上(即快取行行尾),第二條條件分支指令起始於下一個快取行的0位元組上(即快取行行首),這兩條指令不可以做巨集熔合。
由於符合巨集熔合條件的指令對在各種型別的程式中都很常見,所以即便不重新編譯程式,巨集熔合機制也能帶來效能收益。
巨集熔合後的指令都只需要一次分發即可投入執行(因為只生成一條微指令)。這樣既降低了執行延遲,也節省了執行資源。同時,還可以獲得更高的重新命名和指令退役頻寬,增加虛擬儲存容量(即更高的儲存密度),以及用更少的位元位表示更多的操作,從而更加節能。