LLVMにはすでにRISC-Vのバックエンドサポートが追加されている。しかし、勉強のために独自のRISC-V実装をLLVMに追加している。
第7章の残りに取り組む。 浮動小数点の実装はとりあえず省略。RISC-Vではclzもclo命令も存在しないのでどのようにして実現すればよいのかは良く分からない。
次に配列と構造体のサポート。アドレスが微妙にずれるのを防ぐためのサポートとなる。これも元から実装していたのだが、アドレスの変換時の計算を少し追加する必要があるようだ。
lib/Target/MYRISCVX/MYRISCVXISelDAGToDAG.cpp
bool MYRISCVXDAGToDAGISel:: SelectAddr(SDNode *Parent, SDValue Addr, SDValue &Base, SDValue &Offset) { //@SelectAddr } ... // Addresses of the form FI+const or FI|const if (CurDAG->isBaseWithConstantOffset(Addr)) { ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)); if (isInt<12>(CN->getSExtValue())) { // If the first operand is a FI, get the TargetFI Node if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode> (Addr.getOperand(0))) Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy); else Base = Addr.getOperand(0); Offset = CurDAG->getTargetConstant(CN->getZExtValue(), DL, ValTy); return true; } }
最後に、ベクトル型をサポートする。テストパタンを通すために、getSetCCResultType
を追加する。
%1 = load volatile <4 x i32>, <4 x i32>* %a0, align 16 %2 = load volatile <4 x i32>, <4 x i32>* %b0, align 16 %3 = icmp slt <4 x i32> %1, %2 %4 = sext <4 x i1> %3 to <4 x i32>
@@ -337,3 +344,10 @@ MYRISCVXTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) cons // The MYRISCVX target isn't yet aware of offsets. return false; } + +EVT MYRISCVXTargetLowering::getSetCCResultType(const DataLayout &, LLVMContext &, + EVT VT) const { + if (!VT.isVector()) + return MVT::i32; + return VT.changeVectorElementTypeToInteger(); +} diff --git a/lib/Target/MYRISCVX/MYRISCVXISelLowering.h b/lib/Target/MYRISCVX/MYRISCVXISelLowering.h index 2418473550c..d8b80c7b2c9 100644 --- a/lib/Target/MYRISCVX/MYRISCVXISelLowering.h +++ b/lib/Target/MYRISCVX/MYRISCVXISelLowering.h @@ -240,6 +240,11 @@ class MYRISCVXTargetLowering : public TargetLowering { const SmallVectorImpl<ISD::OutputArg> &Outs, const SmallVectorImpl<SDValue> &OutVals, const SDLoc &dl, SelectionDAG &DAG) const override; + + /// getSetCCResultType - get the ISD::SETCC result ValueType + EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, + EVT VT) const override; + };
これで、以下のコードをコンパイルできるようになる。
ch7_1_vector.cpp
int test_cmplt_long() { volatile vector8long a0 = {2, 2, 2, 2, 1, 1, 1, 1}; volatile vector8long b0 = {1, 1, 1, 1, 2, 2, 2, 2}; volatile vector8long c0; c0 = a0 < b0; // c0[0..3] = {0, 0, ...}, c0[4..7] = {-2147483647=0x80000001, ...} return (c0[0]+c0[1]+c0[2]+c0[3]+c0[4]+c0[5]+c0[6]+c0[7]); //4 }
こんなコードが生成された。とりあえず、ベクトル型がRISC-Vの命令になって出力されるようだ。
... lw x5, 60(x2) lw x6, 56(x2) lw x7, 52(x2) lw x28, 48(x2) lw x29, 44(x2) lw x30, 40(x2) lw x31, 36(x2) lw x4, 32(x2) slt x17, x17, x4 addi x4, x0, 0 sub x17, x4, x17 slt x16, x16, x31 sub x16, x4, x16 slt x15, x15, x30 sub x15, x4, x15 slt x14, x14, x29 sub x14, x4, x14 slt x13, x13, x28 sub x13, x4, x13 slt x12, x12, x7 sub x12, x4, x12 slt x11, x11, x6 sub x11, x4, x11 slt x10, x10, x5 sub x10, x4, x10 sw x10, 28(x2) sw x11, 24(x2) sw x12, 20(x2) ...