編譯器與程式碼產生

指令選擇(instruction selection)

最佳化器的 IR 講的是抽象操作——加、乘、載入、比較——不綁定任何單一晶片。但真實處理器有一份特定、往往古怪的指令菜單,有時一個指令一次做好幾個抽象操作。指令選擇就是後端為每一塊 IR 挑出「用目標處理器哪些真正的機器指令來實現它」的步驟。

把它想成把抽象 IR 對目標的指令集做樣式比對。選擇器檢視 IR 操作的樣式,找出產生相同效果的最佳機器指令(或短序列)。它往往能把好幾個抽象操作融合成一個真正的指令:在 x86-64 上,陣列位址的抽象樣式 base + index * 4 + offset 對應到一個帶複雜定址模式的單一載入,而「先乘再加」在支援處可變成一個融合乘加(FMA)指令。目標是用機器指令覆蓋整份 IR,同時把總成本(週期數、程式碼大小)最小化,編譯器用成本驅動的樣式比對器(常由目標描述產生)來近似它。

它重要在於:同一份 IR 在不同處理器上對應到非常不同的指令——這個階段是後端為何依賴目標、以及同一份 C 在 x86 與 ARM 上編譯出不同組合語言的一大原因。當你讀反組譯、看到一個指令做了你原始碼裡看似兩個操作的事,那個融合就是指令選擇在運作。一個提醒:指令選擇受限於晶片實際提供什麼、以及正確性——它只能挑行為與 IR 意義完全相符的指令(包括旗標效果與溢位行為),所以一個「聰明」但細微不同的指令即使看起來更快也不能用。

// 陣列位址的 IR: base + i*4 + 8 // x86-64 指令選擇能把它全部摺進一個定址模式: mov eax, [rdi + rsi*4 + 8] ; 一個載入做完整個位址計算 // 浮點的「先乘再加」可變成一個 FMA: vfmadd...

好幾個抽象操作(乘法、兩個加法、一個載入)摺成一個帶複雜定址模式的 x86-64 指令。

選擇受精確等價約束:一個指令只有在其行為(包括旗標與溢位)符合 IR 意義時才能被選,所以一個看似更快但細微不同的指令是禁區——這也正是同一份 IR 在不同目標產生不同程式碼的原因。

又称
iselinstruction loweringpattern matching to machine instructions指令挑選