簡體   English   中英

編譯器優化問題

[英]Compiler Optimizations Questions

  1. 編譯器消除重復的子表達式重新計算的一些方法是什么? 你如何跟蹤子表達式? 你如何識別重復的?
  2. 除了使用按位運算符之外,常見編譯器還使用了哪些強度降低技術?

對於1,您正在尋找的優化名稱是常見的子表達式消除(CSE)。 根據您的表示,這可能相當容易。 通常,編譯器將具有程序的一些中間表示,其中操作盡可能地被分解並且線性化。 因此,例如,表達式c = a * b + a * b可能會被細分為:

v1 = a * b
v2 = a * b
c = v1 + v2

因此,您可以通過查找具有相同運算符和操作數的操作來以非常低的級別執行CSE。 遇到重復項(在本例中為v2)時,將其所有實例替換為原始實例。 所以我們可以簡化上面的代碼:

v1 = a * b
c = v1 + v1

這通常假設您只分配一次變量(單個靜態賦值形式),但您可以在沒有該限制的情況下實現這樣的操作。 當您嘗試跨分支執行此優化時,這會變得更加復雜。 正如Zifre所提到的那樣,請考慮部分冗余消除。

無論哪種方式,您都會得到一些基本的改進,而您需要跟蹤的只是基本表達式。 您可能希望更進一步,尋找算術身份。 例如, a * bb * a相同。 此外, x * (y + z) = x * y + x * z 這使得您的優化變得更加復雜,並且不太清楚它會給您帶來如此多的性能提升。 有趣的是,CSE優化的大部分好處來自於數組訪問等地址計算,您不需要像上面那樣復雜的身份。

對於2,有用的強度降低實際上取決於您編譯的體系結構。 通常這只涉及將乘法和除法轉換為移位,加法和減法。

我強烈推薦這些主題的兩個印刷參考:

  1. Steven S. Muchnick的高級編譯器設計與實現
  2. 構建 Robert Morgan 的優化編譯器

Muchnick的書是正式的,但是非常易讀,並且對所有重要的優化技術都有很好的描述。 摩根書籍具有更多動手實踐的感覺,並且將成為專注於優化技術的編譯器項目的重要基礎。 這兩本書都沒有太多關於詞匯分析或解析的說法,因此假定這些科目的知識。

  1. 我相信很多編譯器都使用SSAPRE(靜態單一賦值部分冗余消除)來消除重復的表達式。 這要求代碼采用SSA形式 ,允許更多優化。

  2. 我不太確定這個,但看看這個LLVM通行證列表 LLVM是編譯器的優化IR,通常比GCC更快。 每個傳球都有一個小的解釋。 如果您需要更多信息,請查看這些傳遞的LLVM源。 它是用C ++編寫的,但非常干凈且易於理解。

編輯:順便說一句,如果您正在開發編譯器,我強烈推薦LLVM,它非常易於使用並生成高度優化的代碼。

要在建議列表中再添一本書,請查看Henry S. Warren撰寫的“Hacker's Delight” 這是優化常見操作的技術概要,例如將整數除法轉換為乘法。

您正在尋找部分冗余消除(PRE)。 CSE(來自其他答案)和循環不變的代碼運動都包含在PRE中。 (PRE的變體是Lazy Code Motion,我認為這是最佳的)。

查看Keith Cooper的講義 ,這些講稿似乎很好地描述了這些技巧。

不要使用SSAPRE。 AFAIK,這需要一種特殊形式的SSA,稱為HSSA,它有一些缺點:

  • 它非常復雜
  • 它需要全局值編號(因此SSAPRE不提供值編號,因為它預期已經存在)。
  • 如果您的語言不支持指向堆棧變量的指針(如果它支持,則停止編寫您自己的分析並使用LLVM或gcc),它不會提供任何內容。
  • gcc使用HSSA一段時間了,但他們已經離開了它。
  • LLVM對它進行了實驗,但是AFAIK他們不再使用它了。

編輯:

Muchnick的書有一個詳細的描述,它的另一個答案相關聯。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM