概要
g++ ってどんなコードを吐いているのか?
前の pomera gcc で thumb コードが吐かれていたので、ラズパイ3B+ の g++ で出力しているコードを確認しよう。
環境
ラズパイ3B+ の CPU は Cortex-A53 (ARMv8) である。
まず、試しに cpuinfo を覗いてみる。
cpuinfo
$ cat /proc/cpuinfo
processor : 0
model name : ARMv7 Processor rev 4 (v7l)
BogoMIPS : 38.40
Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm crc32
(以下略)
テスト
古い ARM 32bit では 整数除算命令がなく、新しめの ARM 32bit ではハードウェア除算命令(sdiv/udiv)があるので、これが利用されているか見てみる。
テストコード
divtest.cpp
int div(int a, int b)
{
return a / b;
}
そのまま -O2
何も考えず -O2 のみ
コンパイル
$ g++ -O2 -S -c divtest.cpp
結果
divtest.s
_Z3divii:
.fnstart
.LFB0:
@ args = 0, pretend = 0, frame = 0
@ frame_needed = 0, uses_anonymous_args = 0
push {r4, lr}
bl __aeabi_idiv
pop {r4, pc}
.cantunwind
.fnend
まぁ、CRT (__aeabi_idiv 関数)を呼びますよねー デスヨネー
CPU を指定 -mcpu=cortex-a53
Cortex-A53 を指定する
コンパイル
$ g++ -O2 -S -c divtest.cpp -mcpu=cortex-a53
結果
divtest.s
_Z3divii:
.fnstart
.LFB0:
@ args = 0, pretend = 0, frame = 0
@ frame_needed = 0, uses_anonymous_args = 0
@ link register save eliminated.
sdiv r0, r0, r1
bx lr
.cantunwind
.fnend
ハードウェア除算 (sdiv) を使いますよねー デスヨネー
-march
march でどうなるか? (コアによって ハードウェア除算があったりなかったりするので)
オプション | 結果 |
---|---|
-march=armv7 | __aeabi_idiv |
-march=armv7-a | __aeabi_idiv |
-march=armv8-a | sdiv |
ARMv8 までいくと全部除算命令があるってことかな?
-march=native
ラズパイ3B+では armv8-a として出力されました
結果
.arch armv8-a
.arch_extension crc
.file "divtest.cpp"
結論
プロジェクトにもよるけど、ラズパイ用のアプリならセルフ ビルドだろうから -march=native をつけてあげるといいのかなー?