FPGA開発日記

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

オリジナルLLVMバックエンド実装をまとめる(12. int32以外の型のサポートの確認)

これまでの実装で、int型以外の型もサポートできているが、念のために確認しておく。

int32型よりも小さい型を扱うために、これまでに以下のノードを追加していたのだった。

  • llvm-myriscvx80/lib/Target/MYRISCVX/MYRISCVXInstrInfo.td
// Load/Store PatFrags.
def load_a          : AlignedLoad<load>;
def sextloadi8_a    : AlignedLoad<sextloadi8>;
def zextloadi8_a    : AlignedLoad<zextloadi8>;
def sextloadi16_a   : AlignedLoad<sextloadi16>;
def zextloadi16_a   : AlignedLoad<zextloadi16>;
def extloadi16_a    : AlignedLoad<extloadi16>;

def store_a         : AlignedStore<store>;
def truncstorei8_a  : AlignedStore<truncstorei8>;
def truncstorei16_a : AlignedStore<truncstorei16>;

32ビット以外でも、16ビットと8ビットでロードストアをするためのノードを定義している。このノードを使って、ロード命令とストア命令を定義する。

/// Load and Store Instructions
///  aligned
mory <0b0000011, 0b010, "lw",  GPR, sextloadi32_a  , 0>;
def SW  : StoreMemory<0b0100011, 0b010, "sw",  GPR, sextloadi32_a  , 0>;
def LB  : LoadMemory <0b0000011, 0b000, "lb",  GPR, sextloadi8_a   , 0>;
def LBU : LoadMemory <0b0000011, 0b100, "lbu", GPR, zextloadi8_a   , 0>;
def SB  : StoreMemory<0b0100011, 0b000, "sb",  GPR, truncstorei8_a , 0>;
def LH  : LoadMemory <0b0000011, 0b001, "lh",  GPR, sextloadi16_a  , 0>;
def LHU : LoadMemory <0b0000011, 0b101, "lhu", GPR, zextloadi16_a  , 0>;
def SH  : StoreMemory<0b0100011, 0b001, "sh",  GPR, truncstorei16_a, 0>;

さらに、MYRISCVXのレジスタはi32型なので、charなどの符号なし整数からi32型へのロードができるように以下のパタンを追加している。

defm : LoadPattern<sextloadi8  , LB>;
defm : LoadPattern<extloadi8   , LB>;
defm : LoadPattern<sextloadi16 , LH>;
defm : LoadPattern<extloadi16  , LH>;
defm : LoadPattern<load        , LW>, Requires<[IsRV32]>;
defm : LoadPattern<zextloadi8  , LBU>;
defm : LoadPattern<zextloadi16 , LHU>;

defm : StorePattern<truncstorei8  , SB>;
defm : StorePattern<truncstorei16 , SH>;
defm : StorePattern<store         , SW>, Requires<[IsRV32]>;
f:id:msyksphinz:20191001204900p:plain
MYRISCVXのロード命令に対するパタンの関係

確認のために以下のソースコードコンパイルしてみる。

  • test_small_type.cpp
#include <stdint.h>

int8_t test_int8_type ()
{
  volatile int8_t i8  = 0xab;
  int8_t i8_2 = i8 + 4;
  return i8_2;
}


uint8_t test_uint8_type ()
{
  volatile uint8_t  u8  = 0xab;
  uint8_t u8_2 = u8 + 4U;
  return u8_2;
}
./bin/clang ../myriscvx-tests/tests/test_small_type.cpp -c -emit-llvm --target=riscv32-unknown-elf -o test_small_type.rv32.bc
./bin/llc -march=myriscvx32 -filetype=asm test_small_type.rv32.bc -o -

生成されたコードは以下のようになった。

_Z14test_int8_typev:                    # @_Z14test_int8_typev

# %bb.0:                                # %entry
        addi    $x2, $x2, -8
        addi    $x10, $zero, 171
        sb      $x10, 4($x2)
        lb      $x10, 4($x2)
        addi    $x10, $x10, 4
        sb      $x10, 0($x2)
        addi    $x2, $x2, 8
        ret
$func_end0:

_Z15test_uint8_typev:                   # @_Z15test_uint8_typev

# %bb.0:                                # %entry
        addi    $x2, $x2, -8
        addi    $x10, $zero, 171
        sb      $x10, 4($x2)
        lb      $x10, 4($x2)
        addi    $x10, $x10, 4
        sb      $x10, 0($x2)
        addi    $x2, $x2, 8
        ret
$func_end1:

ちゃんとlb命令、sb命令が生成されている。