1、volatile:
順序性:兩個包含volatile變數的指令,編譯後不可以亂序。注意是編譯後不亂序,但是在執行的過程中還是可能會亂序的,這點需要由其它機制來保證,例如memory- barriers。
不可優化性:volatile告訴編譯器,不要對這個變數進行各種激進的優化,甚至將變數直接消除,保證**中的指令一定會被執行。
2、nrv(named return value)優化:
函式返回乙個類,例如下:
class x;
x bar()
// 函式呼叫
x x2; // 這裡只是預留記憶體,並未呼叫初始化函式
bar(x2);
nrv優化後:
void bar(x& __result)
}彙編**:
movl $10, %ebx
subl $272, %esp #分配272位元組棧空間
leal -264(%ebp), %esi #取buf位址
.l2:
movl %esi, (%esp) #buf位址入棧
call test2 #呼叫test2
subl $1, %ebx
jne .l2 #迴圈未結束則跳到l2
該函式中,buf不會每次迴圈都生成,而是迴圈外生成,迴圈內不斷的使用。
4、算數式優化
a*2被編譯成a+a;無符號數a/2被編譯成a>>1;有符號數a/2。
5、memset函式優化
memset函式常用來初始化大段記憶體,但對小資料來說memset能否保持足夠高效呢?
看這段程式:
編譯成彙編:
movl $0, -24(%ebp) #設定s1
movl $0, -20(%ebp)
movl $0, -16(%ebp)
movl $0, -12(%ebp)
call test2 #呼叫test2
leal -8216(%ebp), %edx #設定s2
xorl %eax, %eax
movl %edx, %edi
movl $2048, %ecx
rep stosl
movl %edx, (%esp) #呼叫test2
call test2
movl %ebx, (%esp) #設定s3
movl $8193, 8(%esp)
movl $0, 4(%esp)
call memset
movl %ebx, (%esp) #呼叫test2
call test2
當資料長度比較小時(如s1是16位元組),memset被編譯成連續的賦值語句;當資料長度不大於8kb時(如s2),memset用串操作指令來實現;當資料長度大於8kb時(如s3),memset被編譯成函式呼叫。
串操作類指令:在記憶體乙個儲存區域連續存放著若干個位元組(或字)資料,這樣一組資料稱為「資料串」(高階語言視為陣列)。若每個資料是乙個位元組,稱「位元組串」;若是字,則稱「字串」。串操作指令可以用來實現記憶體區域的資料串操作。串操作指令每次只處理資料串中的乙個資料,但與重複字首配合使用(重複字首+串操作指令),則可使操作重複進行(其執行過程相當於乙個迴圈程式的執行,重複次數由暫存器cx決定)。
C 編譯器優化
1 volatile 順序性 兩個包含volatile變數的指令,編譯後不可以亂序。注意是編譯後不亂序,但是在執行的過程中還是可能會亂序的,這點需要由其它機制來保證,例如memory barriers。不可優化性 volatile告訴編譯器,不要對這個變數進行各種激進的優化,甚至將變數直接消除,保證...
C 編譯器優化
正如在第一篇文章中提到的,編譯器可能通過對記憶體操作進行重新排序來優化 在 net framework 4.5 中,將 c 編譯為 il 的 csc.exe 編譯器並不執行大量的優化操作,因此該編譯器不會對記憶體操作進行重新排序。但將 il 編譯為機器碼的實時 jit 編譯器實際上將執行一些對記憶體...
編譯器優化
常量摺疊 a 1 2 由於結果可預見,編譯器直接生成a 3 常量傳播a 1 若後續 沒有更改a,則編譯器將a直接用其值1代替 減少變數 對於x和y的比較,可以轉換成if i j x i2 y j 2 if x y 複寫傳播 類似於常量長傳,不過傳播的是變數 若後續 未修改a的值,則編譯器用m代替a ...