FPGA開発日記

カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages , English Version https://fpgadevdiary.hatenadiary.com/

LLVMのバックエンドを作るための第一歩 (54. Compressed命令を実装する検討)

f:id:msyksphinz:20190425001356p:plain

RISC-Vの命令セットは基本的に32ビット長だが、Compresed命令という16ビット長の短縮命令が定義されている。これはArmのThumb命令のようなもので、命令フェッチのサイズを減らし、性能を向上させることを目的としている。

今回はこのCompressed命令をLLVMに実装する方法について検討する。

Compressed命令の仕様

Compressed命令は16ビット長の命令で、命令フェッチサイズを削減し性能を向上させることを目的としている。 16ビットで命令を表現するために、定義されているのは必要最小限の命令で、かつ指定できるレジスタの範囲にも制限がある。 以下に、RISC-Vで定義されているCompressed命令のフォーマットを示す。このように、大きく分けて9種類の命令フォーマットが定義されている。

1565885086152

また、rs1', rs2', rd'などで定義されているレジスタは以下のようなマップになっている。3ビットでレジスタを表現するために、必要最小限のレジスタのみを指定できる。

RVC Register Number 000 001 010 011 100 101 110 111
Integer Register Number x8 x9 x10 x11 x12 x13 x14 x15
Integer Register ABI Name s0 s1 a0 a1 a2 a3 a4 a5
Floating-Point Register Number f8 f9 f10 f11 f12 f13 f14 f15
Floating-Point Register ABI Name fs0 fs1 fa0 fa1 fa2 fa3 fa4 fa5

まずは、命令フォーマットを定義します。上記の9種類の命令フォーマットをLLVMで表現しましょう。

  • llvm-myriscvx/lib/Target/MYRISCVX/MYRISCVXInstrFormats.td
// MYRISCVX Compressed Format
class MYRISCVXCInst<dag outs, dag ins, string asmstr, list<dag> pattern,
                    InstrItinClass itin, Format f>: Instruction
{
  // Inst and Size: for tablegen(... -gen-emitter) and
  // tablegen(... -gen-disassembler) in CMakeLists.txt
  field bits<16> Inst;
  Format Form = f;
  let Namespace = "MYRISCVX";
  let Size = 2;
  bits<2> Opcode = 0;

  // Bottom 2 bits are the 'opcode' field
  let Inst{1-0} = Opcode;

...

  field bits<32> SoftFail = 0;
}

MYRISCVXInstに加えて、MYRISCVXCInstを定義した。変更しているのは、field bits<16> Instとして命令長を16ビットに絞っているところである。

このクラスを利用して、上記の9種類の命令フォーマットを定義する

  • llvm-myriscvx/lib/Target/MYRISCVX/MYRISCVXInstrInfoC.td
// Compressed Instruciton CR (Compressed Register)
class MYRISCVX_CR<bits<4> funct4, bits<2> op,
                  dag outs, dag ins, string asmstr,
                  list<dag> pattern, InstrItinClass itin> :
  MYRISCVXCInst<outs, ins, asmstr, pattern, itin, FrmR>
{
  bits<5> rd;
  bits<5> rs2;

  let Inst{15-12} = funct4;
  let Inst{11-7}  = rd;
  let Inst{6-2}   = rs2;
}
// Compressed Instruciton CI (Compressed Immediate)
class MYRISCVX_CI<bits<3> funct3, bits<2> op,
                  dag outs, dag ins, string asmstr,
                  list<dag> pattern, InstrItinClass itin> :
  MYRISCVXCInst<outs, ins, asmstr, pattern, itin, FrmR>
{
  // 省略
}
  • MYRISCVX_CSSクラス(スタックポインタ制御命令)
// Compressed Instruciton CSS (Compressed Stack-relative Store)
class MYRISCVX_CSS<bits<3> funct3,
                  dag outs, dag ins, string asmstr,
                  list<dag> pattern, InstrItinClass itin> :
  MYRISCVXCInst<outs, ins, asmstr, pattern, itin, FrmR>
{
  // 省略
}
  • MYRISCVX_CIWクラス(幅広即値命令)
// Compressed Instruciton CIW (Compressed Wide Immediate)
class MYRISCVX_CIW<bits<3> funct3,
                  dag outs, dag ins, string asmstr,
                  list<dag> pattern, InstrItinClass itin> :
  MYRISCVXCInst<outs, ins, asmstr, pattern, itin, FrmR>
{
  // 省略
}
  • MYRISCVX_CLクラス (ロード命令)
// Compressed Instruciton CS (Compressed Store)
class MYRISCVX_CS<bits<3> funct3,
                  dag outs, dag ins, string asmstr,
                  list<dag> pattern, InstrItinClass itin> :
  MYRISCVXCInst<outs, ins, asmstr, pattern, itin, FrmR>
{
  // 省略
}
  • MYRISCVX_CSクラス (ストア命令)
class MYRISCVX_CS<bits<3> funct3,
                  dag outs, dag ins, string asmstr,
                  list<dag> pattern, InstrItinClass itin> :
  MYRISCVXCInst<outs, ins, asmstr, pattern, itin, FrmR>
{
  // 省略
}
  • MYRISCVX_CAクラス (算術演算命令)
// Compressed Instruciton CA (Compressed Arithmetic)
class MYRISCVX_CA<bits<6> funct6, bits<2> funct2,
                  dag outs, dag ins, string asmstr,
                  list<dag> pattern, InstrItinClass itin> :
  MYRISCVXCInst<outs, ins, asmstr, pattern, itin, FrmR>
{
  // 省略
}
  • MYRISCVX_CBクラス (条件分岐命令)
// Compressed Instruciton CB (Compressed Branch)
class MYRISCVX_CB<bits<3> funct3,
                  dag outs, dag ins, string asmstr,
                  list<dag> pattern, InstrItinClass itin> :
  MYRISCVXCInst<outs, ins, asmstr, pattern, itin, FrmR>
{
  // 省略
}
  • MYRISCVX_CJクラス (無条件分岐命令)
// Compressed Instruciton CJ (Compressed Jump)
class MYRISCVX_CJ<bits<3> funct3,
                  dag outs, dag ins, string asmstr,
                  list<dag> pattern, InstrItinClass itin> :
  MYRISCVXCInst<outs, ins, asmstr, pattern, itin, FrmR>
{
  // 省略
}

これらを登録してまずはLLVMコンパイルしてみる。