現代C C 編譯器有多智慧型?能做出什麼厲害的優化?

時間 2021-05-29 22:56:22

1樓:Xi Yang

弱爆了,連幫我把卷積自動「優化」成FFT加速的都做不到。

另外,如果你寫:

struct MyVec4i

// 使用處

MyVec4i v1(1,2,3,4);

MyVec4i v2(5 6 7 8);

MyVec4i result = v1 + v2;

MSVC:我特麼就是要往記憶體裡放。

2樓:原子筆

我把裡面的巨集展開成常數,那個函式在64位下是這樣的。

template

inline char* get_stack_base(char* prev_stack_base)else

}這個函式的效果是計算在給定函式引數個數下,需要怎樣調整棧頂指標,讓函式引數傳遞完畢後棧頂指標16位元組對齊。Cost 代表有多少個需要用棧傳遞的函式引數個數, 乙個引數的傳遞消耗8位元組棧。

這個計算方法並不複雜,標準的演算法就是else裡面的那個分支,即算清楚最終棧應該在哪個地方後,算清楚應該開銷多少棧,再減掉這個差值就行了。

但是如果仔細想想,Cost是偶數的時候,傳遞的開銷就是16的倍數,所以只需要把棧頂指標調整為16位元組對齊,那麼傳遞引數後自然也是16位元組對齊了。這也是if裡面那個分支的內容。

然而反彙編結果讓我大吃一驚:

哪怕是gcc O0 優化,在Cost是偶數的時候, else 分支的編譯結果和if也是一樣的!!!換而言之,我根本不需要去寫那個if分支來做編譯期選擇優化!!雖然我把這段留下來特別提醒我:

人在機器面前是多麼愚蠢的啊。。

原理其實就是:

y- (y&(x-1)) == y&(~(x-1)), 如果x是2的冪。在x是常數的時候左邊運算2次,右邊運算1次。

我估計編譯器像背圍棋定式一樣背了很多類似的定式吧。這個化簡類似位元運算中的因式分解。

3樓:Gomo Psivarh

利用C++11的range-based for loop語法可以實現類似python裡的range生成器,也就是實現乙個range物件,使得

for(

autoi:

range

(start

,stop

,step

))功能上相當於

for(

autoi=

start,i

+=step

)乙個簡單的實現如下:

#include

using

std::

cout

;class

range_iterator

range_iterator

&operator

++()

bool

operator!=(

const

range_iterator

&other

)int

&operator*()

private

:int

value

,step;};

class

range

range_iterator

begin

()range_iterator

end()

private

:int

start

,stop

,step;};

intmain

()system

("pause");}

用VS2015在release下編譯,看下反彙編:

可以發現根本沒有例項化過任何range和range_iterator物件,for迴圈裡的內容已經被優化成了for(int i = op; i < ed; i += step)

4樓:陳碩

乙份比較老的slides:

C C 主流編譯器為什麼不做成debug模式編譯的程式檢查陣列越界 溢位等錯誤,release模式編譯的程式不檢查?

看錯問題了 debug模式,VC可以檢查指向棧上物件的指標是否越界 對於new或者malloc出來的堆上的資料,就沒法判斷了 根源在於,C C 並沒有規範規定new或malloc出來的空間前後需要有什麼樣的標記,new甚至可以過載使得分配記憶體在自己預申請的空間內,或者這個空間甚至根本不是C C 系...

如何開發編譯器?

gitlab.gnome.org GNOME vala issues?milestone title 1.0 發展中的編譯器,正好可以做學習和研究。 Anges 說一下做過的編譯器前端部分 動態生成語法樹,詞法解析,主要利用狀態機,更高階點nfa轉行dfa,其實解析起來也沒有大家說的那麼難,會基本的...

編譯器是如何編譯自己的?

何源 比如你是馬雲,沒身份證 編譯器 之前怎麼證明自己是馬雲。那你得弄來一張名為馬雲的身份證 編譯器 問題來了,這張身份證怎麼來呢?你去找你爸要了戶口本 其他語言的編譯器 去派出所填寫了自己的資料 自己編譯器原始碼 辦理身份證,因為戶口本上你的名字是馬雲,派出所給了一張名為馬雲的身份證。從此,你不用...