[llvm] 7b79e8d - [RISCV] Add vendor-defined XTheadFMemIdx (FP Indexed Memory Operations) extension

Philipp Tomsich via llvm-commits llvm-commits at lists.llvm.org
Thu Feb 23 15:35:54 PST 2023


Author: Manolis Tsamis
Date: 2023-02-24T00:35:37+01:00
New Revision: 7b79e8d45576e17daca4853deae40119615588b0

URL: https://github.com/llvm/llvm-project/commit/7b79e8d45576e17daca4853deae40119615588b0
DIFF: https://github.com/llvm/llvm-project/commit/7b79e8d45576e17daca4853deae40119615588b0.diff

LOG: [RISCV] Add vendor-defined XTheadFMemIdx (FP Indexed Memory Operations) extension

The vendor-defined XTHeadFMemIdx (no comparable standard extension exists
at the time of writing) extension adds indexed load/store instructions
for floating-point registers.

It is supported by the C9xx cores (e.g., found in the wild in the
Allwinner D1) by Alibaba T-Head.

The current (as of this commit) public documentation for this
extension is available at:
  https://github.com/T-head-Semi/thead-extension-spec/releases/download/2.2.2/xthead-2023-01-30-2.2.2.pdf

Support for these instructions has already landed in GNU Binutils:
  https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=f511f80fa3fcaf6bcbe727fb902b8bd5ec8f9c20

Depends on D144249

Reviewed By: craig.topper

Differential Revision: https://reviews.llvm.org/D144647

Added: 
    llvm/test/CodeGen/RISCV/xtheadfmemidx.ll
    llvm/test/MC/RISCV/rv32xtheadfmemidx-d-invalid.s
    llvm/test/MC/RISCV/rv32xtheadfmemidx-f-invalid.s
    llvm/test/MC/RISCV/rv32xtheadfmemidx-valid.s
    llvm/test/MC/RISCV/rv64xtheadfmemidx-invalid.s
    llvm/test/MC/RISCV/rv64xtheadfmemidx-valid.s

Modified: 
    llvm/docs/RISCVUsage.rst
    llvm/docs/ReleaseNotes.rst
    llvm/lib/Support/RISCVISAInfo.cpp
    llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
    llvm/lib/Target/RISCV/RISCVFeatures.td
    llvm/lib/Target/RISCV/RISCVInstrInfoXTHead.td
    llvm/test/CodeGen/RISCV/attributes.ll

Removed: 
    


################################################################################
diff  --git a/llvm/docs/RISCVUsage.rst b/llvm/docs/RISCVUsage.rst
index 45a4ac9455f5c..5be15a158cf37 100644
--- a/llvm/docs/RISCVUsage.rst
+++ b/llvm/docs/RISCVUsage.rst
@@ -189,6 +189,9 @@ The current vendor extensions supported are:
 ``XTHeadCmo``
   LLVM implements `the THeadCmo (cache management operations) vendor-defined instructions specified in <https://github.com/T-head-Semi/thead-extension-spec/releases/download/2.2.2/xthead-2023-01-30-2.2.2.pdf>`_  by T-HEAD of Alibaba.  Instructions are prefixed with `th.` as described in the specification.
 
+``XTHeadFMemIdx``
+  LLVM implements `the THeadFMemIdx (indexed memory operations for floating point) vendor-defined instructions specified in <https://github.com/T-head-Semi/thead-extension-spec/releases/download/2.2.2/xthead-2023-01-30-2.2.2.pdf>`_  by T-HEAD of Alibaba.  Instructions are prefixed with `th.` as described in the specification.
+
 ``XTheadMac``
   LLVM implements `the XTheadMac (multiply-accumulate instructions) vendor-defined instructions specified in <https://github.com/T-head-Semi/thead-extension-spec/releases/download/2.2.2/xthead-2023-01-30-2.2.2.pdf>`_  by T-HEAD of Alibaba.  Instructions are prefixed with `th.` as described in the specification.
 

diff  --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst
index 82fad2287b7e8..5c8d3fcb4026f 100644
--- a/llvm/docs/ReleaseNotes.rst
+++ b/llvm/docs/ReleaseNotes.rst
@@ -119,6 +119,7 @@ Changes to the RISC-V Backend
 * Support for the now-ratified Zawrs extension is no longer experimental.
 * Adds support for the vendor-defined XTHeadCmo (cache management operations) extension.
 * Adds support for the vendor-defined XTHeadSync (multi-core synchronization instructions) extension.
+* Added support for the vendor-defined XTHeadFMemIdx (indexed memory operations for floating point) extension.
 
 Changes to the WebAssembly Backend
 ----------------------------------

