Renesas Synergy™

FAQ 1008081 : for / while ループを goto のループに変形する記述例は?

回答

CA850は、for や while のように最初に条件判断の式のあるループに対して、 次のイメージ図のように条件判断の式を2回生成します。
このようなループの変形は、Cコンパイラの最初のフェーズであるフロントエンド(構文解析部) によって行われますが、これはその後の最適化によって最初の条件判断が削除されることが多く、 実行速度向上の点ではこのように変形するのが有利であるためです。
ところが、削除されなかった場合、コード・サイズの面では冗長となります。


forループ

    for (文1; 式2; 文3) {
        ループ・ボディ
    }

    文1;
    if (式2) {
        do {
            ループ・ボディ
            文3;
        } while (式2) ;
}


whlieループ

    while (式1) {
        ループ・ボディ
    }
    if (式1) {
        do {
            ループ・ボディ
        } while (式1) ;
    }


したがって、1回目の条件判断の式が最適化により削除されない場合には、以下のように goto で構成されるループに変形することで、条件判断の式を1個に減らすことができます。


forループ

    文1;
loop_bgn:
    if (! 式2) goto loop_end;
    ループ・ボディ
    文3;
    goto loop_bgn;
loop_end:


whileループ

loop_bgn:
    if (! 式1) goto loop_end;
    ループ・ボディ
    goto loop_bgn;
loop_end:

 

 

変更前   変更後 (2byte減 ※)
    for (i = 0; i < s; ++i) {
        array[i] = array[i+1];
    }
    i = 0;
bgn_loop:
    if (i >= s) goto end_loop;
    array[i] = array[i+1];
    ++i;
    goto bgn_loop;
end_loop:


※削減量は例に関するものであり、個々のケースにより異なります。

 


ソースを変更した結果、出力命令が減少し、高速化もされる場合があります。



ソース変更を行う際には、次のような点に注意してください。

  • ソース変更によりレジスタの使用状況が変わるため、意図しない箇所において、 それまで最適化されずに残っていたレジスタ転送が削除されたり、 逆に、最適化が効かなくなって冗長なレジスタ転送が残ったりする可能性があります。
  • テンポラリ変数を追加することにより、新たなレジスタ変数用レジスタが使用されるようになり、それに伴い、関数の入口/出口でそのレジスタの退避/復帰が追加されることがあります。この場合、退避/復帰のコード分(8バイト)だけコード・サイズが増加します。

 

適用製品

V850用コンパイラパッケージ [CA850]
他にご質問がございましたら、リクエストを送信してください