LLVMにはすでにRISC-Vのバックエンドサポートが追加されている。しかし、勉強のために独自のRISC-V実装をLLVMに追加している。
Chapter-4.2のあたりを進めている。論理演算命令と比較命令だ。
比較命令をテストしようとすると、MYRISCVXの実装では命令の生成に失敗してしまった。
./bin/clang -target mips-unknown-linux-gnu -c ../lbdex/input/ch4_2_logic.cpp -emit-llvm ./bin/llc -march=myriscvx32 -relocation-model=pic -filetype=asm ch4_2_logic.bc -o -
Selecting: t36: ch = store<(store 4 into %ir.b)> t30:1, t52, FrameIndex:i32<1>, undef:i32 Selecting: t52: i32 = and t50, Constant:i32<1> Selecting: t50: i32 = setcc t30, Constant:i32<0>, seteq:ch LLVM ERROR: Cannot select: t50: i32 = setcc t30, Constant:i32<0>, seteq:ch t30: i32,ch = load<(dereferenceable load 4 from %ir.a)> t29, FrameIndex:i32<0>, undef:i32 t2: i32 = FrameIndex<0> t4: i32 = undef t3: i32 = Constant<0> In function: _Z16test_andorxornotv
どうも、RISC-Vでは比較命令のバリエーションが少ないため、SLT/SLTIUをうまく使いまわして命令を生成する必要があるらしい。 RISC-V本体の実装から引っ張ってきた。 パタンルールを追加する。
diff --git a/lib/Target/MYRISCVX/MYRISCVXInstrInfo.td b/lib/Target/MYRISCVX/MYRISCVXInstrInfo.td index 41a47ff6ff3..2c0424c98d4 100644 --- a/lib/Target/MYRISCVX/MYRISCVXInstrInfo.td +++ b/lib/Target/MYRISCVX/MYRISCVXInstrInfo.td @@ -296,6 +296,17 @@ def SLTIU : SetCC_I<0b0010011, 0b011, "sltiu", setult, simm12, immSExt12, GPR>; def SLT : SetCC_R<0b0110011, 0b010, "slt", setlt, GPR>; def SLTU : SetCC_R<0b0110011, 0b011, "sltu", setult, GPR>; +// Define pattern expansions for setcc operations that aren't directly +// handled by a RISC-V instruction. +def : Pat<(seteq GPR:$rs1, GPR:$rs2), (SLTIU (XOR GPR:$rs1, GPR:$rs2), 1)>; +def : Pat<(setne GPR:$rs1, GPR:$rs2), (SLTU ZERO, (XOR GPR:$rs1, GPR:$rs2))>; +def : Pat<(setugt GPR:$rs1, GPR:$rs2), (SLTU GPR:$rs2, GPR:$rs1)>; +def : Pat<(setuge GPR:$rs1, GPR:$rs2), (XORI (SLTU GPR:$rs1, GPR:$rs2), 1)>; +def : Pat<(setule GPR:$rs1, GPR:$rs2), (XORI (SLTU GPR:$rs2, GPR:$rs1), 1)>; +def : Pat<(setgt GPR:$rs1, GPR:$rs2), (SLT GPR:$rs2, GPR:$rs1)>; +def : Pat<(setge GPR:$rs1, GPR:$rs2), (XORI (SLT GPR:$rs1, GPR:$rs2), 1)>; +def : Pat<(setle GPR:$rs1, GPR:$rs2), (XORI (SLT GPR:$rs2, GPR:$rs1), 1)>; + // Only op DAG can be disabled by ch4_1, data DAG cannot. def SDT_MYRISCVXDivRem : SDTypeProfile<0, 2, [SDTCisInt<0>,
これで、比較命令が生成できるようになる。
lw x10, 28(x2) lw x11, 24(x2) xor x10, x10, x11 sltiu x10, x10, 1 andi x10, x10, 1 sw x10, 20(x2)
次にテストするのは、ch4_2_slt_explain.cpp
だ。
これは本来比較フラグをレジスタに引っ張ってきて演算をするのだが、RISC-Vでは比較命令の結果も汎用レジスタに格納するので特に考えることは無い。
int a = 3, b = 1; int d = 0, e = 0, f = 0; d = (a < 1); e = (b < 2); f = d + e; return (f);
生成結果は以下となった。
slti x10, x10, 1 andi x10, x10, 1 sw x10, 12(x2) lw x10, 16(x2) slti x10, x10, 2 andi x10, x10, 1 sw x10, 8(x2) lw x10, 12(x2) lw x11, 8(x2) add x10, x10, x11 sw x10, 4(x2)