RISC-Vの命令セットは基本的に32ビット長だが、Compresed命令という16ビット長の短縮命令が定義されている。これはArmのThumb命令のようなもので、命令フェッチのサイズを減らし、性能を向上させることを目的としている。
今回はこのCompressed命令をLLVMに実装する方法について検討する。
Compressed命令の仕様
Compressed命令は16ビット長の命令で、命令フェッチサイズを削減し性能を向上させることを目的としている。 16ビットで命令を表現するために、定義されているのは必要最小限の命令で、かつ指定できるレジスタの範囲にも制限がある。 以下に、RISC-Vで定義されているCompressed命令のフォーマットを示す。このように、大きく分けて9種類の命令フォーマットが定義されている。

また、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.tdMYRISCVX_CRクラス (レジスタ間演算命令)
// 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;
}
MYRISCVX_CIクラス(レジスター即値命令)
// 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>
{
// 省略
}