日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
優(yōu)化C++代碼(3)常量合并

這篇文章講的是常量合并,這是VC++編譯器最簡單的優(yōu)化之一。  這種優(yōu)化,是指編譯器在編譯時(編譯期間)直接計算出表達式的結(jié)果,在生成的代碼中直接用計算結(jié)果替換表達式。 這樣就避免了程序在運行時執(zhí)行這些計算花費的成本。

靖宇網(wǎng)站制作公司哪家好,找成都創(chuàng)新互聯(lián)公司!從網(wǎng)頁設(shè)計、網(wǎng)站建設(shè)、微信開發(fā)、APP開發(fā)、響應(yīng)式網(wǎng)站等網(wǎng)站項目制作,到程序開發(fā),運營維護。成都創(chuàng)新互聯(lián)公司自2013年創(chuàng)立以來到現(xiàn)在10年的時間,我們擁有了豐富的建站經(jīng)驗和運維經(jīng)驗,來保證我們的工作的順利進行。專注于網(wǎng)站建設(shè)就選成都創(chuàng)新互聯(lián)公司。

下面是一個例子 APP.cpp文件中的main函數(shù):

 
 
 
  1. int main() { return 7 + 8; }

首先,關(guān)于這篇文章的一些須知:

  1. 我們將從命令行來構(gòu)建程序(而不是Visual Studio)
  2. 我們會使用Visual Studio 2012。 特別注意的是,這個版本的編譯器會產(chǎn)生x64位代碼(而不是已經(jīng)過時的x86架構(gòu))在64位機子上編譯。

如果你想要繼續(xù),請看下說明。實際上,你只需要從Visual Studio 列表里選擇一個正確的變體。

(注意:如果你正在使用Visual Studio Express上的免費編譯器,它僅僅只能運行在x86上,但是也會順利生成x64的代碼。對這個實驗同樣有用。)

我們可以通過命令 CL /FA App.cpp來構(gòu)建示例程序。用/FA開關(guān)創(chuàng)建一個輸出文件,用來保存編譯器生成的匯編代碼,可以輸入type App.asm來顯示:

 
 
 
  1. PUBLIC  main
  2. _TEXT   SEGMENT
  3. main    PROC
  4.         mov     eax, 15
  5.         ret     0
  6. main    ENDP
  7. _TEXT   ENDS
  8. END

有趣的是這條指令move ax,15—-僅僅將15賦值給寄存器EAX(根據(jù)x64調(diào)用標準的定義,x64函數(shù)將會設(shè)置一個int值,作為函數(shù)的結(jié)果,并返回給調(diào)用者)。編譯器運行期間并沒有發(fā)出 7加8的指令。就像下面這樣:

 
 
 
  1. PUBLIC  main
  2. _TEXT   SEGMENT
  3. main    PROC
  4.         mov     eax, 7
  5.         add     eax, 8
  6.         ret     0
  7. main    ENDP
  8. _TEXT   ENDS
  9. END

(注意看了,這兩段代碼的***一條指令,ret 0,是指將控制權(quán)返回給調(diào)用者,并從棧里彈出0個字節(jié)。不要被誤導認為是返回數(shù)值0給調(diào)用者?。?/p>

我猜到,你可能在想:這很好啊,但是哪個白癡會想到在代碼里寫 7+8 這樣的運算?的確,你是對的,但是編譯器會把這樣的結(jié)構(gòu)看成是有副作用的宏??戳讼旅娴睦?,你就會明白常量合并是一個很有用的優(yōu)化方法:

 
 
 
  1. #define SECS_PER_MINUTE  60
  2. #define MINUTES_PER_HOUR 60
  3. #define HOURS_PER_DAY    24
  4.  
  5. enum Event { Started, Stopped, LostData, ParityError };
  6.  
  7. struct {
  8.     int        clock_time;
  9.     enum Event ev;
  10.     char*      reason;
  11. }   Record;
  12.  
  13. int main() {
  14.     const int table_size = SECS_PER_MINUTE * MINUTES_PER_HOUR * HOURS_PER_DAY * sizeof Record;
  15.     // rest of program
  16. }

我們要創(chuàng)建一個足夠大的表保存每一秒的記錄,所以table_size就是表的大小,用字節(jié)表示。很容易查看變量table_size的匯編指令:

 
 
 
  1. mov     DWORD PTR table_size$[rsp], 1382400     ; 00151800H

這兒沒有乘法指令,60*60*24*16=1382400 是在編譯時計算的。

事實上,我們窺探下編譯器的內(nèi)部,會發(fā)現(xiàn)這種常量合并的運算非常簡單,它是由前端來執(zhí)行的。它并不需要后端優(yōu)化器笨重的提升能力。所以它總是存在的。不管你是開啟優(yōu)化(使用 /O2)或者關(guān)閉優(yōu)化(/Od)都沒什么區(qū)別—–該優(yōu)化總是自動執(zhí)行的。

不管表達式有多復雜,我們都能在編譯期間進行常量合并嗎?—事實上,前端可以處理任意的常量算術(shù)表達式(甚至包括上面提到的sizeof,只要它們在編譯時能被計算出來)和運算符(+ - * / % << >> ++ 和 –)。你甚至可以使用布爾值,邏輯運算符 和條件運算符if AND ?:。

有沒有常量合并需要后端優(yōu)化器的時候呢?當然有,看下面的例子:

 
 
 
  1. int bump(int n) { return n + 1; } 
  2.   
  3. int main() { return 3 + bump(6); } 

輸入命令cl /FA /Od App.cpp,會得到信息:不能優(yōu)化,謝謝!,輸入 App.asm,我們會得到:

 
 
 
  1. mov     ecx, 6
  2. call    ?bump@@YAHH@Z                           ; bump
  3. add     eax, 3

正如我們所預料的: ECX會保存***個參數(shù)6,根據(jù)x64調(diào)用約定,然后調(diào)用bump函數(shù),結(jié)果返回給EAX,然后EAX再加3。

我們來看看如果我們使用 cl /FA /O2 App.cpp 來進行優(yōu)化,會發(fā)生什么。

 
 
 
  1. mov eax,10

后端優(yōu)化器已經(jīng)識別到bump函數(shù)很小,可以包含到調(diào)用者里(我們在后面的章節(jié)將會講到這種優(yōu)化方法,叫做內(nèi)聯(lián)函數(shù))。它在編譯時就能夠估算出整個表達式的值,***只剩下一條單指令。很神奇,對吧?


當前標題:優(yōu)化C++代碼(3)常量合并
文章URL:http://www.dlmjj.cn/article/cospphh.html