如何使用設定檔導向最佳化建置 Clang 和 LLVM¶
簡介¶
PGO(設定檔導向最佳化)讓您的編譯器能夠根據程式碼的實際執行情況更好地最佳化程式碼。使用者報告指出,將此技術應用於 Clang 和 LLVM 可以減少整體編譯時間達 20%。
本指南將引導您完成如何使用 PGO 建置 Clang 的步驟,儘管它也適用於其他子專案,例如 LLD。
如果您想使用 PGO 建置其他軟體,請參閱 PGO 的終端使用者文件。
使用預先設定的 CMake 快取¶
請參閱 https://llvm.dev.org.tw/docs/AdvancedBuilds.html#multi-stage-pgo
使用腳本¶
我們在 utils/collect_and_build_with_pgo.py
提供了一個腳本。此腳本已在幾個 Linux 版本上測試過,並且需要 LLVM、Clang 和 compiler-rt 的 checkout。儘管名稱如此,它會執行四次 Clang 的完整建置,因此可能需要一段時間才能完成。請參閱腳本的 --help
以獲取更多關於如何執行它以及可用的不同選項的資訊。如果您想針對特定用例(例如,編譯特定的龐大軟體)充分利用 PGO,請務必閱讀以下關於「基準測試」選擇的部分。
請注意,此腳本僅在少數 Linux 發行版上進行了測試。一如既往,非常感謝您提供補丁以增加對其他平台的支持。:)
此腳本也支援 --dry-run
選項,這會使其印出重要的命令而不是執行它們。
選擇「基準測試」¶
當收集到的設定檔能代表使用者計劃如何使用編譯器時,PGO 的效果最佳。值得注意的是,如果您要以 ARM 為目標,那麼準確度極高的 llc 建置 x86_64 程式碼的設定檔並不是非常有幫助。
預設情況下,上述腳本會執行兩項操作以獲得穩固的覆蓋率。它
執行 Clang 和 LLVM 的所有 lit 測試,以及
使用 instrumented Clang 建置 Clang、LLVM 以及所有其他可用的 LLVM 子專案。
總之,這些應該為您提供
穩固的 C++ 建置覆蓋率,
良好的 C 建置覆蓋率,
出色的執行最佳化覆蓋率,
出色的主機架構後端覆蓋率,以及
一些其他架構的覆蓋率(如果其他架構是支援的後端)。
總而言之,這應該涵蓋 Clang 和 LLVM 的各種不同用途。如果您有非常特定的需求(例如,您的編譯器旨在為四個不同的平台編譯大型瀏覽器,或類似情況),您可能需要執行其他操作。這可以在腳本本身中配置。
使用 PGO 建置 Clang¶
如果您不喜歡使用腳本或 cmake 快取,本節將簡要介紹如何使用 PGO 建置 Clang/LLVM。
首先,您應該至少在本地 checkout LLVM、Clang 和 compiler-rt。
接下來,從高層次來看,您需要執行以下操作
建置標準的 Release Clang 和相關的 libclang_rt.profile 庫
使用您在上面建置的 Clang 建置 Clang,但要帶有 instrumentation
使用 instrumented Clang 生成設定檔,這包含兩個步驟
在代表使用者將如何使用所述工具的任務上執行 instrumented Clang/LLVM/lld/etc。
使用工具將上面生成的「raw」設定檔轉換為單個最終的 PGO 設定檔。
使用從基準測試收集的設定檔建置最終的 release Clang(以及您需要的任何其他二進制檔案)
更詳細的步驟
像平常一樣配置 Clang 建置。強烈建議您為此使用 Release 配置,因為它將用於建置另一個 Clang。由於您需要 Clang 和支援庫,因此您需要建置
all
目標(例如ninja all
或make -j4 all
)。如上所述配置 Clang 建置,但添加以下 CMake 參數
-DLLVM_BUILD_INSTRUMENTED=IR
– 這會使我們建置所有帶有 instrumentation 的內容。-DLLVM_BUILD_RUNTIME=No
– 一些專案在使用 profiling 建置時會有不良互動,並且不是必要的建置項目。此標誌會將它們關閉。-DCMAKE_C_COMPILER=/path/to/stage1/clang
- 使用我們在步驟 1 中建置的 Clang。-DCMAKE_CXX_COMPILER=/path/to/stage1/clang++
- 與上述相同。
在這個建置目錄中,您只需要建置
clang
目標(以及您的基準測試所需的任何支援工具)。
如上所述,這包含兩個步驟:收集設定檔資料,然後將其整理成有用的形式
使用在步驟 2 中生成的 Clang 建置您的基準測試。「標準」基準測試建議是在 instrumented Clang 的建置目錄中執行
check-clang
和check-llvm
,並使用您的 instrumented Clang 完整建置 Clang/LLVM。因此,再創建另一個建置目錄,並使用以下 CMake 參數-DCMAKE_C_COMPILER=/path/to/stage2/clang
- 使用我們在步驟 2 中建置的 Clang。-DCMAKE_CXX_COMPILER=/path/to/stage2/clang++
- 與上述相同。
如果您的使用者是 debug info 的愛好者,您可能需要考慮使用
-DCMAKE_BUILD_TYPE=RelWithDebInfo
而不是-DCMAKE_BUILD_TYPE=Release
。這將提供更好的 clang debug info 組件覆蓋率,但會花費更長的時間才能完成,並導致更大的建置目錄。建議使用您的 instrumented Clang 建置
all
目標,因為更高的覆蓋率通常更好。
您現在應該在
path/to/stage2/profiles/
中有一些*.profraw
檔案。您需要使用llvm-profdata
合併這些檔案(即使您只有一個!設定檔合併也會將 profraw 轉換為實際的設定檔資料)。這可以使用/path/to/stage1/llvm-profdata merge -output=/path/to/output/profdata.prof path/to/stage2/profiles/*.profraw
完成。
現在,建置您的最終 PGO 最佳化 Clang。為此,您需要將以下額外參數傳遞給 CMake。
-DLLVM_PROFDATA_FILE=/path/to/output/profdata.prof
- 使用上一步驟中的 PGO 設定檔。-DCMAKE_C_COMPILER=/path/to/stage1/clang
- 使用我們在步驟 1 中建置的 Clang。-DCMAKE_CXX_COMPILER=/path/to/stage1/clang++
- 與上述相同。
從這裡開始,您可以建置您需要的任何目標。
注意
您可能會在建置輸出中看到關於設定檔不匹配的警告。這些通常是無害的。若要消除它們,您可以將
-DCMAKE_C_FLAGS='-Wno-backend-plugin' -DCMAKE_CXX_FLAGS='-Wno-backend-plugin'
添加到您的 CMake 調用中。
恭喜!您現在擁有一個使用設定檔導向最佳化建置的 Clang,如果您願意,您可以刪除除了最終建置目錄之外的所有內容。
如果這對您來說效果良好,並且您計劃經常執行此操作,則可以進行一些輕微的最佳化:LLVM 和 Clang 有一個名為 tblgen 的工具,該工具在建置過程中建置和執行。雖然在步驟 3 中將其建置以獲得覆蓋率可能很好,但您的其他建置都不應從建置它中受益。您可以將 CMake 選項 -DLLVM_NATIVE_TOOL_DIR=/path/to/stage1/bin
傳遞給步驟 2 及之後的步驟,以避免這些無用的重新建置。