C/C++コンパイラの最適化を賢く使いこなす:CheckIPOSupportedモジュールでIPO/LTOを有効化する


CMakeモジュール「CheckIPOSupported」は、プロジェクトで使用しているコンパイラがインタープロシージャル最適化(IPO)またはリンクタイム最適化(LTO)をサポートしているかどうかを判定するモジュールです。IPO/LTOは、複数のソースファイルを単一のモジュールに統合し、コンパイルとリンクの段階でより多くの最適化を行うことで、プログラムのパフォーマンスを向上させる技術です。

使い方

このモジュールを使用するには、以下のコマンドをCMakeLists.txtファイルに追加します。

check_ipo_supported()

このコマンドは、以下の変数を設定します。

  • CMAKE_LTO_SUPPORTED: コンパイラがLTOをサポートしているかどうかを示すブール値。
  • CMAKE_IPO_SUPPORTED: コンパイラがIPOをサポートしているかどうかを示すブール値。

オプション

以下のオプションを使用して、このモジュールの動作を制御できます。

  • RESULT: IPO/LTOがサポートされているかどうかを格納する変数を指定します。
  • LANGUAGES: チェックするプログラミング言語を指定します。デフォルトはC、C++、Fortranです。

以下の例は、C++コンパイラがIPOをサポートしているかどうかを判定し、その結果をMY_IPO_SUPPORTED変数に格納します。

check_ipo_supported(LANGUAGES CXX RESULT MY_IPO_SUPPORTED)

if(MY_IPO_SUPPORTED)
  message(STATUS "C++ compiler supports IPO.")
else()
  message(STATUS "C++ compiler does not support IPO.")
endif()

詳細

このモジュールの詳細については、以下のドキュメントを参照してください。

  • IPO/LTOは、プログラムのパフォーマンスを向上させる可能性がありますが、必ずしもすべてのプログラムで効果があるわけではありません。
  • IPO/LTOを使用すると、コンパイルとリンクにかかる時間が長くなる場合があります。
  • IPO/LTOは、すべてのコンパイラでサポートされているわけではありません。


check_ipo_supported(LANGUAGES CXX)

if(CMAKE_IPO_SUPPORTED)
  message(STATUS "C++ compiler supports IPO.")
  set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON)
else()
  message(STATUS "C++ compiler does not support IPO.")
endif()

例2:CとC++コンパイラがIPOをサポートしているかどうかを判定し、その結果を変数に格納する

set(MY_C_IPO_SUPPORTED FALSE)
set(MY_CXX_IPO_SUPPORTED FALSE)

check_ipo_supported(LANGUAGES C RESULT MY_C_IPO_SUPPORTED)
check_ipo_supported(LANGUAGES CXX RESULT MY_CXX_IPO_SUPPORTED)

if(MY_C_IPO_SUPPORTED)
  message(STATUS "C compiler supports IPO.")
  set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_C ON)
endif()

if(MY_CXX_IPO_SUPPORTED)
  message(STATUS "C++ compiler supports IPO.")
  set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_CXX ON)
endif()

例3:オプションを使用して、CheckIPOSupportedモジュールの動作を制御する

check_ipo_supported(LANGUAGES CXX RESULT MY_IPO_SUPPORTED CACHE MY_IPO_SUPPORTED_CACHE RESULTS_VARIABLE MY_IPO_SUPPORTED_OUTPUT)

message(STATUS "IPO support check output:")
message(STATUS "${MY_IPO_SUPPORTED_OUTPUT}")

if(MY_IPO_SUPPORTED)
  message(STATUS "C++ compiler supports IPO.")
else()
  message(STATUS "C++ compiler does not support IPO.")
endif()
  • 各例では、モジュールの結果を使用して、プロジェクトの設定を調整しています。
  • 各例では、異なるオプションを使用してモジュールを呼び出しています。
  • 上記の例は、CMakeモジュール「CheckIPOSupported」の使用方法を示しています。
  • 実際のプロジェクトでは、必要に応じてコードを変更する必要があります。


代替方法

以下に、CheckIPOSupportedの代替方法をいくつか紹介します。

コンパイラ固有のフラグを使用する

多くのコンパイラは、IPO/LTOを有効にするためのフラグを提供しています。これらのフラグを使用して、プロジェクトの設定を手動で調整することができます。

例:GCCの場合

set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fipa-cp -flto")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fipa-cp -flto")

例:Clangの場合

set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fipa-cp -flto")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fipa-cp -flto")

CMakeのFindPackageモジュールを使用する

一部のコンパイラは、CMakeのFindPackageモジュールを使用して検出することができます。これらのモジュールは、コンパイラがIPO/LTOをサポートしているかどうかを判定するための情報を提供することがあります。

例:Intelの場合

find_package(Intel CXX)

if(INTEL_CXX_COMPILER)
  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${INTEL_CXX_COMPILER_FLAGS} -ipo")
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${INTEL_CXX_COMPILER_FLAGS} -ipo")
endif()

カスタムモジュールを作成する

上記の方法でうまくいかない場合は、カスタムモジュールを作成することができます。このモジュールは、コンパイラがIPO/LTOをサポートしているかどうかを判定するための独自ロジックを実装することができます。

コンパイラのドキュメントを参照する

コンパイラのドキュメントには、IPO/LTOを有効にする方法に関する情報が含まれている場合があります。

  • カスタムモジュールを作成する場合は、プログラミング言語に関する十分な知識が必要です。
  • コンパイラ固有のフラグやFindPackageモジュールを使用する場合は、コンパイラのドキュメントを参照する必要があります。
  • 上記の代替方法は、すべてのコンパイラで利用できるとは限りません。