DAG-to-DAGの目的は、ターゲットとは独立したノード情報をターゲット固有のノードに変換する処理を行うことだ。命令を選択するアルゴリズムはSelectionDAGに対して実行される。
DAGToDAGの中で実装しなければならない重要な関数の一つは、アドレスを計算するためのSelectAddr
だ。
SelectAddr
はMYRISCVXInstrInfo.td
で以下のように定義されている。
llvm-myriscvx/lib/Target/MYRISCVX/MYRISCVXInstrInfo.td
// MYRISCVX Address Mode! SDNode frameindex could possibily be a match // since load and store instructions from stack used it. def addr : ComplexPattern<iPTR, 2, "SelectAddr", [frameindex]>;
この"SelectAddr"を実装しなければなりません。ここでは、アドレスを計算するためにBase
とOffset
を計算する。
しかし、とりあえずオフセットは使わず、Base
がそのままアドレス、Offset
は0となるように構築する。
llvm-myriscvx/lib/Target/MYRISCVX/MYRISCVXISelDAGToDAG.cpp
//@SelectAddr { /// ComplexPattern used on MYRISCVXInstrInfo /// Used on MYRISCVX Load/Store instructions bool MYRISCVXDAGToDAGISel:: SelectAddr(SDValue Addr, SDValue &Base, SDValue &Offset) { //@SelectAddr } EVT ValTy = Addr.getValueType(); SDLoc DL(Addr); // if Address is FI, get the TargetFrameIndex. if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy); Offset = CurDAG->getTargetConstant(0, DL, ValTy); return true; } Base = Addr; Offset = CurDAG->getTargetConstant(0, DL, ValTy); return true; }
ここまでの実装で一度コンパイルを実行してみる。ターゲットをMYRISCVXでアセンブリを実行してみる。
./bin/clang -target mips-unknown-linux-gnu -c ../lbdex/input/ch3.cpp -emit-llvm -o ch3.bc ./bin/llc -march=myriscvx32 -mcpu=simple32 -mattr=+64bit -relocation-model=pic -filetype=asm ch3.bc -o - .text .section .mdebug.abilp32 .previous .file "ch3.cpp" ^C zsh: interrupt ./bin/llc -march=myriscvx32 -mcpu=simple32 -mattr=+64bit -relocation-model=pi
まだ命令の生成途中でフリーズしてしまう。 これはLLVM IRのstoreノードをしょるすることができないためだ。 これにはスタックの処理を追加する必要があるが、とりあえずここではまだ対処しない。
./bin/llvm-dis ch3.bc -o -
; Function Attrs: noinline norecurse nounwind optnone define dso_local i32 @main() #0 { entry: %retval = alloca i32, align 4 store i32 0, i32* %retval, align 4 ret i32 0 }
とりあえずclangに-O2
オプションを付けることでstoreの生成を除去する。
./bin/clang -target mips-unknown-linux-gnu -c ../lbdex/input/ch3.cpp -emit-llvm -O2 -o ch3.o2.bc ./bin/llc -march=myriscvx32 -mcpu=simple32 -mattr=+64bit -relocation-model=pic -filetype=asm ch3.o2.bc -o -
... main: .frame $x8,0,$x1 .mask 0x00000000,0 .set noreorder .set nomacro # %bb.0: # %entry addi x10, zero, 0 ret x1 .set macro .set reorder .end main ...
無事に命令を生成することができた。