FPGA開発日記

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

LLVMのバックエンドを作るための第一歩 (22. RISC-Vに存在しないパタンをどのように命令生成するか)

f:id:msyksphinz:20190425001356p:plain

例えば、以下のようなプログラムをコンパイルする。 このプログラムは命令を生成する段階でローテートを示すIRを生成する。

int test_rotate_left()
{
  unsigned int a = 8;
  int result = ((a << 30) | (a >> 2));

  return result;
}
./bin/clang -target mips-unknown-linux-gnu -c ../lbdex/input/ch4_1_rotate.cpp -emit-llvm
./bin/llc -debug -march=myriscvx32 -mcpu=simple32 -mattr=+64bit -relocation-model=pic -filetype=asm ch4_1_rotate.bc -o -
...
Combining: t12: i32 = FrameIndex<1>

Combining: t11: i32 = or t8, t10
Creating new node: t18: i32 = rotl t6, Constant:i32<30>
 ... into: t18: i32 = rotl t6, Constant:i32<30>

Combining: t13: ch = store<(store 4 into %ir.result)> t6:1, t18, FrameIndex:i32<1>, undef:i32
...

最終的に、rotlを命令に変換しようとするが、当然エラーとなる。

ISEL: Starting pattern match
  Initial Opcode index to 0
  Match failed at index 0
LLVM ERROR: Cannot select: t18: i32 = rotl t6, Constant:i32<30>
  t6: i32,ch = load<(dereferenceable load 4 from %ir.a)> t5, FrameIndex:i32<0>, undef:i32
    t2: i32 = FrameIndex<0>
    t4: i32 = undef
  t7: i32 = Constant<30>
In function: _Z16test_rotate_leftv

このような場合どうすればよいのかというと、MYRISCVXTargetLoweringに以下を追加する。

  • llvm-myriscvx/lib/Target/MYRISCVX/MYRISCVXSEISelLowering.cpp
//@MYRISCVXSETargetLowering {
MYRISCVXSETargetLowering::MYRISCVXSETargetLowering(const MYRISCVXTargetMachine &TM,
                                                   const MYRISCVXSubtarget &STI)
...

  setOperationAction(ISD::ROTL, MVT::i32, Expand);
  setOperationAction(ISD::ROTR, MVT::i32, Expand);
}

llvm::TargetLoweringBase::setOperationActionは、特定の命令においてターゲットアーキテクチャでのネイティブ命令が生成できない場合に指定する。これにより、一般的な命令に分解を行い命令を生成する。

./bin/llc -debug -march=myriscvx32 -mcpu=simple32 -mattr=+64bit -relocation-model=pic -filetype=asm ch4_1_rotate.bc -o - 
        addi    x2, x2, -8
        addi    x10, zero, 8
        sw      x10, 4(x2)
        lw      x10, 4(x2)
        slli    x11, x10, 30
        srli    x10, x10, 2
        or      x10, x11, x10
        sw      x10, 0(x2)
        lw      x10, 0(x2)
        addi    x2, x2, 8
        ret     x1
f:id:msyksphinz:20190608182451p:plain
Combineによるrotlが生成されるが、これを防ぎたい。