🐥
C言語でforループ内にifが入る場合の挙動をアセンブリレベルで確認する
サマリ
C言語で通常のfor文、ifを内部に入れたfor文、最適化オプションを入れたもののアセンブリレベルでの比較を行いました。
マシンスペック
MacBook Air M2 arm64
1. 通常のforループの挙動
まずは通常のforループの挙動です。
単純な加算を行います。
#include <stdio.h>
int main() {
int sum = 0;
for (int i = 0; i < 100; i++) {
sum += i;
}
printf("%d\n", sum);
return 0;
}
下記のコマンドで、コンパイルしてアセンブリの内容が確認できます。
gcc -S -o simple_loop.s simple_loop.c
cat simple_loop.s
下記が出力結果です。
.section __TEXT,__text,regular,pure_instructions
.build_version macos, 14, 0 sdk_version 14, 4
.globl _main ; -- Begin function main
.p2align 2
_main: ; @main
.cfi_startproc
; %bb.0:
sub sp, sp, #48
.cfi_def_cfa_offset 48
stp x29, x30, [sp, #32] ; 16-byte Folded Spill
add x29, sp, #32
.cfi_def_cfa w29, 16
.cfi_offset w30, -8
.cfi_offset w29, -16
stur wzr, [x29, #-4]
stur wzr, [x29, #-8]
stur wzr, [x29, #-12]
b LBB0_1
LBB0_1: ; =>This Inner Loop Header: Depth=1
ldur w8, [x29, #-12]
subs w8, w8, #100
cset w8, ge
tbnz w8, #0, LBB0_4
b LBB0_2
LBB0_2: ; in Loop: Header=BB0_1 Depth=1
ldur w9, [x29, #-12]
ldur w8, [x29, #-8]
add w8, w8, w9
stur w8, [x29, #-8]
b LBB0_3
LBB0_3: ; in Loop: Header=BB0_1 Depth=1
ldur w8, [x29, #-12]
add w8, w8, #1
stur w8, [x29, #-12]
b LBB0_1
LBB0_4:
ldur w9, [x29, #-8]
; implicit-def: $x8
mov x8, x9
mov x9, sp
str x8, [x9]
adrp x0, l_.str@PAGE
add x0, x0, l_.str@PAGEOFF
bl _printf
mov w0, #0
ldp x29, x30, [sp, #32] ; 16-byte Folded Reload
add sp, sp, #48
ret
.cfi_endproc
; -- End function
.section __TEXT,__cstring,cstring_literals
l_.str: ; @.str
.asciz "%d\n"
.subsections_via_symbols
2. forループの中にifを入れた場合
次に、forの中にif文を入れて条件分岐を追加した場合です。
偶数の時に加算するようにしてみました。
#include <stdio.h>
int main() {
int sum = 0;
for (int i = 0; i < 100; i++) {
if (i % 2 == 0) {
sum += i;
}
}
printf("%d\n", sum);
return 0;
}
アセンブリファイルを確認します。
gcc -S -o loop_if.s loop_if.c
cat loop_if.s
.section __TEXT,__text,regular,pure_instructions
.build_version macos, 14, 0 sdk_version 14, 4
.globl _main ; -- Begin function main
.p2align 2
_main: ; @main
.cfi_startproc
; %bb.0:
sub sp, sp, #48
.cfi_def_cfa_offset 48
stp x29, x30, [sp, #32] ; 16-byte Folded Spill
add x29, sp, #32
.cfi_def_cfa w29, 16
.cfi_offset w30, -8
.cfi_offset w29, -16
stur wzr, [x29, #-4]
stur wzr, [x29, #-8]
stur wzr, [x29, #-12]
b LBB0_1
LBB0_1: ; =>This Inner Loop Header: Depth=1
ldur w8, [x29, #-12]
subs w8, w8, #100
cset w8, ge
tbnz w8, #0, LBB0_6
b LBB0_2
LBB0_2: ; in Loop: Header=BB0_1 Depth=1
ldur w8, [x29, #-12]
mov w10, #2
sdiv w9, w8, w10
mul w9, w9, w10
subs w8, w8, w9
subs w8, w8, #0
cset w8, ne
tbnz w8, #0, LBB0_4
b LBB0_3
LBB0_3: ; in Loop: Header=BB0_1 Depth=1
ldur w9, [x29, #-12]
ldur w8, [x29, #-8]
add w8, w8, w9
stur w8, [x29, #-8]
b LBB0_4
LBB0_4: ; in Loop: Header=BB0_1 Depth=1
b LBB0_5
LBB0_5: ; in Loop: Header=BB0_1 Depth=1
ldur w8, [x29, #-12]
add w8, w8, #1
stur w8, [x29, #-12]
b LBB0_1
LBB0_6:
ldur w9, [x29, #-8]
; implicit-def: $x8
mov x8, x9
mov x9, sp
str x8, [x9]
adrp x0, l_.str@PAGE
add x0, x0, l_.str@PAGEOFF
bl _printf
mov w0, #0
ldp x29, x30, [sp, #32] ; 16-byte Folded Reload
add sp, sp, #48
ret
.cfi_endproc
; -- End function
.section __TEXT,__cstring,cstring_literals
l_.str: ; @.str
.asciz "%d\n"
.subsections_via_symbols
3. 最適化オプションを付与してみる
最適化オプションを付与して、2の内容をコンパイルして同様に確認してみます。
gcc -O2 -S -o loop_if_optimized.s loop_if.c
cat loop_if_optimized.s
結果は以下の通りです。
.section __TEXT,__text,regular,pure_instructions
.build_version macos, 14, 0 sdk_version 14, 4
.globl _main ; -- Begin function main
.p2align 2
_main: ; @main
.cfi_startproc
; %bb.0:
sub sp, sp, #32
.cfi_def_cfa_offset 32
stp x29, x30, [sp, #16] ; 16-byte Folded Spill
add x29, sp, #16
.cfi_def_cfa w29, 16
.cfi_offset w30, -8
.cfi_offset w29, -16
mov w8, #2450
str x8, [sp]
Lloh0:
adrp x0, l_.str@PAGE
Lloh1:
add x0, x0, l_.str@PAGEOFF
bl _printf
mov w0, #0
ldp x29, x30, [sp, #16] ; 16-byte Folded Reload
add sp, sp, #32
ret
.loh AdrpAdd Lloh0, Lloh1
.cfi_endproc
; -- End function
.section __TEXT,__cstring,cstring_literals
l_.str: ; @.str
.asciz "%d\n"
.subsections_via_symbols
Discussion