ひとり勉強会

ひとり楽しく勉強会

insn_operands_unification

オペランド融合。この最適化は現在はOFFになってるみたいです。一応ソースだけ読んでみました。

この関数は、ビルド時に定義ファイル"opt_operand.def"から自動生成されます。(自動生成スクリプトは"tool/insns2vm.rb"。)定義ファイルの中身はこんな感じで、

getlocal 2
getlocal 3
getlocal 4

setlocal 2
setlocal 3
setlocal 4

getdynamic *, 0
getdynamic 1, 0
...

1行が1個の融合命令に対応しています。例えば最初の行「getlocal 2」は、getlocal_OP_2 という融合命令を定義しています。この定義に対応して、insn_operands_unification 関数が自動生成されます(Makefileと同じディレクトリの、optinsn.incというファイルです)。

static INSN *
insn_operands_unification(INSN *insnobj){
#ifdef OPT_OPERANDS_UNIFICATION
  /* optimize rule */
  switch(insnobj->insn_id){

case BIN(getlocal):
  if(
    insnobj->operands[0] == INT2FIX(2)
  ){
    insnobj->insn_id = BIN(getlocal_OP_2);
    insnobj->operand_size = 0;
    break;
  }
  if(
    insnobj->operands[0] == INT2FIX(3)
  ){
    insnobj->insn_id = BIN(getlocal_OP_3);
    insnobj->operand_size = 0;
    break;
  }
  ...

getlocal命令に引数2を渡している箇所を、getlocal_OP_2 という専用命令に置き換える、という処理ですね。まだ読んでませんがたぶん実行時は、命令ごとにdispatchしてから、オペランドの必要な命令ではオペランドを読み取って、実際の処理…という流れになっているんだと思います。なので、よくあるオペランドについては固定した専用命令を作ってしまって、読み取り処理を省いた方が効率的になり得るのでしょう。かと言って全ての可能なオペランドについて全部融合命令を作ることはできませんから、よくあるパターンについてだけ、定義しておくという形になっています。