diff  --git a/llvm/lib/Support/RISCVISAInfo.cpp b/llvm/lib/Support/RISCVISAInfo.cpp
index 7cd92b49e70d8..d36a783ded4dd 100644
--- a/llvm/lib/Support/RISCVISAInfo.cpp
+++ b/llvm/lib/Support/RISCVISAInfo.cpp
@@ -117,6 +117,7 @@ static const RISCVSupportedExtension SupportedExtensions[] = {
     {"xtheadbb", RISCVExtensionVersion{1, 0}},
     {"xtheadbs", RISCVExtensionVersion{1, 0}},
     {"xtheadcmo", RISCVExtensionVersion{1, 0}},
+    {"xtheadfmemidx", RISCVExtensionVersion{1, 0}},
     {"xtheadmac", RISCVExtensionVersion{1, 0}},
     {"xtheadmemidx", RISCVExtensionVersion{1, 0}},
     {"xtheadmempair", RISCVExtensionVersion{1, 0}},

diff  --git a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
index 807d1e9fa9f41..eccaa9d03f514 100644
--- a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
+++ b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
@@ -527,6 +527,13 @@ DecodeStatus RISCVDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
       if (Result != MCDisassembler::Fail)
         return Result;
     }
+    if (STI.hasFeature(RISCV::FeatureVendorXTHeadFMemIdx)) {
+      LLVM_DEBUG(dbgs() << "Trying XTHeadFMemIdx custom opcode table:\n");
+      Result = decodeInstruction(DecoderTableTHeadFMemIdx32, MI, Insn, Address,
+                                 this, STI);
+      if (Result != MCDisassembler::Fail)
+        return Result;
+    }
     if (STI.hasFeature(RISCV::FeatureVendorXTHeadMac)) {
       LLVM_DEBUG(dbgs() << "Trying XTHeadMac custom opcode table:\n");
       Result = decodeInstruction(DecoderTableTHeadMac32, MI, Insn, Address,

diff  --git a/llvm/lib/Target/RISCV/RISCVFeatures.td b/llvm/lib/Target/RISCV/RISCVFeatures.td
index 9cd863693f113..ad789170ce1ae 100644
--- a/llvm/lib/Target/RISCV/RISCVFeatures.td
+++ b/llvm/lib/Target/RISCV/RISCVFeatures.td
@@ -512,6 +512,14 @@ def HasVendorXTHeadCmo : Predicate<"Subtarget->hasVendorXTHeadCmo()">,
                                    AssemblerPredicate<(all_of FeatureVendorXTHeadCmo),
                                    "'xtheadcmo' (T-Head cache management instructions)">;
 
+def FeatureVendorXTHeadFMemIdx
+    : SubtargetFeature<"xtheadfmemidx", "HasVendorXTHeadFMemIdx", "true",
+                       "'xtheadfmemidx' (T-Head FP Indexed Memory Operations)",
+                       [FeatureStdExtF]>;
+def HasVendorXTHeadFMemIdx : Predicate<"Subtarget->hasVendorXTHeadFMemIdx()">,
+                                       AssemblerPredicate<(all_of FeatureVendorXTHeadFMemIdx),
+                                       "'xtheadfmemidx' (T-Head FP Indexed Memory Operations)">;
+
 def FeatureVendorXTHeadMac
     : SubtargetFeature<"xtheadmac", "HasVendorXTHeadMac", "true",
                        "'xtheadmac' (T-Head Multiply-Accumulate Instructions)">;

diff  --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXTHead.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXTHead.td
index 41a79a26e005c..4feff6323890b 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoXTHead.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXTHead.td
@@ -164,8 +164,7 @@ class THCacheInst_void<bits<5> funct5, string opcodestr>
   let rs2 = funct5;
 }
 
-let Predicates = [HasVendorXTHeadMemIdx], DecoderNamespace = "THeadMemIdx",
-  hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
+let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
 class THLoadIndexed<RegisterClass Ty, bits<5> funct5, string opcodestr>
     : RVInstR<!shl(funct5, 2), !if(!eq(Ty, GPR), 0b100, 0b110), OPC_CUSTOM_0,
               (outs Ty:$rd), (ins GPR:$rs1, GPR:$rs2, uimm2:$uimm2),
@@ -187,8 +186,7 @@ class THLoadUpdate<bits<5> funct5, string opcodestr>
 }
 }
 
-let Predicates = [HasVendorXTHeadMemIdx], DecoderNamespace = "THeadMemIdx",
-  hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
+let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
 class THStoreIndexed<RegisterClass StTy, bits<5> funct5, string opcodestr>
     : RVInstR<!shl(funct5, 2), !if(!eq(StTy, GPR), 0b101, 0b111), OPC_CUSTOM_0,
               (outs), (ins StTy:$rd, GPR:$rs1, GPR:$rs2, uimm2:$uimm2),
@@ -284,7 +282,7 @@ def TH_SDD  : THStorePair<0b11111, "th.sdd">,
               Sched<[WriteSTD, WriteSTD, ReadStoreData, ReadMemBase]>;
 }
 
