FPGA開発日記

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

オリジナルLLVM Backendを追加しよう (17. 命令フォーマット増強)

LLVMにはすでにRISC-Vのバックエンドサポートが追加されている。しかし、勉強のために独自のRISC-V実装をLLVMに追加している。

関数コールに対応するためには、EmitPrologueおよびEmitEpilogueを実装しなければならない。 このためには、ロードストア命令・アドレス計算に必要な命令を定義しなければならない。

LUI命令は、Load Immediate Upperに相当する命令だが、これはRISC-V命令セットのうちでU-Typeに相当する。

f:id:msyksphinz:20190211004147p:plain
RISC-Vの命令フォーマット

U-Typeを命令フォーマットで定義した。

  • lib/Target/MYRISCVX/MYRISCVXInstrFormats.td
class FU<bits<7> opcode,
         dag outs, dag ins, string asmstr, list<dag> pattern,
         InstrItinClass itin>: MYRISCVXInst<outs, ins, asmstr, pattern, itin, FrmI>
{
  bits<5>  rd;
  bits<20> imm20;

  let Opcode = opcode;

  let Inst{31-12} = imm20;
  let Inst{11-7}  = rd;
}

これに基づいて、LUI命令をはじめとする命令群を定義していく。

def ORI  : ArithLogicI<0b0010011, 0b110, "ori", or, uimm12, immZExt12, GPR>;
def LUI  : ArithLogicU<0b0110111, "lui", simm20, immSExt12>;
def ADD  : ArithLogicR<0b0110011, 0b000, "add", add, GPR>;
def SRLI : shift_rotate_imm32<0b0010011, 0b101, 0x00, "shli", shl>;

定数を扱うためのパターンも定義してゆく。

// Small immediates
def : Pat<(i32 immSExt12:$in),
          (ADDI ZERO, imm:$in)>;

def : Pat<(i32 immZExt12:$in),
          (ORI ZERO, imm:$in)>;

def : Pat<(i32 immLow12Zero:$in),
          (LUI (HI20 imm:$in))>;

// Arbitrary immediates
def : Pat<(i32 imm:$imm),
           (ORI (LUI (HI20 imm:$imm)), (LO12 imm:$imm))>;

この中で登場するLO12とか、HI20は以下のように定義される。

// Transformation Function - get the lower 12 bits.
def LO12 : SDNodeXForm<imm, [{
  return getImm(N, N->getZExtValue() & 0xfff);
}]>;

// Transformation Function - get the higher 20 bits.
def HI20 : SDNodeXForm<imm, [{
  return getImm(N, (N->getZExtValue() >> 12) & 0xfffff);
}]>;

EmitPrologue, EmitEpilogue, さらにloadImmediate()関数を追加してビルドを実行した。

一応ビルドに成功し、命令の選択はできるようになったが途中で固まってしまう。どこかで無限ループしているか?解析する必要がありそうだ。

$ ./bin/llc -march=myriscvx64 -mcpu=myriscvx64 -relocation-model=pic -filetype=asm ch3.bc -o -
...

'-noabicalls' is not a recognized feature for this target (ignoring feature)
Selecting: t7: ch = MYRISCVXISD::Ret t6, Register:i32 $a0, t6:1

Selecting: t6: ch,glue = CopyToReg t4, Register:i32 $a0, Constant:i32<0>

Selecting: t4: ch = store<(store 4 into %ir.retval)> t0, Constant:i32<0>, FrameIndex:i32<0>, undef:i32

Selecting: t5: i32 = Register $a0

Selecting: t1: i32 = Constant<0>

Selecting: t0: ch = EntryToken