[llvm] 480202f - [RISCV] Add Zilsd and Zclsd Extensions (#131094)

via llvm-commits llvm-commits at lists.llvm.org
Wed Mar 19 08:53:45 PDT 2025


Author: dong-miao
Date: 2025-03-19T08:53:41-07:00
New Revision: 480202f0d16f7dbc5c650aea6e8dfd9eca5b999d

URL: https://github.com/llvm/llvm-project/commit/480202f0d16f7dbc5c650aea6e8dfd9eca5b999d
DIFF: https://github.com/llvm/llvm-project/commit/480202f0d16f7dbc5c650aea6e8dfd9eca5b999d.diff

LOG: [RISCV] Add Zilsd and Zclsd Extensions (#131094)

This commit adds the Load/Store pair instructions (Zilsd) and Compressed
Load/Store pair instructions (Zclsd).

[Specification
link](https://github.com/riscv/riscv-isa-manual/blob/main/src/zilsd.adoc).

Added: 
    llvm/lib/Target/RISCV/RISCVInstrInfoZclsd.td
    llvm/lib/Target/RISCV/RISCVInstrInfoZilsd.td
    llvm/test/MC/RISCV/rv32zclsd-invalid.s
    llvm/test/MC/RISCV/rv32zclsd-valid.s
    llvm/test/MC/RISCV/rv32zilsd-invalid.s
    llvm/test/MC/RISCV/rv32zilsd-valid.s

Modified: 
    clang/test/Driver/print-supported-extensions-riscv.c
    clang/test/Preprocessor/riscv-target-features.c
    llvm/docs/RISCVUsage.rst
    llvm/docs/ReleaseNotes.md
    llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
    llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
    llvm/lib/Target/RISCV/RISCVFeatures.td
    llvm/lib/Target/RISCV/RISCVInstrInfo.td
    llvm/lib/TargetParser/RISCVISAInfo.cpp
    llvm/test/CodeGen/RISCV/attributes.ll
    llvm/test/MC/RISCV/attribute-arch.s
    llvm/test/MC/RISCV/rv64c-valid.s
    llvm/unittests/TargetParser/RISCVISAInfoTest.cpp

Removed: 
    


################################################################################
diff  --git a/clang/test/Driver/print-supported-extensions-riscv.c b/clang/test/Driver/print-supported-extensions-riscv.c
index 019106abfabc3..35de2820ef84f 100644
--- a/clang/test/Driver/print-supported-extensions-riscv.c
+++ b/clang/test/Driver/print-supported-extensions-riscv.c
@@ -29,6 +29,7 @@
 // CHECK-NEXT:     zihintntl            1.0       'Zihintntl' (Non-Temporal Locality Hints)
 // CHECK-NEXT:     zihintpause          2.0       'Zihintpause' (Pause Hint)
 // CHECK-NEXT:     zihpm                2.0       'Zihpm' (Hardware Performance Counters)
+// CHECK-NEXT:     zilsd                1.0       'Zilsd' (Load/Store Pair Instructions)
 // CHECK-NEXT:     zimop                1.0       'Zimop' (May-Be-Operations)
 // CHECK-NEXT:     zmmul                1.0       'Zmmul' (Integer Multiplication)
 // CHECK-NEXT:     za128rs              1.0       'Za128rs' (Reservation Set Size of at Most 128 Bytes)
@@ -50,6 +51,7 @@
 // CHECK-NEXT:     zcd                  1.0       'Zcd' (Compressed Double-Precision Floating-Point Instructions)
 // CHECK-NEXT:     zce                  1.0       'Zce' (Compressed extensions for microcontrollers)
 // CHECK-NEXT:     zcf                  1.0       'Zcf' (Compressed Single-Precision Floating-Point Instructions)
+// CHECK-NEXT:     zclsd                1.0       'Zclsd' (Compressed Load/Store Pair Instructions)
 // CHECK-NEXT:     zcmop                1.0       'Zcmop' (Compressed May-Be-Operations)
 // CHECK-NEXT:     zcmp                 1.0       'Zcmp' (sequenced instructions for code-size reduction)
 // CHECK-NEXT:     zcmt                 1.0       'Zcmt' (table jump instructions for code-size reduction)

diff  --git a/clang/test/Preprocessor/riscv-target-features.c b/clang/test/Preprocessor/riscv-target-features.c
index c219771135275..67e4dfc3db3e9 100644
--- a/clang/test/Preprocessor/riscv-target-features.c
+++ b/clang/test/Preprocessor/riscv-target-features.c
@@ -108,6 +108,7 @@
 // CHECK-NOT: __riscv_zcd {{.*$}}
 // CHECK-NOT: __riscv_zce {{.*$}}
 // CHECK-NOT: __riscv_zcf {{.*$}}
+// CHECK-NOT: __riscv_zclsd {{.*$}}
 // CHECK-NOT: __riscv_zcmop {{.*$}}
 // CHECK-NOT: __riscv_zcmp {{.*$}}
 // CHECK-NOT: __riscv_zcmt {{.*$}}
@@ -133,6 +134,7 @@
 // CHECK-NOT: __riscv_zihintntl {{.*$}}
 // CHECK-NOT: __riscv_zihintpause {{.*$}}
 // CHECK-NOT: __riscv_zihpm {{.*$}}
+// CHECK-NOT: __riscv_zilsd {{.*$}}
 // CHECK-NOT: __riscv_zimop {{.*$}}
 // CHECK-NOT: __riscv_zk {{.*$}}
 // CHECK-NOT: __riscv_zkn {{.*$}}
@@ -922,6 +924,11 @@
 // RUN:   -o - | FileCheck --check-prefix=CHECK-ZCF-EXT %s
 // CHECK-ZCF-EXT: __riscv_zcf 1000000{{$}}
 
+// RUN: %clang --target=riscv32-unknown-linux-gnu \
+// RUN:   -march=rv32i_zclsd1p0 -E -dM %s \
+// RUN:   -o - | FileCheck --check-prefix=CHECK-ZCLSD-EXT %s
+// CHECK-ZCLSD-EXT: __riscv_zclsd  1000000{{$}}
+
 // RUN: %clang --target=riscv32-unknown-linux-gnu \
 // RUN:   -march=rv32i_zcmop1p0 -E -dM %s \
 // RUN:   -o - | FileCheck --check-prefix=CHECK-ZCMOP-EXT %s
@@ -1118,6 +1125,11 @@
 // RUN:   -o - | FileCheck --check-prefix=CHECK-ZIHPM-EXT %s
 // CHECK-ZIHPM-EXT: __riscv_zihpm 2000000{{$}}
 
+// RUN: %clang --target=riscv32-unknown-linux-gnu \
+// RUN:   -march=rv32i_zilsd1p0 -E -dM %s \
+// RUN:   -o - | FileCheck --check-prefix=CHECK-ZILSD-EXT %s
+// CHECK-ZILSD-EXT: __riscv_zilsd  1000000{{$}}
+
 // RUN: %clang --target=riscv32-unknown-linux-gnu \
 // RUN:   -march=rv32i_zimop1p0 -E -dM %s \
 // RUN:   -o - | FileCheck --check-prefix=CHECK-ZIMOP-EXT %s

diff  --git a/llvm/docs/RISCVUsage.rst b/llvm/docs/RISCVUsage.rst
index cf7be8b2c5c96..d6ac226dad5e6 100644
--- a/llvm/docs/RISCVUsage.rst
+++ b/llvm/docs/RISCVUsage.rst
@@ -179,6 +179,7 @@ on support follow.
      ``Zcb``           Supported
      ``Zcd``           Supported
      ``Zcf``           Supported
+     ``Zclsd``         Assembly Support
      ``Zcmop``         Supported
      ``Zcmp``          Supported
      ``Zcmt``          Assembly Support
@@ -205,6 +206,7 @@ on support follow.
      ``Zihintntl``     Supported
      ``Zihintpause``   Assembly Support
      ``Zihpm``         (`See Note <#riscv-i2p1-note>`__)
+     ``Zilsd``         Assembly Support
      ``Zimop``         Supported
      ``Zkn``           Supported
      ``Zknd``          Supported (`See note <#riscv-scalar-crypto-note2>`__)

diff  --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md
index b191a840d9803..30d66b4a77a71 100644
--- a/llvm/docs/ReleaseNotes.md
+++ b/llvm/docs/ReleaseNotes.md
@@ -128,6 +128,10 @@ Changes to the RISC-V Backend
 * Added non-quadratic ``log-vrgather`` cost model for ``vrgather.vv`` instruction
 * Adds experimental assembler support for the Qualcomm uC 'Xqcisim` (Simulation Hint)
   extension.
+* Adds assembler support for the 'Zilsd` (Load/Store Pair Instructions)
+  extension.
+* Adds assembler support for the 'Zclsd` (Compressed Load/Store Pair Instructions)
+  extension.
 
 Changes to the WebAssembly Backend
 ----------------------------------

diff  --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index 433e95d2bca19..ce25380cbdda2 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -487,6 +487,18 @@ struct RISCVOperand final : public MCParsedAsmOperand {
                Reg.RegNum);
   }
 
+  bool isGPRPairC() const {
+    return Kind == KindTy::Register &&
+           RISCVMCRegisterClasses[RISCV::GPRPairCRegClassID].contains(
+               Reg.RegNum);
+  }
+
+  bool isGPRPairNoX0() const {
+    return Kind == KindTy::Register &&
+           RISCVMCRegisterClasses[RISCV::GPRPairNoX0RegClassID].contains(
+               Reg.RegNum);
+  }
+
   bool isGPRF16() const {
     return Kind == KindTy::Register &&
            RISCVMCRegisterClasses[RISCV::GPRF16RegClassID].contains(Reg.RegNum);

diff  --git a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
index e3c4cc36ee822..05bb6d30cc9a7 100644
--- a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
+++ b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
@@ -224,6 +224,22 @@ static DecodeStatus DecodeGPRPairRegisterClass(MCInst &Inst, uint32_t RegNo,
   return MCDisassembler::Success;
 }
 
+static DecodeStatus DecodeGPRPairCRegisterClass(MCInst &Inst, uint32_t RegNo,
+                                                uint64_t Address,
+                                                const MCDisassembler *Decoder) {
+  if (RegNo >= 8 || RegNo % 2)
+    return MCDisassembler::Fail;
+
+  const RISCVDisassembler *Dis =
+      static_cast<const RISCVDisassembler *>(Decoder);
+  const MCRegisterInfo *RI = Dis->getContext().getRegisterInfo();
+  MCRegister Reg = RI->getMatchingSuperReg(
+      RISCV::X8 + RegNo, RISCV::sub_gpr_even,
+      &RISCVMCRegisterClasses[RISCV::GPRPairCRegClassID]);
+  Inst.addOperand(MCOperand::createReg(Reg));
+  return MCDisassembler::Success;
+}
+
 static DecodeStatus DecodeSR07RegisterClass(MCInst &Inst, uint32_t RegNo,
                                             uint64_t Address,
                                             const void *Decoder) {

diff  --git a/llvm/lib/Target/RISCV/RISCVFeatures.td b/llvm/lib/Target/RISCV/RISCVFeatures.td
index 74224b2e150e4..f23a855e7049f 100644
--- a/llvm/lib/Target/RISCV/RISCVFeatures.td
+++ b/llvm/lib/Target/RISCV/RISCVFeatures.td
@@ -176,6 +176,13 @@ def HasStdExtZicfiss : Predicate<"Subtarget->hasStdExtZicfiss()">,
                                           "'Zicfiss' (Shadow stack)">;
 def NoHasStdExtZicfiss : Predicate<"!Subtarget->hasStdExtZicfiss()">;
 
+def FeatureStdExtZilsd
+    : RISCVExtension<1, 0,
+                     "Load/Store Pair Instructions">;
+def HasStdExtZilsd : Predicate<"Subtarget->hasStdExtZilsd()">,
+                       AssemblerPredicate<(all_of FeatureStdExtZilsd),
+                                          "'Zilsd' (Load/Store pair instructions)">;
+
 // Multiply Extensions
 
 def FeatureStdExtZmmul
@@ -401,6 +408,14 @@ def FeatureStdExtZcf
                      "Compressed Single-Precision Floating-Point Instructions",
                      [FeatureStdExtF, FeatureStdExtZca]>;
 
+def FeatureStdExtZclsd
+    : RISCVExtension<1, 0,
+                     "Compressed Load/Store Pair Instructions",
+                     [FeatureStdExtZilsd,FeatureStdExtZca]>;     
+def HasStdExtZclsd : Predicate<"Subtarget->hasStdExtZclsd()">,
+                    AssemblerPredicate<(all_of FeatureStdExtZclsd),
+                        "'Zclsd' (Compressed Load/Store pair instructions)">;
+
 def FeatureStdExtZcmp
     : RISCVExtension<1, 0,
                      "sequenced instructions for code-size reduction",

diff  --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
index 6be4fb1db602d..02398219c5105 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
@@ -2144,11 +2144,13 @@ include "RISCVInstrInfoZimop.td"
 include "RISCVInstrInfoZicbo.td"
 include "RISCVInstrInfoZicond.td"
 include "RISCVInstrInfoZicfiss.td"
+include "RISCVInstrInfoZilsd.td"
 
 // Compressed
 include "RISCVInstrInfoC.td"
 include "RISCVInstrInfoZc.td"
 include "RISCVInstrInfoZcmop.td"
+include "RISCVInstrInfoZclsd.td"
 
 //===----------------------------------------------------------------------===//
 // Vendor extensions

diff  --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZclsd.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZclsd.td
new file mode 100644
index 0000000000000..d130025b450d6
--- /dev/null
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZclsd.td
@@ -0,0 +1,107 @@
+//===-- RISCVInstrInfoZclsd.td -----------------------------*- tablegen -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file describes the RISC-V instructions from the standard 'Zclsd',
+// Compressed Load/Store pair instructions extension.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// Instruction Class Templates
+//===----------------------------------------------------------------------===//
+
+def GPRPairNoX0RV32Operand : AsmOperandClass {
+  let Name = "GPRPairNoX0RV32";
+  let ParserMethod = "parseGPRPair<false>";
+  let PredicateMethod = "isGPRPairNoX0";
+  let RenderMethod = "addRegOperands";
+}
+
+def GPRPairNoX0RV32 : RegisterOperand<GPRPairNoX0> {
+  let ParserMatchClass = GPRPairNoX0RV32Operand;
+}
+
+def GPRPairCRV32Operand : AsmOperandClass {
+  let Name = "GPRPairCRV32";
+  let ParserMethod = "parseGPRPair<false>";
+  let PredicateMethod = "isGPRPairC";
+  let RenderMethod = "addRegOperands";
+}
+
+def GPRPairCRV32 : RegisterOperand<GPRPairC> {
+  let ParserMatchClass = GPRPairCRV32Operand;
+}
+
+let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in
+class PairCStackLoad<bits<3> funct3, string OpcodeStr,
+                     DAGOperand RC, DAGOperand opnd>
+    : RVInst16CI<funct3, 0b10, (outs RC:$rd), (ins SPMem:$rs1, opnd:$imm),
+                 OpcodeStr, "$rd, ${imm}(${rs1})">;
+
+let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
+class PairCStackStore<bits<3> funct3, string OpcodeStr,
+                      DAGOperand RC, DAGOperand opnd>
+    : RVInst16CSS<funct3, 0b10, (outs), (ins RC:$rs2, SPMem:$rs1, opnd:$imm),
+                  OpcodeStr, "$rs2, ${imm}(${rs1})">;
+
+let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in
+class PairCLoad_ri<bits<3> funct3, string OpcodeStr,
+                  DAGOperand RC, DAGOperand opnd>
+    : RVInst16CL<funct3, 0b00, (outs RC:$rd), (ins GPRCMem:$rs1, opnd:$imm),
+                 OpcodeStr, "$rd, ${imm}(${rs1})">;
+
+let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
+class PairCStore_rri<bits<3> funct3, string OpcodeStr,
+                     DAGOperand RC, DAGOperand opnd>
+    : RVInst16CS<funct3, 0b00, (outs), (ins RC:$rs2,GPRCMem:$rs1, opnd:$imm),
+                 OpcodeStr, "$rs2, ${imm}(${rs1})">;
+                 
+//===----------------------------------------------------------------------===//
+// Instructions
+//===----------------------------------------------------------------------===//
+
+let Predicates = [HasStdExtZclsd, IsRV32], DecoderNamespace = "ZcOverlap" in {
+def C_LDSP_RV32 : PairCStackLoad<0b011, "c.ldsp", GPRPairNoX0RV32, uimm9_lsb000>,
+                  Sched<[WriteLDD, ReadMemBase]> {
+  let Inst{4-2} = imm{8-6};
+}
+
+def C_SDSP_RV32 : PairCStackStore<0b111, "c.sdsp", GPRPairRV32, uimm9_lsb000>,
+                  Sched<[WriteSTD, ReadStoreData, ReadMemBase]> {
+  let Inst{9-7} = imm{8-6};
+}
+
+def C_LD_RV32 : PairCLoad_ri<0b011, "c.ld", GPRPairCRV32, uimm8_lsb000>,
+                Sched<[WriteLDD, ReadMemBase]> {
+  bits<8> imm;
+  let Inst{12-10} = imm{5-3};
+  let Inst{6-5} = imm{7-6};
+}
+
+def C_SD_RV32 : PairCStore_rri<0b111, "c.sd", GPRPairCRV32, uimm8_lsb000>,
+                Sched<[WriteSTD, ReadStoreData, ReadMemBase]> {
+  bits<8> imm;
+  let Inst{12-10} = imm{5-3};
+  let Inst{6-5} = imm{7-6};
+}
+}// Predicates = [HasStdExtZclsd, IsRV32], DecoderNamespace = "ZcOverlap"
+
+//===----------------------------------------------------------------------===//
+// Compress Instruction tablegen backend.
+//===----------------------------------------------------------------------===//
+
+let Predicates = [HasStdExtZclsd, IsRV32] in {
+def : CompressPat<(LD_RV32 GPRPairNoX0RV32:$rd, SPMem:$rs1, uimm9_lsb000:$imm),
+                  (C_LDSP_RV32 GPRPairNoX0RV32:$rd, SPMem:$rs1, uimm9_lsb000:$imm)>;
+def : CompressPat<(SD_RV32 GPRPairRV32:$rs2, SPMem:$rs1, uimm9_lsb000:$imm),
+                  (C_SDSP_RV32 GPRPairRV32:$rs2, SPMem:$rs1, uimm9_lsb000:$imm)>;
+def : CompressPat<(LD_RV32 GPRPairCRV32:$rd, GPRCMem:$rs1, uimm8_lsb000:$imm),
+                  (C_LD_RV32 GPRPairCRV32:$rd, GPRCMem:$rs1, uimm8_lsb000:$imm)>;
+def : CompressPat<(SD_RV32 GPRPairCRV32:$rs2, GPRCMem:$rs1, uimm8_lsb000:$imm),
+                  (C_SD_RV32 GPRPairCRV32:$rs2, GPRCMem:$rs1, uimm8_lsb000:$imm)>;
+} // Predicates = [HasStdExtZclsd, IsRV32]

diff  --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZilsd.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZilsd.td
new file mode 100644
index 0000000000000..a8923ae317a3f
--- /dev/null
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZilsd.td
@@ -0,0 +1,38 @@
+//===-- RISCVInstrInfoZilsd.td -----------------------------*- tablegen -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file describes the RISC-V instructions from the standard 'Zilsd',
+// Load/Store pair instructions extension.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// Instruction Class Templates
+//===----------------------------------------------------------------------===//
+
+let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in
+class PairLoad_ri<string opcodestr, DAGOperand RC>
+    : RVInstI<0b011, OPC_LOAD, (outs RC:$rd), 
+              (ins GPRMem:$rs1, simm12:$imm12),
+              opcodestr, "${rd}, ${imm12}(${rs1})">;
+
+let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
+class PairStore_rri<string opcodestr, DAGOperand RC>
+    : RVInstS<0b011, OPC_STORE, (outs),
+              (ins RC:$rs2, GPRMem:$rs1, simm12:$imm12),
+              opcodestr, "${rs2}, ${imm12}(${rs1})">;
+
+//===----------------------------------------------------------------------===//
+// Instructions
+//===----------------------------------------------------------------------===//
+
+let Predicates = [HasStdExtZilsd, IsRV32], DecoderNamespace = "RV32Only" in {
+def LD_RV32 : PairLoad_ri<"ld", GPRPairRV32>, Sched<[WriteLDD, ReadMemBase]>;
+def SD_RV32 : PairStore_rri<"sd", GPRPairRV32>, Sched<[WriteSTD, ReadStoreData,
+                            ReadMemBase]>;
+} // Predicates = [HasStdExtZilsd, IsRV32], DecoderNamespace = "RV32Only"

diff  --git a/llvm/lib/TargetParser/RISCVISAInfo.cpp b/llvm/lib/TargetParser/RISCVISAInfo.cpp
index d10c334330a14..11d4b3746e94d 100644
--- a/llvm/lib/TargetParser/RISCVISAInfo.cpp
+++ b/llvm/lib/TargetParser/RISCVISAInfo.cpp
@@ -780,6 +780,14 @@ Error RISCVISAInfo::checkDependency() {
       return getIncompatibleError("xwchc", "zcb");
   }
 
+  if (Exts.count("zclsd") != 0) {
+    if (XLen != 32)
+      return getError("'zclsd' is only supported for 'rv32'");
+
+    if (Exts.count("zcf") != 0)
+      return getIncompatibleError("zclsd", "zcf");
+  }
+
   for (auto Ext : XqciExts)
     if (Exts.count(Ext.str()) && (XLen != 32))
       return getError("'" + Twine(Ext) + "'" + " is only supported for 'rv32'");

diff  --git a/llvm/test/CodeGen/RISCV/attributes.ll b/llvm/test/CodeGen/RISCV/attributes.ll
index a5cbc7f0cf882..344438e554ce6 100644
--- a/llvm/test/CodeGen/RISCV/attributes.ll
+++ b/llvm/test/CodeGen/RISCV/attributes.ll
@@ -128,7 +128,9 @@
 ; RUN: llc -mtriple=riscv32 -mattr=+zve32x -mattr=+zvkt %s -o - | FileCheck --check-prefix=RV32ZVKT %s
 ; RUN: llc -mtriple=riscv32 -mattr=+zvfh %s -o - | FileCheck --check-prefix=RV32ZVFH %s
 ; RUN: llc -mtriple=riscv32 -mattr=+zicond %s -o - | FileCheck --check-prefix=RV32ZICOND %s
+; RUN: llc -mtriple=riscv32 -mattr=+zilsd %s -o - | FileCheck --check-prefix=RV32ZILSD %s
 ; RUN: llc -mtriple=riscv32 -mattr=+zimop %s -o - | FileCheck --check-prefix=RV32ZIMOP %s
+; RUN: llc -mtriple=riscv32 -mattr=+zclsd %s -o - | FileCheck --check-prefix=RV32ZCLSD %s
 ; RUN: llc -mtriple=riscv32 -mattr=+zcmop %s -o - | FileCheck --check-prefix=RV32ZCMOP %s
 ; RUN: llc -mtriple=riscv32 -mattr=+smaia %s -o - | FileCheck --check-prefixes=CHECK,RV32SMAIA %s
 ; RUN: llc -mtriple=riscv32 -mattr=+ssaia %s -o - | FileCheck --check-prefixes=CHECK,RV32SSAIA %s
@@ -453,7 +455,9 @@
 ; RV32ZVKT: .attribute 5, "rv32i2p1_zicsr2p0_zve32x1p0_zvkt1p0_zvl32b1p0"
 ; RV32ZVFH: .attribute 5, "rv32i2p1_f2p2_zicsr2p0_zfhmin1p0_zve32f1p0_zve32x1p0_zvfh1p0_zvfhmin1p0_zvl32b1p0"
 ; RV32ZICOND: .attribute 5, "rv32i2p1_zicond1p0"
+; RV32ZILSD: .attribute 5, "rv32i2p1_zilsd1p0"
 ; RV32ZIMOP: .attribute 5, "rv32i2p1_zimop1p0"
+; RV32ZCLSD: .attribute 5, "rv32i2p1_zilsd1p0_zca1p0_zclsd1p0"
 ; RV32ZCMOP: .attribute 5, "rv32i2p1_zca1p0_zcmop1p0"
 ; RV32SMAIA: .attribute 5, "rv32i2p1_smaia1p0"
 ; RV32SSAIA: .attribute 5, "rv32i2p1_ssaia1p0"

diff  --git a/llvm/test/MC/RISCV/attribute-arch.s b/llvm/test/MC/RISCV/attribute-arch.s
index a8bb9b7e6cef1..574b4cb45437e 100644
--- a/llvm/test/MC/RISCV/attribute-arch.s
+++ b/llvm/test/MC/RISCV/attribute-arch.s
@@ -255,6 +255,9 @@
 .attribute arch, "rv32izcb1p0"
 # CHECK: attribute      5, "rv32i2p1_zca1p0_zcb1p0"
 
+.attribute arch, "rv32izclsd1p0"
+# CHECK: attribute      5, "rv32i2p1_zilsd1p0_zca1p0_zclsd1p0"
+
 .attribute arch, "rv32izcmp1p0"
 # CHECK: attribute      5, "rv32i2p1_zca1p0_zcmp1p0"
 
@@ -429,6 +432,9 @@
 .attribute arch, "rv32i_zicfiss1p0"
 # CHECK: .attribute     5, "rv32i2p1_zicfiss1p0_zicsr2p0_zimop1p0"
 
+.attribute arch, "rv32i_zilsd1p0"
+# CHECK: .attribute     5, "rv32i2p1_zilsd1p0"
+
 .attribute arch, "rv64i_xsfvfwmaccqqq"
 # CHECK: attribute      5, "rv64i2p1_f2p2_zicsr2p0_zve32f1p0_zve32x1p0_zvfbfmin1p0_zvl32b1p0_xsfvfwmaccqqq1p0"
 

diff  --git a/llvm/test/MC/RISCV/rv32zclsd-invalid.s b/llvm/test/MC/RISCV/rv32zclsd-invalid.s
new file mode 100644
index 0000000000000..78e391c56ab87
--- /dev/null
+++ b/llvm/test/MC/RISCV/rv32zclsd-invalid.s
@@ -0,0 +1,22 @@
+# RUN: not llvm-mc -triple=riscv32 -mattr=+zclsd < %s 2>&1 | FileCheck %s
+
+## GPRPairC
+c.ld t1, 4(sp) # CHECK: :[[@LINE]]:6: error: invalid operand for instruction
+c.sd s2, 4(sp) # CHECK: :[[@LINE]]:6: error: invalid operand for instruction
+
+## GPRPairNoX0
+c.ldsp  x0, 4(sp) # CHECK: :[[@LINE]]:9: error: invalid operand for instruction
+c.ldsp  zero, 4(sp) # CHECK: :[[@LINE]]:9: error: invalid operand for instruction
+
+## uimm9_lsb000
+c.ldsp t1, 512(sp) # CHECK: :[[@LINE]]:12: error: immediate must be a multiple of 8 bytes in the range [0, 504]
+c.sdsp t1, -8(sp) # CHECK: :[[@LINE]]:12: error: immediate must be a multiple of 8 bytes in the range [0, 504]
+## uimm8_lsb000
+c.ld  s0, -8(sp) # CHECK: :[[@LINE]]:11: error: immediate must be a multiple of 8 bytes in the range [0, 248]
+c.sd  s0, 256(sp) # CHECK: :[[@LINE]]:11: error: immediate must be a multiple of 8 bytes in the range [0, 248]
+
+# Invalid register names
+c.ld a1, 4(sp) # CHECK: :[[@LINE]]:6: error: register must be even
+c.sd a3, 4(sp) # CHECK: :[[@LINE]]:6: error: register must be even
+c.ldsp ra, 4(sp) # CHECK: :[[@LINE]]:8: error: register must be even
+c.ldsp t0, 4(sp) # CHECK: :[[@LINE]]:8: error: register must be even

diff  --git a/llvm/test/MC/RISCV/rv32zclsd-valid.s b/llvm/test/MC/RISCV/rv32zclsd-valid.s
new file mode 100644
index 0000000000000..1afe5a0b2760b
--- /dev/null
+++ b/llvm/test/MC/RISCV/rv32zclsd-valid.s
@@ -0,0 +1,18 @@
+# RUN: llvm-mc %s -triple=riscv32 -mattr=+zclsd -M no-aliases -show-encoding \
+# RUN:     | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s
+# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+zclsd< %s \
+# RUN:     | llvm-objdump --mattr=+zclsd --no-print-imm-hex -M no-aliases -d -r - \
+# RUN:     | FileCheck --check-prefix=CHECK-ASM-AND-OBJ %s
+
+# CHECK-ASM-AND-OBJ: c.ldsp t1, 176(sp)
+# CHECK-ASM: encoding: [0x4a,0x73]
+c.ldsp t1, 176(sp)
+# CHECK-ASM-AND-OBJ: c.sdsp t1, 360(sp)
+# CHECK-ASM: encoding: [0x9a,0xf6]
+c.sdsp t1, 360(sp)
+# CHECK-ASM-AND-OBJ: c.ld a4, 0(a3)
+# CHECK-ASM: encoding: [0x98,0x62]
+c.ld a4, 0(a3)
+# CHECK-ASM-AND-OBJ: c.sd s0, 248(a3)
+# CHECK-ASM: encoding: [0xe0,0xfe]
+c.sd s0, 248(a3)

diff  --git a/llvm/test/MC/RISCV/rv32zilsd-invalid.s b/llvm/test/MC/RISCV/rv32zilsd-invalid.s
new file mode 100644
index 0000000000000..421358c29d68c
--- /dev/null
+++ b/llvm/test/MC/RISCV/rv32zilsd-invalid.s
@@ -0,0 +1,12 @@
+# RUN: not llvm-mc -triple riscv32 -mattr=+zilsd < %s 2>&1 | FileCheck %s
+
+# Out of range immediates
+## simm12
+ld t1, -2049(a0) # CHECK: :[[@LINE]]:8: error: operand must be a symbol with %lo/%pcrel_lo/%tprel_lo modifier or an integer in the range [-2048, 2047]
+sd t1, 2048(a0) # CHECK: :[[@LINE]]:8: error: operand must be a symbol with %lo/%pcrel_lo/%tprel_lo modifier or an integer in the range [-2048, 2047]
+
+# Invalid register names
+ld t2, (4)a0 # CHECK: :[[@LINE]]:4: error: register must be even
+ld s3, (4)a0 # CHECK: :[[@LINE]]:4: error: register must be even
+sd t2, (10)s2 # CHECK: :[[@LINE]]:4: error: register must be even
+sd a7, (10)s2 # CHECK: :[[@LINE]]:4: error: register must be even

diff  --git a/llvm/test/MC/RISCV/rv32zilsd-valid.s b/llvm/test/MC/RISCV/rv32zilsd-valid.s
new file mode 100644
index 0000000000000..d9f81e6dd7fac
--- /dev/null
+++ b/llvm/test/MC/RISCV/rv32zilsd-valid.s
@@ -0,0 +1,25 @@
+# RUN: llvm-mc %s -triple=riscv32 -mattr=+zilsd -M no-aliases -show-encoding \
+# RUN:     | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s
+# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+zilsd < %s \
+# RUN:     | llvm-objdump  --mattr=+zilsd --no-print-imm-hex -M no-aliases -d -r - \
+# RUN:     | FileCheck --check-prefix=CHECK-ASM-AND-OBJ %s
+
+# CHECK-ASM-AND-OBJ: ld t1, 12(a0)
+# CHECK-ASM: encoding: [0x03,0x33,0xc5,0x00]
+ld t1, 12(a0)
+# CHECK-ASM-AND-OBJ: ld a0, 4(a2)
+# CHECK-ASM: encoding: [0x03,0x35,0x46,0x00]
+ld a0, +4(a2)
+# CHECK-ASM-AND-OBJ: ld t1, -2048(a4)
+# CHECK-ASM: encoding: [0x03,0x33,0x07,0x80]
+ld t1, -2048(a4)
+# CHECK-ASM-AND-OBJ: ld t1, 2047(a4)
+# CHECK-ASM: encoding: [0x03,0x33,0xf7,0x7f]
+ld t1, 2047(a4)
+
+# CHECK-ASM-AND-OBJ: sd s0, 2047(a0)
+# CHECK-ASM: encoding: [0xa3,0x3f,0x85,0x7e]
+sd s0, 2047(a0)
+# CHECK-ASM-AND-OBJ: sd a0, -2048(a2)
+# CHECK-ASM: encoding: [0x23,0x30,0xa6,0x80]
+sd a0, -2048(a2)

diff  --git a/llvm/test/MC/RISCV/rv64c-valid.s b/llvm/test/MC/RISCV/rv64c-valid.s
index f8736e5d5453b..9f53c6a3b4b0a 100644
--- a/llvm/test/MC/RISCV/rv64c-valid.s
+++ b/llvm/test/MC/RISCV/rv64c-valid.s
@@ -19,31 +19,29 @@
 
 # TODO: more exhaustive testing of immediate encoding.
 
-# CHECK-ASM-AND-OBJ: c.ldsp ra, 0(sp)
-# CHECK-ASM: encoding: [0x82,0x60]
+# CHECK-ASM-AND-OBJ: c.ldsp s0, 0(sp)
+# CHECK-ASM: encoding: [0x02,0x64]
 # CHECK-NO-EXT:  error: instruction requires the following: 'C' (Compressed Instructions) or 'Zca' (part of the C extension, excluding compressed floating point loads/stores){{$}}
-# CHECK-NO-RV64:  error: instruction requires the following: RV64I Base Instruction Set{{$}}
-c.ldsp ra, 0(sp)
-# CHECK-ASM-AND-OBJ: c.sdsp ra, 504(sp)
-# CHECK-ASM: encoding: [0x86,0xff]
+# CHECK-NO-RV64:  error: instruction requires the following: 'Zclsd' (Compressed Load/Store pair instructions){{$}}
+c.ldsp s0, 0(sp)
+# CHECK-ASM-AND-OBJ: c.sdsp s2, 504(sp)
+# CHECK-ASM: encoding: [0xca,0xff]
 # CHECK-NO-EXT:  error: instruction requires the following: 'C' (Compressed Instructions) or 'Zca' (part of the C extension, excluding compressed floating point loads/stores){{$}}
-# CHECK-NO-RV64:  error: instruction requires the following: RV64I Base Instruction Set{{$}}
-c.sdsp ra, 504(sp)
+# CHECK-NO-RV64:  error: instruction requires the following: 'Zclsd' (Compressed Load/Store pair instructions){{$}}
+c.sdsp s2, 504(sp)
 # CHECK-ASM-AND-OBJ: c.ld a4, 0(a3)
 # CHECK-ASM: encoding: [0x98,0x62]
 # CHECK-NO-EXT:  error: instruction requires the following: 'C' (Compressed Instructions) or 'Zca' (part of the C extension, excluding compressed floating point loads/stores){{$}}
-# CHECK-NO-RV64:  error: instruction requires the following: RV64I Base Instruction Set{{$}}
+# CHECK-NO-RV64:  error: instruction requires the following: 'Zclsd' (Compressed Load/Store pair instructions){{$}}
 c.ld a4, 0(a3)
-# CHECK-ASM-AND-OBJ: c.sd a5, 248(a3)
-# CHECK-ASM: encoding: [0xfc,0xfe]
+# CHECK-ASM-AND-OBJ: c.sd a2, 248(a3)
+# CHECK-ASM: encoding: [0xf0,0xfe]
 # CHECK-NO-EXT:  error: instruction requires the following: 'C' (Compressed Instructions) or 'Zca' (part of the C extension, excluding compressed floating point loads/stores){{$}}
-# CHECK-NO-RV64:  error: instruction requires the following: RV64I Base Instruction Set{{$}}
-c.sd a5, 248(a3)
+# CHECK-NO-RV64:  error: instruction requires the following: 'Zclsd' (Compressed Load/Store pair instructions){{$}}
+c.sd a2, 248(a3)
 
 # CHECK-ASM-AND-OBJ: c.subw a3, a4
 # CHECK-ASM: encoding: [0x99,0x9e]
-# CHECK-NO-EXT:  error: instruction requires the following: 'C' (Compressed Instructions) or 'Zca' (part of the C extension, excluding compressed floating point loads/stores){{$}}
-# CHECK-NO-RV64:  error: instruction requires the following: RV64I Base Instruction Set{{$}}
 c.subw a3, a4
 # CHECK-ASM-AND-OBJ: c.addw a0, a2
 # CHECK-ASM: encoding: [0x31,0x9d]

diff  --git a/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp b/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp
index 04082a89124ee..c734f8a66d289 100644
--- a/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp
+++ b/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp
@@ -653,6 +653,11 @@ TEST(ParseArchString, RejectsConflictingExtensions) {
               "'xwchc' and 'zcb' extensions are incompatible");
   }
 
+  for (StringRef Input : {"rv32i_zcf_zclsd"}) {
+    EXPECT_EQ(toString(RISCVISAInfo::parseArchString(Input, true).takeError()),
+              "'zclsd' and 'zcf' extensions are incompatible");
+  }
+
   for (StringRef Input :
        {"rv64i_xqcisls0p2", "rv64i_xqcia0p4", "rv64i_xqciac0p3",
         "rv64i_xqcicsr0p2", "rv64i_xqcilsm0p2", "rv64i_xqcicm0p2",
@@ -969,6 +974,7 @@ R"(All available -march extensions for RISC-V
     zihintntl            1.0
     zihintpause          2.0
     zihpm                2.0
+    zilsd                1.0
     zimop                1.0
     zmmul                1.0
     za128rs              1.0
@@ -990,6 +996,7 @@ R"(All available -march extensions for RISC-V
     zcd                  1.0
     zce                  1.0
     zcf                  1.0
+    zclsd                1.0
     zcmop                1.0
     zcmp                 1.0
     zcmt                 1.0


        


More information about the llvm-commits mailing list