-let Predicates = [HasVendorXTHeadMemIdx] in {
+let Predicates = [HasVendorXTHeadMemIdx], DecoderNamespace = "THeadMemIdx" in {
 // T-Head Load/Store + Update instructions.
 def TH_LBIA : THLoadUpdate<0b00011, "th.lbia">,
   Sched<[WriteLDB, ReadMemBase]>;
@@ -364,7 +362,7 @@ def TH_SURW : THStoreIndexed<GPR, 0b01010, "th.surw">,
   Sched<[WriteLDB, ReadMemBase]>;
 }
 
-let Predicates = [HasVendorXTHeadMemIdx, IsRV64] in {
+let Predicates = [HasVendorXTHeadMemIdx, IsRV64], DecoderNamespace = "THeadMemIdx" in {
 // T-Head Load/Store + Update instructions.
 def TH_LWUIA : THLoadUpdate<0b11011, "th.lwuia">,
   Sched<[WriteLDH, ReadMemBase]>;
@@ -398,6 +396,40 @@ def TH_SURD : THStoreIndexed<GPR, 0b01110, "th.surd">,
   Sched<[WriteLDB, ReadMemBase]>;
 }
 
+// T-Head Load/Store Indexed instructions for floating point registers.
+
+let Predicates = [HasVendorXTHeadFMemIdx, HasStdExtF],
+    DecoderNamespace = "THeadFMemIdx" in {
+def TH_FLRW : THLoadIndexed<FPR32, 0b01000, "th.flrw">,
+              Sched<[WriteFLD32, ReadFMemBase]>;
+def TH_FSRW : THStoreIndexed<FPR32, 0b01000, "th.fsrw">,
+              Sched<[WriteFST32, ReadFStoreData, ReadFMemBase]>;
+}
+
+let Predicates = [HasVendorXTHeadFMemIdx, HasStdExtD],
+    DecoderNamespace = "THeadFMemIdx" in {
+def TH_FLRD : THLoadIndexed<FPR64, 0b01100, "th.flrd">,
+              Sched<[WriteFLD64, ReadFMemBase]>;
+def TH_FSRD : THStoreIndexed<FPR64, 0b01100, "th.fsrd">,
+              Sched<[WriteFST64, ReadFStoreData, ReadFMemBase]>;
+}
+
+let Predicates = [HasVendorXTHeadFMemIdx, HasStdExtF, IsRV64],
+    DecoderNamespace = "THeadFMemIdx" in {
+def TH_FLURW : THLoadIndexed<FPR32, 0b01010, "th.flurw">,
+               Sched<[WriteFLD32, ReadFMemBase]>;
+def TH_FSURW : THStoreIndexed<FPR32, 0b01010, "th.fsurw">,
+               Sched<[WriteFST32, ReadFStoreData, ReadFMemBase]>;
+}
+
+let Predicates = [HasVendorXTHeadFMemIdx, HasStdExtD, IsRV64],
+    DecoderNamespace = "THeadFMemIdx" in {
+def TH_FLURD : THLoadIndexed<FPR64, 0b01110, "th.flurd">,
+               Sched<[WriteFLD64, ReadFMemBase]>;
+def TH_FSURD : THStoreIndexed<FPR64, 0b01110, "th.fsurd">,
+               Sched<[WriteFST64, ReadFStoreData, ReadFMemBase]>;
+}
+
 let Predicates = [HasVendorXTHeadVdot],
     Constraints = "@earlyclobber $vd",
     RVVConstraint = WidenV in {
@@ -774,6 +806,30 @@ defm : StIdxPat<store, TH_SRD, GPR>;
 defm : StZextIdxPat<store, TH_SURD, GPR>;
 }
 
+let Predicates = [HasVendorXTHeadFMemIdx, HasStdExtF, IsRV32] in {
+defm : LdIdxPat<load, TH_FLRW, f32>;
+defm : StIdxPat<store, TH_FSRW, FPR32, f32>;
+}
+
+let Predicates = [HasVendorXTHeadFMemIdx, HasStdExtD, IsRV32] in {
+defm : LdIdxPat<load, TH_FLRD, f64>;
+defm : StIdxPat<store, TH_FSRD, FPR64, f64>;
+}
+
+let Predicates = [HasVendorXTHeadFMemIdx, HasStdExtF, IsRV64] in {
+defm : LdIdxPat<load, TH_FLRW, f32>;
+defm : LdZextIdxPat<load, TH_FLURW, f32>;
+defm : StIdxPat<store, TH_FSRW, FPR32, f32>;
+defm : StZextIdxPat<store, TH_FSURW, FPR32, f32>;
+}
+
+let Predicates = [HasVendorXTHeadFMemIdx, HasStdExtD, IsRV64] in {
+defm : LdIdxPat<load, TH_FLRD, f64>;
+defm : LdZextIdxPat<load, TH_FLURD, f64>;
+defm : StIdxPat<store, TH_FSRD, FPR64, f64>;
+defm : StZextIdxPat<store, TH_FSURD, FPR64, f64>;
+}
+
 def simm5shl2 : ComplexPattern<XLenVT, 2, "selectSimm5Shl2">;
 
 multiclass StoreUpdatePat<PatFrag st, Instruction Inst, ValueType vt = XLenVT> {

diff  --git a/llvm/test/CodeGen/RISCV/attributes.ll b/llvm/test/CodeGen/RISCV/attributes.ll
index a0daf0c328b23..cbc22780a10c7 100644
--- a/llvm/test/CodeGen/RISCV/attributes.ll
+++ b/llvm/test/CodeGen/RISCV/attributes.ll
@@ -42,6 +42,7 @@
 ; RUN: llc -mtriple=riscv32 -mattr=+svpbmt %s -o - | FileCheck --check-prefixes=CHECK,RV32SVPBMT %s
 ; RUN: llc -mtriple=riscv32 -mattr=+svinval %s -o - | FileCheck --check-prefixes=CHECK,RV32SVINVAL %s
 ; RUN: llc -mtriple=riscv32 -mattr=+xtheadcmo %s -o - | FileCheck --check-prefix=RV32XTHEADCMO %s
+; RUN: llc -mtriple=riscv32 -mattr=+xtheadfmemidx %s -o - | FileCheck --check-prefix=RV32XTHEADFMEMIDX %s
 ; RUN: llc -mtriple=riscv32 -mattr=+xtheadmac %s -o - | FileCheck --check-prefixes=CHECK,RV32XTHEADMAC %s
 ; RUN: llc -mtriple=riscv32 -mattr=+xtheadmemidx %s -o - | FileCheck --check-prefix=RV32XTHEADMEMIDX %s
 ; RUN: llc -mtriple=riscv32 -mattr=+xtheadmempair %s -o - | FileCheck --check-prefix=RV32XTHEADMEMPAIR %s
@@ -100,6 +101,7 @@
 ; RUN: llc -mtriple=riscv64 -mattr=+xtheadbb %s -o - | FileCheck --check-prefixes=CHECK,RV64XTHEADBB %s
 ; RUN: llc -mtriple=riscv64 -mattr=+xtheadbs %s -o - | FileCheck --check-prefixes=CHECK,RV64XTHEADBS %s
 ; RUN: llc -mtriple=riscv64 -mattr=+xtheadcmo %s -o - | FileCheck --check-prefix=RV64XTHEADCMO %s
+; RUN: llc -mtriple=riscv64 -mattr=+xtheadfmemidx %s -o - | FileCheck --check-prefix=RV64XTHEADFMEMIDX %s
 ; RUN: llc -mtriple=riscv64 -mattr=+xtheadmac %s -o - | FileCheck --check-prefixes=CHECK,RV64XTHEADMAC %s
 ; RUN: llc -mtriple=riscv64 -mattr=+xtheadmemidx %s -o - | FileCheck --check-prefix=RV64XTHEADMEMIDX %s
 ; RUN: llc -mtriple=riscv64 -mattr=+xtheadmempair %s -o - | FileCheck --check-prefix=RV64XTHEADMEMPAIR %s
@@ -157,6 +159,7 @@
 ; RV32SVPBMT: .attribute 5, "rv32i2p0_svpbmt1p0"
 ; RV32SVINVAL: .attribute 5, "rv32i2p0_svinval1p0"
 ; RV32XTHEADCMO: .attribute 5, "rv32i2p0_xtheadcmo1p0"
+; RV32XTHEADFMEMIDX: .attribute 5, "rv32i2p0_f2p0_xtheadfmemidx1p0"
 ; RV32XTHEADMAC: .attribute 5, "rv32i2p0_xtheadmac1p0"
 ; RV32XTHEADMEMIDX: .attribute 5, "rv32i2p0_xtheadmemidx1p0"
 ; RV32XTHEADMEMPAIR: .attribute 5, "rv32i2p0_xtheadmempair1p0"
@@ -215,6 +218,7 @@
 ; RV64XTHEADBB: .attribute 5, "rv64i2p0_xtheadbb1p0"
 ; RV64XTHEADBS: .attribute 5, "rv64i2p0_xtheadbs1p0"
 ; RV64XTHEADCMO: .attribute 5, "rv64i2p0_xtheadcmo1p0"
+; RV64XTHEADFMEMIDX: .attribute 5, "rv64i2p0_f2p0_xtheadfmemidx1p0"
 ; RV64XTHEADMAC: .attribute 5, "rv64i2p0_xtheadmac1p0"
 ; RV64XTHEADMEMIDX: .attribute 5, "rv64i2p0_xtheadmemidx1p0"
 ; RV64XTHEADMEMPAIR: .attribute 5, "rv64i2p0_xtheadmempair1p0"

diff  --git a/llvm/test/CodeGen/RISCV/xtheadfmemidx.ll b/llvm/test/CodeGen/RISCV/xtheadfmemidx.ll
new file mode 100644
index 0000000000000..fb3fd3bd00504
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/xtheadfmemidx.ll
@@ -0,0 +1,153 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=riscv32 -mattr=+d -mattr=+xtheadfmemidx -mattr=+m -verify-machineinstrs < %s \
+; RUN:   | FileCheck %s -check-prefix=RV32XTHEADMEMIDX
+; RUN: llc -mtriple=riscv64 -mattr=+d -mattr=+xtheadfmemidx -verify-machineinstrs < %s \
+; RUN:   | FileCheck %s -check-prefix=RV64XTHEADFMEMIDX
+
+define float @flrw(float* %a, i64 %b) {
+; RV32XTHEADMEMIDX-LABEL: flrw:
+; RV32XTHEADMEMIDX:       # %bb.0:
+; RV32XTHEADMEMIDX-NEXT:    th.flrw ft0, a0, a1, 2
+; RV32XTHEADMEMIDX-NEXT:    fadd.s fa0, ft0, ft0
+; RV32XTHEADMEMIDX-NEXT:    ret
+;
+; RV64XTHEADFMEMIDX-LABEL: flrw:
+; RV64XTHEADFMEMIDX:       # %bb.0:
+; RV64XTHEADFMEMIDX-NEXT:    th.flrw ft0, a0, a1, 2
+; RV64XTHEADFMEMIDX-NEXT:    fadd.s fa0, ft0, ft0
+; RV64XTHEADFMEMIDX-NEXT:    ret
+  %1 = getelementptr float, float* %a, i64 %b
+  %2 = load float, float* %1, align 4
+  %3 = fadd float %2, %2
+  ret float %3
+}
+
+define float @flurw(float* %a, i32 %b) {
+; RV32XTHEADMEMIDX-LABEL: flurw:
+; RV32XTHEADMEMIDX:       # %bb.0:
+; RV32XTHEADMEMIDX-NEXT:    th.flrw ft0, a0, a1, 2
+; RV32XTHEADMEMIDX-NEXT:    fadd.s fa0, ft0, ft0
+; RV32XTHEADMEMIDX-NEXT:    ret
+;
+; RV64XTHEADFMEMIDX-LABEL: flurw:
+; RV64XTHEADFMEMIDX:       # %bb.0:
+; RV64XTHEADFMEMIDX-NEXT:    th.flurw ft0, a0, a1, 2
+; RV64XTHEADFMEMIDX-NEXT:    fadd.s fa0, ft0, ft0
+; RV64XTHEADFMEMIDX-NEXT:    ret
+  %1 = zext i32 %b to i64
+  %2 = getelementptr float, float* %a, i64 %1
+  %3 = load float, float* %2, align 4
+  %4 = fadd float %3, %3
+  ret float %4
+}
+
+define void @fsrw(float* %a, i64 %b, float %c) {
+; RV32XTHEADMEMIDX-LABEL: fsrw:
+; RV32XTHEADMEMIDX:       # %bb.0:
+; RV32XTHEADMEMIDX-NEXT:    fadd.s ft0, fa0, fa0
+; RV32XTHEADMEMIDX-NEXT:    th.fsrw ft0, a0, a1, 2
+; RV32XTHEADMEMIDX-NEXT:    ret
+;
+; RV64XTHEADFMEMIDX-LABEL: fsrw:
+; RV64XTHEADFMEMIDX:       # %bb.0:
+; RV64XTHEADFMEMIDX-NEXT:    fadd.s ft0, fa0, fa0
+; RV64XTHEADFMEMIDX-NEXT:    th.fsrw ft0, a0, a1, 2
+; RV64XTHEADFMEMIDX-NEXT:    ret
+  %1 = fadd float %c, %c
+  %2 = getelementptr float, float* %a, i64 %b
+  store float %1, float* %2, align 4
+  ret void
+}
+
+define void @fsurw(float* %a, i32 %b, float %c) {
+; RV32XTHEADMEMIDX-LABEL: fsurw:
+; RV32XTHEADMEMIDX:       # %bb.0:
+; RV32XTHEADMEMIDX-NEXT:    fadd.s ft0, fa0, fa0
+; RV32XTHEADMEMIDX-NEXT:    th.fsrw ft0, a0, a1, 2
+; RV32XTHEADMEMIDX-NEXT:    ret
+;
+; RV64XTHEADFMEMIDX-LABEL: fsurw:
+; RV64XTHEADFMEMIDX:       # %bb.0:
+; RV64XTHEADFMEMIDX-NEXT:    fadd.s ft0, fa0, fa0
+; RV64XTHEADFMEMIDX-NEXT:    th.fsurw ft0, a0, a1, 2
+; RV64XTHEADFMEMIDX-NEXT:    ret
+  %1 = zext i32 %b to i64
+  %2 = fadd float %c, %c
+  %3 = getelementptr float, float* %a, i64 %1
+  store float %2, float* %3, align 4
+  ret void
+}
+
+define double @flrd(double* %a, i64 %b) {
+; RV32XTHEADMEMIDX-LABEL: flrd:
+; RV32XTHEADMEMIDX:       # %bb.0:
+; RV32XTHEADMEMIDX-NEXT:    th.flrd ft0, a0, a1, 3
+; RV32XTHEADMEMIDX-NEXT:    fadd.d fa0, ft0, ft0
+; RV32XTHEADMEMIDX-NEXT:    ret
+;
+; RV64XTHEADFMEMIDX-LABEL: flrd:
+; RV64XTHEADFMEMIDX:       # %bb.0:
+; RV64XTHEADFMEMIDX-NEXT:    th.flrd ft0, a0, a1, 3
+; RV64XTHEADFMEMIDX-NEXT:    fadd.d fa0, ft0, ft0
+; RV64XTHEADFMEMIDX-NEXT:    ret
+  %1 = getelementptr double, double* %a, i64 %b
+  %2 = load double, double* %1, align 8
+  %3 = fadd double %2, %2
+  ret double %3
+}
+
+define double @flurd(double* %a, i32 %b) {
+; RV32XTHEADMEMIDX-LABEL: flurd:
+; RV32XTHEADMEMIDX:       # %bb.0:
+; RV32XTHEADMEMIDX-NEXT:    th.flrd ft0, a0, a1, 3
+; RV32XTHEADMEMIDX-NEXT:    fadd.d fa0, ft0, ft0
+; RV32XTHEADMEMIDX-NEXT:    ret
+;
+; RV64XTHEADFMEMIDX-LABEL: flurd:
+; RV64XTHEADFMEMIDX:       # %bb.0:
+; RV64XTHEADFMEMIDX-NEXT:    th.flurd ft0, a0, a1, 3
+; RV64XTHEADFMEMIDX-NEXT:    fadd.d fa0, ft0, ft0
+; RV64XTHEADFMEMIDX-NEXT:    ret
+  %1 = zext i32 %b to i64
+  %2 = getelementptr double, double* %a, i64 %1
+  %3 = load double, double* %2, align 8
+  %4 = fadd double %3, %3
+  ret double %4
+}
+
+define void @fsrd(double* %a, i64 %b, double %c) {
+; RV32XTHEADMEMIDX-LABEL: fsrd:
+; RV32XTHEADMEMIDX:       # %bb.0:
+; RV32XTHEADMEMIDX-NEXT:    fadd.d ft0, fa0, fa0
+; RV32XTHEADMEMIDX-NEXT:    th.fsrd ft0, a0, a1, 3
+; RV32XTHEADMEMIDX-NEXT:    ret
+;
+; RV64XTHEADFMEMIDX-LABEL: fsrd:
+; RV64XTHEADFMEMIDX:       # %bb.0:
+; RV64XTHEADFMEMIDX-NEXT:    fadd.d ft0, fa0, fa0
+; RV64XTHEADFMEMIDX-NEXT:    th.fsrd ft0, a0, a1, 3
+; RV64XTHEADFMEMIDX-NEXT:    ret
+  %1 = fadd double %c, %c
+  %2 = getelementptr double, double* %a, i64 %b
+  store double %1, double* %2, align 8
+  ret void
+}
+
+define void @fsurd(double* %a, i32 %b, double %c) {
+; RV32XTHEADMEMIDX-LABEL: fsurd:
+; RV32XTHEADMEMIDX:       # %bb.0:
+; RV32XTHEADMEMIDX-NEXT:    fadd.d ft0, fa0, fa0
+; RV32XTHEADMEMIDX-NEXT:    th.fsrd ft0, a0, a1, 3
+; RV32XTHEADMEMIDX-NEXT:    ret
+;
+; RV64XTHEADFMEMIDX-LABEL: fsurd:
+; RV64XTHEADFMEMIDX:       # %bb.0:
+; RV64XTHEADFMEMIDX-NEXT:    fadd.d ft0, fa0, fa0
+; RV64XTHEADFMEMIDX-NEXT:    th.fsurd ft0, a0, a1, 3
+; RV64XTHEADFMEMIDX-NEXT:    ret
+  %1 = zext i32 %b to i64
+  %2 = fadd double %c, %c
+  %3 = getelementptr double, double* %a, i64 %1
+  store double %2, double* %3, align 8
+  ret void
+}

diff  --git a/llvm/test/MC/RISCV/rv32xtheadfmemidx-d-invalid.s b/llvm/test/MC/RISCV/rv32xtheadfmemidx-d-invalid.s
new file mode 100644
index 0000000000000..6b82f236968ab
--- /dev/null
+++ b/llvm/test/MC/RISCV/rv32xtheadfmemidx-d-invalid.s
@@ -0,0 +1,6 @@
+# RUN: not llvm-mc -triple riscv32 -mattr=+d -mattr=+xtheadfmemidx < %s 2>&1 | FileCheck %s
+
+th.flurd fa0, a1, a2, 0 # CHECK: :[[@LINE]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}}
+th.flurw fa0, a1, a2, 0 # CHECK: :[[@LINE]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}}
+th.fsurd fa0, a1, a2, 0 # CHECK: :[[@LINE]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}}
+th.fsurw fa0, a1, a2, 0 # CHECK: :[[@LINE]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}}

diff  --git a/llvm/test/MC/RISCV/rv32xtheadfmemidx-f-invalid.s b/llvm/test/MC/RISCV/rv32xtheadfmemidx-f-invalid.s
new file mode 100644
index 0000000000000..bf777fa4d4457
--- /dev/null
+++ b/llvm/test/MC/RISCV/rv32xtheadfmemidx-f-invalid.s
@@ -0,0 +1,8 @@
+# RUN: not llvm-mc -triple riscv32 -mattr=+f -mattr=+xtheadfmemidx < %s 2>&1 | FileCheck %s
+
+th.flrd fa0, a1, a2, 0  # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'D' (Double-Precision Floating-Point){{$}}
+th.fsrd fa0, a1, a2, 0  # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'D' (Double-Precision Floating-Point){{$}}
+th.flurd fa0, a1, a2, 0 # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'D' (Double-Precision Floating-Point), RV64I Base Instruction Set{{$}}
+th.flurw fa0, a1, a2, 0 # CHECK: :[[@LINE]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}}
+th.fsurd fa0, a1, a2, 0 # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'D' (Double-Precision Floating-Point), RV64I Base Instruction Set{{$}}
+th.fsurw fa0, a1, a2, 0 # CHECK: :[[@LINE]]:1: error: instruction requires the following: RV64I Base Instruction Set{{$}}

diff  --git a/llvm/test/MC/RISCV/rv32xtheadfmemidx-valid.s b/llvm/test/MC/RISCV/rv32xtheadfmemidx-valid.s
new file mode 100644
index 0000000000000..ae4bd91b435a0
--- /dev/null
+++ b/llvm/test/MC/RISCV/rv32xtheadfmemidx-valid.s
@@ -0,0 +1,37 @@
+# RUN: llvm-mc %s -triple=riscv32 -mattr=+d -mattr=+xtheadfmemidx -show-encoding \
+# RUN:     | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s
+# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+d -mattr=+xtheadfmemidx < %s \
+# RUN:     | llvm-objdump --mattr=+d --mattr=+xtheadfmemidx -d -r - \
+# RUN:     | FileCheck --check-prefix=CHECK-ASM-AND-OBJ %s
+
+# CHECK-ASM-AND-OBJ: th.flrd fa0, a1, a2, 0
+# CHECK-ASM: encoding: [0x0b,0xe5,0xc5,0x60]
+th.flrd fa0, a1, a2, 0
+
+# CHECK-ASM-AND-OBJ: th.flrd fa0, a1, a2, 3
+# CHECK-ASM: encoding: [0x0b,0xe5,0xc5,0x66]
+th.flrd fa0, a1, a2, 3
+
+# CHECK-ASM-AND-OBJ: th.flrw fa0, a1, a2, 0
+# CHECK-ASM: encoding: [0x0b,0xe5,0xc5,0x40]
+th.flrw fa0, a1, a2, 0
+
+# CHECK-ASM-AND-OBJ: th.flrw fa0, a1, a2, 3
+# CHECK-ASM: encoding: [0x0b,0xe5,0xc5,0x46]
+th.flrw fa0, a1, a2, 3
+
+# CHECK-ASM-AND-OBJ: th.fsrd fa0, a1, a2, 0
+# CHECK-ASM: encoding: [0x0b,0xf5,0xc5,0x60]
+th.fsrd fa0, a1, a2, 0
+
+# CHECK-ASM-AND-OBJ: th.fsrd fa0, a1, a2, 3
+# CHECK-ASM: encoding: [0x0b,0xf5,0xc5,0x66]
+th.fsrd fa0, a1, a2, 3
+
+# CHECK-ASM-AND-OBJ: th.fsrw fa0, a1, a2, 0
+# CHECK-ASM: encoding: [0x0b,0xf5,0xc5,0x40]
+th.fsrw fa0, a1, a2, 0
+
+# CHECK-ASM-AND-OBJ: th.fsrw fa0, a1, a2, 3
+# CHECK-ASM: encoding: [0x0b,0xf5,0xc5,0x46]
+th.fsrw fa0, a1, a2, 3

diff  --git a/llvm/test/MC/RISCV/rv64xtheadfmemidx-invalid.s b/llvm/test/MC/RISCV/rv64xtheadfmemidx-invalid.s
new file mode 100644
index 0000000000000..57082d667e463
--- /dev/null
+++ b/llvm/test/MC/RISCV/rv64xtheadfmemidx-invalid.s
@@ -0,0 +1,9 @@
+# RUN: not llvm-mc -triple riscv32 -mattr=+d -mattr=+xtheadfmemidx < %s 2>&1 | FileCheck %s
+# RUN: not llvm-mc -triple riscv64 -mattr=+d -mattr=+xtheadfmemidx < %s 2>&1 | FileCheck %s
+
+th.flrd fa0, a1, a2, 5     # CHECK: :[[@LINE]]:22: error: immediate must be an integer in the range [0, 3]
+th.flrd a0, a1, a2, 3      # CHECK: :[[@LINE]]:9: error: invalid operand for instruction
+th.flrw 0(fa0), a1, a2, 0  # CHECK: :[[@LINE]]:9: error: invalid operand for instruction
+th.flrw fa0, 4(a1), a2, 3  # CHECK: :[[@LINE]]:14: error: invalid operand for instruction
+th.fsrd fa0, a1, -1(a2), 0 # CHECK: :[[@LINE]]:18: error: invalid operand for instruction
+th.fsrd fa0, a1, a2, -3    # CHECK: :[[@LINE]]:22: error: immediate must be an integer in the range [0, 3]

diff  --git a/llvm/test/MC/RISCV/rv64xtheadfmemidx-valid.s b/llvm/test/MC/RISCV/rv64xtheadfmemidx-valid.s
new file mode 100644
index 0000000000000..0ba43f1fd32af
--- /dev/null
+++ b/llvm/test/MC/RISCV/rv64xtheadfmemidx-valid.s
@@ -0,0 +1,69 @@
+# RUN: llvm-mc %s -triple=riscv64 -mattr=+d -mattr=+xtheadfmemidx -show-encoding \
+# RUN:     | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s
+# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+d -mattr=+xtheadfmemidx < %s \
+# RUN:     | llvm-objdump --mattr=+d --mattr=+xtheadfmemidx -d -r - \
+# RUN:     | FileCheck --check-prefix=CHECK-ASM-AND-OBJ %s
+
+# CHECK-ASM-AND-OBJ: th.flrd fa0, a1, a2, 0
+# CHECK-ASM: encoding: [0x0b,0xe5,0xc5,0x60]
+th.flrd fa0, a1, a2, 0
+
+# CHECK-ASM-AND-OBJ: th.flrd fa0, a1, a2, 3
+# CHECK-ASM: encoding: [0x0b,0xe5,0xc5,0x66]
+th.flrd fa0, a1, a2, 3
+
+# CHECK-ASM-AND-OBJ: th.flrw fa0, a1, a2, 0
+# CHECK-ASM: encoding: [0x0b,0xe5,0xc5,0x40]
+th.flrw fa0, a1, a2, 0
+
+# CHECK-ASM-AND-OBJ: th.flrw fa0, a1, a2, 3
+# CHECK-ASM: encoding: [0x0b,0xe5,0xc5,0x46]
+th.flrw fa0, a1, a2, 3
+
+# CHECK-ASM-AND-OBJ: th.flurd fa0, a1, a2, 0
+# CHECK-ASM: encoding: [0x0b,0xe5,0xc5,0x70]
+th.flurd fa0, a1, a2, 0
+
+# CHECK-ASM-AND-OBJ: th.flurd fa0, a1, a2, 3
+# CHECK-ASM: encoding: [0x0b,0xe5,0xc5,0x76]
+th.flurd fa0, a1, a2, 3
+
+# CHECK-ASM-AND-OBJ: th.flurw fa0, a1, a2, 0
+# CHECK-ASM: encoding: [0x0b,0xe5,0xc5,0x50]
+th.flurw fa0, a1, a2, 0
+
+# CHECK-ASM-AND-OBJ: th.flurw fa0, a1, a2, 3
+# CHECK-ASM: encoding: [0x0b,0xe5,0xc5,0x56]
+th.flurw fa0, a1, a2, 3
+
+# CHECK-ASM-AND-OBJ: th.fsrd fa0, a1, a2, 0
+# CHECK-ASM: encoding: [0x0b,0xf5,0xc5,0x60]
+th.fsrd fa0, a1, a2, 0
+
+# CHECK-ASM-AND-OBJ: th.fsrd fa0, a1, a2, 3
+# CHECK-ASM: encoding: [0x0b,0xf5,0xc5,0x66]
+th.fsrd fa0, a1, a2, 3
+
+# CHECK-ASM-AND-OBJ: th.fsrw fa0, a1, a2, 0
+# CHECK-ASM: encoding: [0x0b,0xf5,0xc5,0x40]
+th.fsrw fa0, a1, a2, 0
+
+# CHECK-ASM-AND-OBJ: th.fsrw fa0, a1, a2, 3
+# CHECK-ASM: encoding: [0x0b,0xf5,0xc5,0x46]
+th.fsrw fa0, a1, a2, 3
+
+# CHECK-ASM-AND-OBJ: th.fsurd fa0, a1, a2, 0
+# CHECK-ASM: encoding: [0x0b,0xf5,0xc5,0x70]
+th.fsurd fa0, a1, a2, 0
+
+# CHECK-ASM-AND-OBJ: th.fsurd fa0, a1, a2, 3
+# CHECK-ASM: encoding: [0x0b,0xf5,0xc5,0x76]
+th.fsurd fa0, a1, a2, 3
+
+# CHECK-ASM-AND-OBJ: th.fsurw fa0, a1, a2, 0
+# CHECK-ASM: encoding: [0x0b,0xf5,0xc5,0x50]
+th.fsurw fa0, a1, a2, 0
+
+# CHECK-ASM-AND-OBJ: th.fsurw fa0, a1, a2, 3
+# CHECK-ASM: encoding: [0x0b,0xf5,0xc5,0x56]
+th.fsurw fa0, a1, a2, 3


        


More information about the llvm-commits mailing list