我與海灣合作委員會的優化選項擺弄gcc的優化,發現這些行:與LEA
int bla(int moo) {
return moo * 384;
}
被翻譯這些:
0: 8d 04 7f lea (%rdi,%rdi,2),%eax
3: c1 e0 07 shl $0x7,%eax
6: c3 retq
我明白換擋表示由2乘法^ 7。第一行必須乘以3.
所以我完全被「lea」線困惑。是不是應該加載地址?
我與海灣合作委員會的優化選項擺弄gcc的優化,發現這些行:與LEA
int bla(int moo) {
return moo * 384;
}
被翻譯這些:
0: 8d 04 7f lea (%rdi,%rdi,2),%eax
3: c1 e0 07 shl $0x7,%eax
6: c3 retq
我明白換擋表示由2乘法^ 7。第一行必須乘以3.
所以我完全被「lea」線困惑。是不是應該加載地址?
lea (%ebx, %esi, 2), %edi
無非是計算ebx + esi*2
並將結果存儲在edi
。
即使lea
旨在計算和存儲的有效地址,它可以和它經常被用來作爲優化技巧上的東西是不是一個內存地址進行計算。
lea (%rdi,%rdi,2),%eax
shl $0x7,%eax
等同於:
eax = rdi + rdi*2;
eax = eax * 128;
而且,由於moo
爲rdi
,它eax
非常感謝! 我知道你可以用lea來做一些不會改變標誌的東西,但是這個...... – Banyoghurt 2013-05-02 13:59:42
存儲moo*384
這是在x86內核的標準優化技巧。 AGU地址生成單元是生成地址的處理器的子部分,能夠進行簡單的算術運算。它不是一個完整的ALU,但有足夠的晶體管來計算索引和縮放地址。添加和移位。 LEA,Load Load Address指令是調用AGU中的邏輯並計算簡單表達式的一種方法。
這裏的優化機會是AGU獨立於ALU運行。所以你可以得到超標量執行,同時執行兩條指令。
這實際上並不在您的代碼片段中發生,但如果在顯示的需要ALU的指令之前進行了計算,則會發生可能發生的。這是一個訣竅,只有在更簡單的cpu核心,486和奔騰年份上才真正實現。現代處理器有多個ALU,所以不再需要這個技巧。
還要注意,轉換通常比'IMUL'快;並且用換檔替代「乘以常數」也是許多CPU的通用優化。 – Brendan 2013-05-02 16:35:30
啓用它的精確GCC優化標誌是什麼(例如'-fuse-lea',暗示爲'-O3')。 – 2015-05-31 20:02:13
爲了完整性:地址操作數讀取的語法是:±d(A,B,C),它將被轉換成A±d + B * C – Banyoghurt 2013-05-02 14:04:05
順便說一句,唯一使用AGU的現代CPU用於' lea'是Intel Atom。在所有其他現代的CPU上,它都會運行一個ALU。但它仍然很有用,因爲它結合了多個操作,具有任意輸出寄存器,並且不會更改標誌。此外,這種格式(64位地址,32位結果)是64位模式下'lea'的最短編碼。 – harold 2013-05-02 18:19:55