SSブログ

continue 文の次に実行されるのは? [PSoC]このエントリーを含むはてなブックマーク#

本日のお題

Twitterで、お題をいただきました。 これは、いっちょ試してみなくては。 題材に取り上げたのは、 Cortex-M0 搭載の PSoC 4 M-Series です。

GCC の場合

まず、 PSoC Creator のデフォルトツールチェインである GCC で試しました。 使用したコードは以下の通りです。

int main(void) {
    CyGlobalIntEnable; /* Enable global interrupts. */

    for (;;) {
        int i;
        for (i = 0; i < 10; ++i) {
            if (i == 0) continue;
        }
    }
}

for 行の中に変数宣言が入れられないので、外で宣言しています。 あれ、もしかしたら、これは C のお題じゃなかったのかな? 気にせず、 LST ファイルを見てみます。

  30 0000 62B6     		CPSIE   i
  33              	.L4:
  37 0002 0023     		mov	r3, #0
  38 0004 00E0     		b	.L2
  40              	.L3:
  42 0006 0133     		add	r3, r3, #1
  44              	.L2:
  46 0008 092B     		cmp	r3, #9
  47 000a FCDD     		ble	.L3
  48 000c F9E7     		b	.L4

変数 i は、 r3 に割り当てられています。 i を 0 と比較する部分は、存在しません。 すでに最適化されてしまっているようです。

continue 文の次に実行されるものは、そもそも if 文さえ存在しないので、問い自体が無意味である。

最適化しない GCC の場合

この結論じゃ面白くないので、最適化されないように -O0 オプションを付けました。

  28 0000 80B5     		push	{r7, lr}
  32 0002 82B0     		sub	sp, sp, #8
  34 0004 00AF     		add	r7, sp, #0
  38 0006 62B6     		CPSIE   i
  41              	.L5:
  44 0008 0023     		mov	r3, #0
  45 000a 7B60     		str	r3, [r7, #4]
  46 000c 06E0     		b	.L2
  47              	.L4:
  49 000e 7B68     		ldr	r3, [r7, #4]
  50 0010 002B     		cmp	r3, #0
  51 0012 00D1     		bne	.L3
  52 0014 C046     		mov	r8, r8
  53              	.L3:
  55 0016 7B68     		ldr	r3, [r7, #4]
  56 0018 0133     		add	r3, r3, #1
  57 001a 7B60     		str	r3, [r7, #4]
  58              	.L2:
  60 001c 7B68     		ldr	r3, [r7, #4]
  61 001e 092B     		cmp	r3, #9
  62 0020 F5DD     		ble	.L4
  65 0022 F1E7     		b	.L5

すると、変数をレジスタに割り当てる事もしないコンパイル結果となりました。 i を 0 と比較する部分は、50行目にあります。 その後、51行目の "bne" で条件分岐を行います。 continue 文に相当するのは、52行目の "mov r8, r8" です。 その後は、55行目から始まる ++i が実行されます。 つまり、 continue 文の次に実行されるのは、 "++i" であるという事がわかりました。

continue 文の次に実行されるものは、 ++i である。

MDK-ARM の場合

同じプロジェクトを MDK-ARM でコンパイルしてみました。

0x000006E4 BF00      NOP      
0x000006E6 B662      CPSIE    I
0x000006E8 BF00      NOP      
0x000006EA BF00      NOP      

0x000006EC 2000      MOVS     r0,#0x00
0x000006EE E004      B        0x000006FA

0x000006F0 2800      CMP      r0,#0x00
0x000006F2 D100      BNE      0x000006F6
0x000006F4 E000      B        0x000006F8

0x000006F6 BF00      NOP      
0x000006F8 1C40      ADDS     r0,r0,#1

0x000006FA 280A      CMP      r0,#0x0A
0x000006FC DBF8      BLT      0x000006F0

0x000006FE E7F5      B        0x000006EC

機能制限版では、 LST ファイルが出力されないようなので、デバッガの "Disassembly" ウィンドウから取ってきました。 変数 i は、 r0 に割り当てられています。

if 文は 0x000006F0 番地にあります。 continue 文に相当するのは、 0x000006F4 番地の "B 0x000006F8" です。 分岐先の 0x000006F8 番地には、 ++i があります。

continue 文の次に実行されるものは、 ++i である。

IAR Embedded Workbench の場合

IAR のコンパイラでも、同じようにコンパイルしてみました。

   \                     main: (+1)
   \   00000000   0xB500             PUSH     {LR}

   \   00000002   0xB662             CPSIE   i
   \                     ??main_0: (+1)
   \   00000004   0x2000             MOVS     R0,#+0
   \                     ??main_1: (+1)
   \   00000006   0x280A             CMP      R0,#+10
   \   00000008   0xDAFC             BGE      ??main_0
   \   0000000A   0x2800             CMP      R0,#+0
   \                     ??main_2: (+1)
   \   0000000C   0x1C40             ADDS     R0,R0,#+1
   \   0000000E   0xE7FA             B        ??main_1

変数 i は、 R0 レジスタに割り当てられています。 変数 i と 0 を比較する部分は、 0000000A 番地の "CMP R0,#+0" です。 しかし、比較をしているだけで後に続く条件分岐が見当たりません。 次に実行されるのは、 0000000C 番地の ++i です。

continue 文に相当する部分が存在しないが、結果的に次に実行されるものは、 ++i である。

最適化をがんばったら

これまでは、 "-O0" オプションで最適化を抑制していました。 普通は、多少の最適化を行わせますので、ためしに GCC の再弱最適化オプションである "-O1" を使ってコンパイルさせてみました。

  30 0000 62B6     		CPSIE   i
  33              	.L2:
  35 0002 FEE7     		b	.L2

すると、最適化の結果、何も残りませんでした。 後にあるのは、一番外側の無限ループのみです。

最適化されると、 for 文がまるごと省略される。

関連商品

PSoC 4200M CY8CKIT-043 Prototyping Kit

PSoC 4200M CY8CKIT-043 Prototyping Kit

  • 出版社/メーカー: スイッチサイエンス
  • メディア: エレクトロニクス

nice!(0)  コメント(0)  トラックバック(0)  このエントリーを含むはてなブックマーク#

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

トラックバック 0

トラックバックの受付は締め切りました

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。