C コードのループの展開

ループは、大半のプログラムに含まれている一般的な構文の 1 つです。ループの実行には多大な時間が費やされることが多いので、時間制限の厳しいループに注意を払うことを推奨します。

小規模なループを展開すると、コードサイズが増大しますが、パフォーマンスを向上できます。ループが展開されると、ループカウンタの更新頻度が低くなり、実行される分岐数が少なくなります。ループが数回しか繰り返されない場合は、ループを完全に展開して、ループオーバーヘッドを完全になくすことができます。コンパイラは、-O3 -Otime で自動的にループを展開します。それ以外の場合は、何らかの展開をソースコードで行う必要があります。

Note

ループを手動で展開すると、ループの自動再展開をはじめ、コンパイラによるループ最適化を妨げる場合があります。

ループ展開のメリットとデメリットは、Table 10 に示す 2 つのサンプルルーチンを使用して説明できます。どちらのルーチンも、最下位ビットを抽出してカウントし、シフトアウトさせることにより、シングルビットを効率的にテストします。

最初のルーチンでは、ビットをカウントするためにループが使用されます。2 番目のルーチンは、最初の実装を 4 回展開し、n の 4 シフト分を 1 つにまとめて最適化が適用されたものです。

頻繁に展開すると、最適化の機会が増えます。

Table 10. 未展開および展開されたビットカウントループを表す C コード

ビットカウントループ展開されたビットカウントループ
int countbit1(unsigned int n)
{
    int bits = 0;
    while (n != 0)
    {
        if (n & 1) bits++;
        n >>= 1;
    }
    return bits;
}
int countbit2(unsigned int n)
{
    int bits = 0;
    while (n != 0)
    {
        if (n & 1) bits++;
        if (n & 2) bits++;
        if (n & 4) bits++;
        if (n & 8) bits++;
        n >>= 4;
    }
    return bits;
}

Table 11 は、コンパイラによって生成されたマシンコードがTable 10の各実装例でどのように逆アセンブルされるかを示したものです。いずれの実装の C コードも、オプション -O2 を使用してコンパイルされています。

Table 11. 未展開および展開されたビットカウントループを表す逆アセンブリコード

ビットカウントループ展開されたビットカウントループ
countbit1 PROC
    MOV      r1, #0
    B        |L1.20|
|L1.8|
    TST      r0, #1
    ADDNE    r1, r1, #1
    LSR      r0, r0, #1
|L1.20|
    CMP      r0, #0
    BNE      |L1.8|
    MOV      r0, r1
    BX       lr
ENDP
countbit2 PROC
    MOV      r1, r0
    MOV      r0, #0
    B        |L1.48|
|L1.12|
    TST      r1, #1
    ADDNE    r0, r0, #1
    TST      r1, #2
    ADDNE    r0, r0, #1
    TST      r1, #4
    ADDNE    r0, r0, #1
    TST      r1, #8
    ADDNE    r0, r0, #1
    LSR      r1, r1, #4
|L1.48|
    CMP      r1, #0
    BNE      |L1.12|
    BX       lr
ENDP

ARM9 では、シングルビットをチェックするために、一番左の列に示すビットカウントループの逆アセンブリで 6 サイクルが必要となります。コードサイズはわずか 9 命令です。このビットカウントループの展開バージョンは、1 ビット当たりわずか平均 3 サイクルのペースで、1 回のループの繰り返しで一度に 4 ビットをチェックします。ただし、その代わりにコードサイズは増大し、15 命令になります。

Show/hide関連項目

Copyright © 2010 ARM. All rights reserved.ARM DUI 0472BJ
Non-ConfidentialID011811