FPGA開発日記

FPGAというより、コンピュータアーキテクチャかもね! カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages

オリジナルLLVM Backendを追加しよう (18. 様々なデータタイプの実装)

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

jonathan2251.github.io

第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)
...