C 編譯器優化

2021-09-12 17:08:29 字數 1590 閱讀 7648

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 ...