FPGA開発日記

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

オリジナルLLVM Backendを追加しよう (20. 算術演算命令の追加)

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

資料としては Tutorial: Creating an LLVM Backend for the Cpu0 Architecture を使用している。やっとChapter-4だ。

今回からは算術演算命令を追加していこう。

算術演算命令追加のためには MYRISCVXInstrInfo.td に命令を追加する。

commit d9a53af99b00ccba20747ef25eb3a2c2301bb4a4
Author: msyksphinz <msyksphinz_dev.gmail.com>
Date:   Thu Feb 14 16:11:05 2019 +0900

    Func: implement some operations

diff --git a/lib/Target/MYRISCVX/MYRISCVXInstrInfo.td b/lib/Target/MYRISCVX/MYRISCVXInstrInfo.td
index 0fda59cdc32..53627d494e8 100644
--- a/lib/Target/MYRISCVX/MYRISCVXInstrInfo.td
+++ b/lib/Target/MYRISCVX/MYRISCVXInstrInfo.td
@@ -256,9 +256,28 @@ def LUI  : ArithLogicU<0b0110111, "lui", simm20, immSExt12>;
 def ADD  : ArithLogicR<0b0110011, 0b000, "add", add, GPR>;
 def SUB  : ArithLogicR<0b0110011, 0b000, "sub", sub, GPR>;

+// sra is IR node for ashr llvm IR instruction of .bc
 def SRL  : shift_rotate_reg<0b0110011, 0b0000000, 0b101, 0x0, "srl", srl, GPR>;
-def SRLI : shift_rotate_imm32<0b0010011, 0b101, 0x00, "shli", shl>;
-
+def SLL  : shift_rotate_reg<0b0110011, 0b0000000, 0b001, 0x0, "sll", shl, GPR>;
+def SRA  : shift_rotate_reg<0b0110011, 0b0100000, 0b101, 0x0, "sra", sra, GPR>;
+
+def SRLI : shift_rotate_imm32<0b0010011, 0b101, 0x00, "shli", srl>;
+def SLLI : shift_rotate_imm32<0b0010011, 0b001, 0x00, "slli", shl>;
+def SRAI : shift_rotate_imm32<0b0010011, 0b101, 0x00, "srai", sra>;
+
+// Only op DAG can be disabled by ch4_1, data DAG cannot.
+def SDT_MYRISCVXDivRem : SDTypeProfile<0, 2,
+                                  [SDTCisInt<0>,
+                                  SDTCisSameAs<0, 1>]>;
+
+def MUL   : ArithLogicR<0b0110011, 0b000, "mul",    mul, GPR>;
+def MULH  : ArithLogicR<0b0110011, 0b001, "mulh",   mul, GPR>;
+def MULHSU: ArithLogicR<0b0110011, 0b010, "mulhsu", mul, GPR>;
+def MULHU : ArithLogicR<0b0110011, 0b011, "mulhu",  mul, GPR>;
+def DIV   : ArithLogicR<0b0110011, 0b100, "div",    sdiv, GPR>;
+def DIVU  : ArithLogicR<0b0110011, 0b101, "divu",   udiv, GPR>;
+def REM   : ArithLogicR<0b0110011, 0b110, "rem",    srem, GPR>;
+def REMU  : ArithLogicR<0b0110011, 0b111, "remu",   urem, GPR>;

 //===----------------------------------------------------------------------===//
 // Instruction aliases
Author: msyksphinz <msyksphinz_dev.gmail.com>
Date:   Thu Feb 14 20:49:50 2019 +0900

    Func: add arithmetic instructions

diff --git a/lib/Target/MYRISCVX/MYRISCVXInstrInfo.td b/lib/Target/MYRISCVX/MYRISCVXInstrInfo.td
index 53627d494e8..4582ef2e569 100644
--- a/lib/Target/MYRISCVX/MYRISCVXInstrInfo.td
+++ b/lib/Target/MYRISCVX/MYRISCVXInstrInfo.td
@@ -270,14 +270,14 @@ def SDT_MYRISCVXDivRem : SDTypeProfile<0, 2,
                                   [SDTCisInt<0>,
                                   SDTCisSameAs<0, 1>]>;

