Fuzix-Compiler-Kitの6800用コンパイラ(9) peep hole optimizer(2)

BASICMASTER, 昔のパソコン

EtchedPixels/Fuzix-Compiler-Kit: Fuzix C Compiler ProjectのCコンパイラ付属のpeephole optimizer (のぞき穴的最適化プログラム)の話の続き。

簡単な最適化でどれぐらい速くなるか、確認してみよう。

テストプログラムその1

ASCII誌に掲載されていたベンチマークテストNo.7をCに書き換えたもの。元々はkilobaud誌に掲載されていたものです。元々がBASICなのでgotoでloopを回しています。

cpu_counter() は、それまでに実行したCPUサイクルを表示する関数。common.h で定義しています。


#include	"common.h"

void
sub()
{
}

int main(int argc, char *argv[])
{
	int	k=0;
	int l;
	int a;
	int m[6];

	cpu_counter();
L:	k=k+1;
	a=k/2*3+4-5;
	sub();
	for(l=1; l<=5; l++){
		m[l]=0;
	}
	if(k<1000) goto L;

	cpu_counter();
    return 0;
}

これを現時点(2024/12/17)のFuzix C Compuler 6800用で走らせてみます。

本体部分の実行サイクルは 1,327,055 で、1MHzの6800だと1.3秒、ベーシックマスターだと1.8秒ぐらいかかります。


../emu6800 6800 9997-bench7 9997-bench7.map
CPU cycles = 154
CPU cycles = 1327209
0

プログラムを見ればわかるように、時間がかかりそうなのは二重ループの内側で、外が1000回・中が5回ループするので5000回実行されます。

ここのオブジェクトコードを見てみましょう。 m[l]=0; の行。

素直に l を2倍して、スタックポインタの値と足して、配列要素の値を求めています。冗長ですが、6800だとどうしてもこうなってしまう。最適化の余地はあまりなさそうです。

(ループ変数 l が 1-5 までなので、ldb 3,x / lslb だけにする手はありますが、peephole optimizerの範疇(はんちゅう)を超えてしまいます)。ここは そのままにしておきます。


	tsx
	ldb 3,x
	lda 2,x
	lslb
	rola
	sts @tmp
	addb @tmp+1
	adca @tmp
	addb #7
	adca #0
	staa @tmp
	stab @tmp+1
	ldx @tmp
	clr 1,x
	clr 0,x

ループ判定を見てみます。for(l=1; l<=5; l++){ の l<=5 の部分。 l と 5を比較するのに、l をスタックに積んで 5 をAccABに入れて、サブルーチンを呼んでいます。直接比較して分岐すれば速くなりそうです。


	tsx
	ldb 3,x
	lda 2,x
	pshb
	psha
	clra
	ldab #5
	jsr __cclteq
;
	jeq L31_b
	jmp L31_n

rules.6800に下記のコードを追加します。分岐ラベルを %2_%3 の形にしているのは、関係演算の結果を0/1にしない場合だけを最適化したいからです。jeq %2 とするとバグります。


        pshb
        psha
        clra
        ldab %1
        jsr __cclteq
;
        jeq %2_%3
=
        subb %1
        sbca #0
        jgt %2_%3
        jlt M%M_cc      ; jsr __cclteq
        tstb
        jne %2_%3
M%M_cc:

再度 実行。867055サイクルになりました。元の65%。ずいぶん速くなります。


../emu6800 6800 9997-bench7 9997-bench7.map
CPU cycles = 154
CPU cycles = 867209
0



peephole optimizeは、使いすぎるとデバッグがしづらくなりますし、コンパイラが出力するコードが変わったらやり直しです。

どうしても速くしたい・短くしたいプログラムがあるときだけ使いましょう(そもそも、その場合は6800用にはしないか…)


リンク