10

この質問は、GCC 5.1 Loop unrollingへのフォローアップの質問の一部です。

GCC のドキュメントによると、上記の質問に対する私の回答で述べたように、「完全なループ ピーリング (つまり、小さな一定回数の反復でループを完全に削除する)」-funroll-loopsなどのフラグをオンにします。したがって、このようなフラグが有効になっている場合、コンパイラは、これが特定のコードの実行を最適化すると判断した場合に、ループを展開することを選択できます。

それにもかかわらず、私のプロジェクトの 1 つで、関連するフラグが有効になっていない場合でも、 GCC がループをアンロールすることがあることに気付きました。たとえば、次の単純なコードを考えてみましょう。

int main(int argc, char **argv)
{
  int k = 0;
  for( k = 0; k < 5; ++k )
  {
    volatile int temp = k;
  }
}

でコンパイルすると-O1、ループが展開され、最新バージョンの GCC で次のアセンブリ コードが生成されます。

main:
        movl    $0, -4(%rsp)
        movl    $1, -4(%rsp)
        movl    $2, -4(%rsp)
        movl    $3, -4(%rsp)
        movl    $4, -4(%rsp)
        movl    $0, %eax
        ret

-fno-unroll-loops -fno-peel-loopsフラグが無効になっていることを確認するために追加でコンパイルした場合でも、GCC は予期せず、上記の例でループ展開を実行します。

この観察は、次の密接に関連した質問に私を導きます。この動作に対応するフラグが無効になっているにもかかわらず、GCC がループ展開を実行するのはなぜですか? アンロールは、無効になっている場合でも、コンパイラがループをアンロールする可能性がある他のフラグによっても制御され-funroll-loopsますか? GCC でループのアンローリングを完全に無効にする方法はあり-O0ますか?

興味深いことに、Clangコンパイラはここで期待どおりの動作をしており、-funroll-loops有効な場合にのみ展開を実行し、それ以外の場合は実行しないようです。

事前に感謝します。この問題に関する追加の洞察をいただければ幸いです。

4

1 に答える 1