-def MUL   : ArithLogicR<0b0110011, 0b000, "mul",    mul, GPR>;
-def MULH  : ArithLogicR<0b0110011, 0b001, "mulh",   mul, GPR>;
-def MULHSU: ArithLogicR<0b0110011, 0b010, "mulhsu", mul, GPR>;
-def MULHU : ArithLogicR<0b0110011, 0b011, "mulhu",  mul, GPR>;
-def DIV   : ArithLogicR<0b0110011, 0b100, "div",    sdiv, GPR>;
-def DIVU  : ArithLogicR<0b0110011, 0b101, "divu",   udiv, GPR>;
-def REM   : ArithLogicR<0b0110011, 0b110, "rem",    srem, GPR>;
-def REMU  : ArithLogicR<0b0110011, 0b111, "remu",   urem, GPR>;
+def MUL   : ArithLogicR<0b0110011, 0b000, "mul",    mul,   GPR>;
+def MULH  : ArithLogicR<0b0110011, 0b001, "mulh",   mulhs, GPR>;
+def MULHSU: ArithLogicR<0b0110011, 0b010, "mulhsu", mulhs, GPR>;
+def MULHU : ArithLogicR<0b0110011, 0b011, "mulhu",  mulhu, GPR>;
+def DIV   : ArithLogicR<0b0110011, 0b100, "div",    sdiv,  GPR>;
+def DIVU  : ArithLogicR<0b0110011, 0b101, "divu",   udiv,  GPR>;
+def REM   : ArithLogicR<0b0110011, 0b110, "rem",    srem,  GPR>;
+def REMU  : ArithLogicR<0b0110011, 0b111, "remu",   urem,  GPR>;

 //===----------------------------------------------------------------------===//
 // Instruction aliases

RISC-Vには算術演算命令が複数定義されており、乗算命令、除算命令などはうまくフィットできそうだが、一つMULHSUはうまくフィットできない。これはどうすれば良いのだろう?

上記のPredicationのうち、mul, sdiv, udiv, srem, uremなどはLLVMに定義されているので、それを使用する。

llvm.org

Tutorialのうち、ch4_math.llと、ch4_1_math.cppを使用する。無事に命令生成に成功したようだ。

./bin/llc -march=myriscvx32 -relocation-model=pic -filetype=asm ../lbdex/input/ch4_math.ll -o -
        addi    x2, x2, -8
        .cfi_def_cfa_offset 8
        lw      x10, 0(x2)
        lw      x11, 4(x2)
        sub     x12, x11, x10
        add     x13, x11, x10
        add     x12, x13, x12
        mul     x13, x11, x10
        add     x12, x12, x13
        slli    x13, x11, 2
        add     x12, x12, x13
        srai    x13, x11, 2
        add     x12, x12, x13
        shli    x13, x11, 30
        add     x12, x12, x13
        addi    x13, x0, 1
        sll     x13, x13, x10
        add     x12, x12, x13
        sra     x11, x11, x10
        addi    x13, x0, 128
        srl     x10, x13, x10
        add     x10, x12, x10
        add     x10, x10, x11
        addi    x2, x2, 8
        ret
./bin/clang -target mips-unknown-linux-gnu -c ../lbdex/input/ch4_math.cpp -emit-llvm
./bin/llc -march=myriscvx32 -relocation-model=pic -filetype=asm ch4_1_math.bc -o -
        addi    x2, x2, -56
        addi    x10, x0, 5
        sw      x10, 52(x2)
        addi    x10, x0, 2
        sw      x10, 48(x2)
        addi    x10, x0, -5
        sw      x10, 44(x2)
        lw      x10, 52(x2)
        lw      x11, 48(x2)
        add     x10, x10, x11
        sw      x10, 40(x2)
        lw      x10, 52(x2)
        lw      x11, 48(x2)
...
        add     x10, x10, x11
        lw      x11, 16(x2)
        add     x10, x10, x11
        lw      x11, 0(x2)
        add     x10, x10, x11
        addi    x2, x2, 56
        ret
f:id:msyksphinz:20190215233346p:plain