[clang] [llvm] [RISCV] Add Qualcomm uC Xqcisls (Scaled Load Store) extension (PR #117987)

via cfe-commits cfe-commits at lists.llvm.org
Thu Nov 28 02:16:13 PST 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-mc

@llvm/pr-subscribers-clang-driver

Author: Sudharsan Veeravalli (svs-quic)

<details>
<summary>Changes</summary>

This extension adds 8 load/store instructions with a scaled index addressing mode.

The current spec can be found at:
https://github.com/quic/riscv-unified-db/releases/latest

This patch adds assembler only support.

---
Full diff: https://github.com/llvm/llvm-project/pull/117987.diff


11 Files Affected:

- (modified) clang/test/Driver/print-supported-extensions-riscv.c (+1) 
- (modified) llvm/docs/RISCVUsage.rst (+3) 
- (modified) llvm/docs/ReleaseNotes.md (+2) 
- (modified) llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp (+2) 
- (modified) llvm/lib/Target/RISCV/RISCVFeatures.td (+8) 
- (modified) llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td (+34) 
- (modified) llvm/lib/TargetParser/RISCVISAInfo.cpp (+6-3) 
- (modified) llvm/test/CodeGen/RISCV/attributes.ll (+2) 
- (added) llvm/test/MC/RISCV/xqcisls-invalid.s (+132) 
- (added) llvm/test/MC/RISCV/xqcisls-valid.s (+43) 
- (modified) llvm/unittests/TargetParser/RISCVISAInfoTest.cpp (+1) 


``````````diff
diff --git a/clang/test/Driver/print-supported-extensions-riscv.c b/clang/test/Driver/print-supported-extensions-riscv.c
index 02edfc03e59cac..70b7a96daf1daf 100644
--- a/clang/test/Driver/print-supported-extensions-riscv.c
+++ b/clang/test/Driver/print-supported-extensions-riscv.c
@@ -189,6 +189,7 @@
 // CHECK-NEXT:     ssctr                1.0       'Ssctr' (Control Transfer Records Supervisor Level)
 // CHECK-NEXT:     svukte               0.3       'Svukte' (Address-Independent Latency of User-Mode Faults to Supervisor Addresses)
 // CHECK-NEXT:     xqcicsr              0.2       'Xqcicsr' (Qualcomm uC CSR Extension)
+// CHECK-NEXT:     xqcisls              0.2       'Xqcisls' (Qualcomm uC Scaled Load Store Extension)
 // CHECK-EMPTY:
 // CHECK-NEXT: Supported Profiles
 // CHECK-NEXT:     rva20s64
diff --git a/llvm/docs/RISCVUsage.rst b/llvm/docs/RISCVUsage.rst
index a7000baa69d806..230bf66fcf461b 100644
--- a/llvm/docs/RISCVUsage.rst
+++ b/llvm/docs/RISCVUsage.rst
@@ -429,6 +429,9 @@ The current vendor extensions supported are:
 ``experimental-Xqcicsr``
   LLVM implements `version 0.2 of the Qualcomm uC CSR extension specification <https://github.com/quic/riscv-unified-db/releases/latest>`__ by Qualcomm.  All instructions are prefixed with `qc.` as described in the specification. These instructions are only available for riscv32.
 
+``experimental-Xqcisls``
+  LLVM implements `version 0.2 of the Qualcomm uC Scaled Load Store extension specification <https://github.com/quic/riscv-unified-db/releases/latest>`__ by Qualcomm.  All instructions are prefixed with `qc.` as described in the specification. These instructions are only available for riscv32.
+
 Experimental C Intrinsics
 =========================
 
diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md
index 8b155d77bbb397..6d50839d68953e 100644
--- a/llvm/docs/ReleaseNotes.md
+++ b/llvm/docs/ReleaseNotes.md
@@ -213,6 +213,8 @@ Changes to the RISC-V Backend
   between e.g. F and Zfinx code.
 * Adds experimental assembler support for the Qualcomm uC 'Xqcicsr` (CSR)
   extension.
+* Adds experimental assembler support for the Qualcomm uC 'Xqcisls` (Scaled Load Store)
+  extension.
 
 Changes to the WebAssembly Backend
 ----------------------------------
diff --git a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
index e4f7ee323cf20b..95658f24f79e1c 100644
--- a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
+++ b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
@@ -684,6 +684,8 @@ DecodeStatus RISCVDisassembler::getInstruction32(MCInst &MI, uint64_t &Size,
                         "CORE-V Immediate Branching custom opcode table");
   TRY_TO_DECODE_FEATURE(RISCV::FeatureVendorXqcicsr, DecoderTableXqcicsr32,
                         "Qualcomm uC CSR custom opcode table");
+  TRY_TO_DECODE_FEATURE(RISCV::FeatureVendorXqcisls, DecoderTableXqcisls32,
+                        "Qualcomm uC Scaled Load Store custom opcode table");
   TRY_TO_DECODE(true, DecoderTable32, "RISCV32 table");
 
   return MCDisassembler::Fail;
diff --git a/llvm/lib/Target/RISCV/RISCVFeatures.td b/llvm/lib/Target/RISCV/RISCVFeatures.td
index 48ae378c0e67ef..95a37a76836729 100644
--- a/llvm/lib/Target/RISCV/RISCVFeatures.td
+++ b/llvm/lib/Target/RISCV/RISCVFeatures.td
@@ -1351,6 +1351,14 @@ def HasVendorXqcicsr
       AssemblerPredicate<(all_of FeatureVendorXqcicsr),
                          "'Xqcicsr' (Qualcomm uC CSR Extension)">;
 
+def FeatureVendorXqcisls
+    : RISCVExperimentalExtension<"xqcisls", 0, 2,
+                                 "'Xqcisls' (Qualcomm uC Scaled Load Store Extension)">;
+def HasVendorXqcisls
+    : Predicate<"Subtarget->hasVendorXqcisls()">,
+      AssemblerPredicate<(all_of FeatureVendorXqcisls),
+                         "'Xqcisls' (Qualcomm uC Scaled Load Store Extension)">;
+
 //===----------------------------------------------------------------------===//
 // LLVM specific features and extensions
 //===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
index 570fe23d744e14..5cdf07ee513a3d 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
@@ -22,6 +22,28 @@
 // Instruction Class Templates
 //===----------------------------------------------------------------------===//
 
+let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
+class QCILoad_ScaleIdx<bits<4> func4, string opcodestr>
+    : RVInstRBase<0b111, OPC_CUSTOM_0,
+                  (outs GPR:$rd), (ins GPRMem:$rs1, GPRNoX0:$rs2, uimm3:$shamt),
+                  opcodestr, "$rd, $rs1, $rs2, $shamt"> {
+  bits<3> shamt;
+  let Inst{31-28} = func4;
+  let Inst{27-25} = shamt;
+}
+}
+
+let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
+class QCIStore_ScaleIdx<bits<4> func4, string opcodestr>
+    : RVInstRBase<0b110, OPC_CUSTOM_1, (outs),
+                  (ins GPR:$rd, GPRMem:$rs1, GPRNoX0:$rs2, uimm3:$shamt),
+                  opcodestr, "$rd, $rs1, $rs2, $shamt"> {
+  bits<3> shamt;
+  let Inst{31-28} = func4;
+  let Inst{27-25} = shamt;
+}
+}
+
 //===----------------------------------------------------------------------===//
 // Instructions
 //===----------------------------------------------------------------------===//
@@ -37,3 +59,15 @@ let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in {
                            "$rd, $rs1, $rs2">;
 } // hasSideEffects = 0, mayLoad = 0, mayStore = 0
 } // Predicates = [HasVendorXqcicsr, IsRV32], DecoderNamespace = "Xqcicsr"
+
+let Predicates = [HasVendorXqcisls, IsRV32], DecoderNamespace = "Xqcisls" in {
+  def  QC_LRB  : QCILoad_ScaleIdx<0b1000, "qc.lrb">;
+  def  QC_LRH  : QCILoad_ScaleIdx<0b1001, "qc.lrh">;
+  def  QC_LRW  : QCILoad_ScaleIdx<0b1010, "qc.lrw">;
+  def  QC_LRBU : QCILoad_ScaleIdx<0b1011, "qc.lrbu">;
+  def  QC_LRHU : QCILoad_ScaleIdx<0b1100, "qc.lrhu">;
+
+  def  QC_SRB  : QCIStore_ScaleIdx<0b1101, "qc.srb">;
+  def  QC_SRH  : QCIStore_ScaleIdx<0b1110, "qc.srh">;
+  def  QC_SRW  : QCIStore_ScaleIdx<0b1111, "qc.srw">;
+} // Predicates = [HasVendorXqcisls, IsRV32], DecoderNamespace = "Xqcisls"
diff --git a/llvm/lib/TargetParser/RISCVISAInfo.cpp b/llvm/lib/TargetParser/RISCVISAInfo.cpp
index cc5be59572e040..08d2774e50a458 100644
--- a/llvm/lib/TargetParser/RISCVISAInfo.cpp
+++ b/llvm/lib/TargetParser/RISCVISAInfo.cpp
@@ -741,6 +741,7 @@ Error RISCVISAInfo::checkDependency() {
   bool HasVector = Exts.count("zve32x") != 0;
   bool HasZvl = MinVLen != 0;
   bool HasZcmt = Exts.count("zcmt") != 0;
+  static constexpr StringLiteral XqciExts[] = {{"xqcicsr"}, {"xqcisls"}};
 
   if (HasI && HasE)
     return getIncompatibleError("i", "e");
@@ -771,9 +772,11 @@ Error RISCVISAInfo::checkDependency() {
       return getIncompatibleError("xwchc", "zcb");
   }
 
-  if (Exts.count("xqcicsr") != 0 && (XLen != 32)) {
-    return getError("'xqcicsr' is only supported for 'rv32'");
-  }
+  for (auto Ext : XqciExts)
+    if (Exts.count(Ext.str()) && (XLen != 32))
+      return createStringError(errc::invalid_argument,
+                               "'" + Twine(Ext) + "'" +
+                                   " is only supported for 'rv32'");
 
   return Error::success();
 }
diff --git a/llvm/test/CodeGen/RISCV/attributes.ll b/llvm/test/CodeGen/RISCV/attributes.ll
index 554ae89357f72c..8a3d5e5cfe6216 100644
--- a/llvm/test/CodeGen/RISCV/attributes.ll
+++ b/llvm/test/CodeGen/RISCV/attributes.ll
@@ -82,6 +82,7 @@
 ; RUN: llc -mtriple=riscv32 -mattr=+xtheadsync %s -o - | FileCheck --check-prefix=RV32XTHEADSYNC %s
 ; RUN: llc -mtriple=riscv32 -mattr=+xwchc %s -o - | FileCheck --check-prefix=RV32XWCHC %s
 ; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcicsr %s -o - | FileCheck --check-prefix=RV32XQCICSR %s
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcisls %s -o - | FileCheck --check-prefix=RV32XQCISLS %s
 ; RUN: llc -mtriple=riscv32 -mattr=+zaamo %s -o - | FileCheck --check-prefix=RV32ZAAMO %s
 ; RUN: llc -mtriple=riscv32 -mattr=+zalrsc %s -o - | FileCheck --check-prefix=RV32ZALRSC %s
 ; RUN: llc -mtriple=riscv32 -mattr=+zca %s -o - | FileCheck --check-prefixes=CHECK,RV32ZCA %s
@@ -387,6 +388,7 @@
 ; RV32XTHEADSYNC: .attribute 5, "rv32i2p1_xtheadsync1p0"
 ; RV32XWCHC: .attribute 5, "rv32i2p1_xwchc2p2"
 ; RV32XQCICSR: .attribute 5, "rv32i2p1_xqcicsr0p2"
+; RV32XQCISLS: .attribute 5, "rv32i2p1_xqcisls0p2"
 ; RV32ZAAMO: .attribute 5, "rv32i2p1_zaamo1p0"
 ; RV32ZALRSC: .attribute 5, "rv32i2p1_zalrsc1p0"
 ; RV32ZCA: .attribute 5, "rv32i2p1_zca1p0"
diff --git a/llvm/test/MC/RISCV/xqcisls-invalid.s b/llvm/test/MC/RISCV/xqcisls-invalid.s
new file mode 100644
index 00000000000000..4cd2a14975a946
--- /dev/null
+++ b/llvm/test/MC/RISCV/xqcisls-invalid.s
@@ -0,0 +1,132 @@
+# Xqcisls - Qualcomm uC Scaled Load Store Extension
+# RUN: not llvm-mc -triple riscv32 -mattr=+experimental-xqcisls < %s 2>&1 \
+# RUN:     | FileCheck -check-prefixes=CHECK,CHECK-PLUS %s
+# RUN: not llvm-mc -triple riscv32 -mattr=-experimental-xqcisls < %s 2>&1 \
+# RUN:     | FileCheck -check-prefixes=CHECK,CHECK-MINUS %s
+
+# CHECK: :[[@LINE+1]]:16: error: invalid operand for instruction
+qc.lrb x5, x2, x0, 4
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.lrb x5, x2, x4
+
+# CHECK-PLUS: :[[@LINE+1]]:20: error: immediate must be an integer in the range [0, 7]
+qc.lrb x5, x2, x4, 12
+
+# CHECK: :[[@LINE+1]]:12: error: invalid operand for instruction
+qc.lrb x5, 2, x4, 4
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcisls' (Qualcomm uC Scaled Load Store Extension)
+qc.lrb x5, x2, x4, 4
+
+
+# CHECK: :[[@LINE+1]]:17: error: invalid operand for instruction
+qc.lrh x1, x12, x0, 2
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.lrh x1, x12, x6
+
+# CHECK-PLUS: :[[@LINE+1]]:21: error: immediate must be an integer in the range [0, 7]
+qc.lrh x1, x12, x6, 22
+
+# CHECK: :[[@LINE+1]]:12: error: invalid operand for instruction
+qc.lrh x1, 12, x6, 2
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcisls' (Qualcomm uC Scaled Load Store Extension)
+qc.lrh x1, x12, x6, 2
+
+
+# CHECK: :[[@LINE+1]]:17: error: invalid operand for instruction
+qc.lrw x15, x7, x0, 1
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.lrw x15, x7, x14
+
+# CHECK-PLUS: :[[@LINE+1]]:22: error: immediate must be an integer in the range [0, 7]
+qc.lrw x15, x7, x14, 11
+
+# CHECK: :[[@LINE+1]]:13: error: invalid operand for instruction
+qc.lrw x15, 7, x14, 1
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcisls' (Qualcomm uC Scaled Load Store Extension)
+qc.lrw x15, x7, x14, 1
+
+
+# CHECK: :[[@LINE+1]]:18: error: invalid operand for instruction
+qc.lrbu x9, x11, x0, 7
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.lrbu x9, x11, x4
+
+# CHECK-PLUS: :[[@LINE+1]]:22: error: immediate must be an integer in the range [0, 7]
+qc.lrbu x9, x11, x4, 37
+
+# CHECK: :[[@LINE+1]]:13: error: invalid operand for instruction
+qc.lrbu x9, 11, x4, 7
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcisls' (Qualcomm uC Scaled Load Store Extension)
+qc.lrbu x9, x11, x4, 7
+
+
+# CHECK: :[[@LINE+1]]:18: error: invalid operand for instruction
+qc.lrhu x16, x6, x0, 4
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.lrhu x16, x6, x10
+
+# CHECK-PLUS: :[[@LINE+1]]:23: error: immediate must be an integer in the range [0, 7]
+qc.lrhu x16, x6, x10, 44
+
+# CHECK: :[[@LINE+1]]:14: error: invalid operand for instruction
+qc.lrhu x16, 6, x10, 4
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcisls' (Qualcomm uC Scaled Load Store Extension)
+qc.lrhu x16, x6, x10, 4
+
+
+# CHECK: :[[@LINE+1]]:16: error: invalid operand for instruction
+qc.srb x0, x2, x0, 3
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.srb x0, x2, x8
+
+# CHECK-PLUS: :[[@LINE+1]]:20: error: immediate must be an integer in the range [0, 7]
+qc.srb x0, x2, x8, 93
+
+# CHECK: :[[@LINE+1]]:12: error: invalid operand for instruction
+qc.srb x0, 2, x8, 3
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcisls' (Qualcomm uC Scaled Load Store Extension)
+qc.srb x0, x2, x8, 3
+
+
+# CHECK: :[[@LINE+1]]:17: error: invalid operand for instruction
+qc.srh x13, x0, x0, 6
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.srh x13, x0, x20
+
+# CHECK-PLUS: :[[@LINE+1]]:22: error: immediate must be an integer in the range [0, 7]
+qc.srh x13, x0, x20, 76
+
+# CHECK: :[[@LINE+1]]:13: error: invalid operand for instruction
+qc.srh x13, 0, x20, 6
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcisls' (Qualcomm uC Scaled Load Store Extension)
+qc.srh x13, x0, x20, 6
+
+
+# CHECK: :[[@LINE+1]]:18: error: invalid operand for instruction
+qc.srw x17, x18, x0, 0
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.srw x17, x18, x19
+
+# CHECK-PLUS: :[[@LINE+1]]:23: error: immediate must be an integer in the range [0, 7]
+qc.srw x17, x18, x19, 10
+
+# CHECK: :[[@LINE+1]]:13: error: invalid operand for instruction
+qc.srw x17, 18, x19, 0
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcisls' (Qualcomm uC Scaled Load Store Extension)
+qc.srw x17, x18, x19, 0
diff --git a/llvm/test/MC/RISCV/xqcisls-valid.s b/llvm/test/MC/RISCV/xqcisls-valid.s
new file mode 100644
index 00000000000000..ae8370afc6c6e2
--- /dev/null
+++ b/llvm/test/MC/RISCV/xqcisls-valid.s
@@ -0,0 +1,43 @@
+# Xqcisls - Qualcomm uC Scaled Load Store Extension
+# RUN: llvm-mc %s -triple=riscv32 -mattr=+experimental-xqcisls -riscv-no-aliases -show-encoding \
+# RUN:     | FileCheck -check-prefixes=CHECK-ENC,CHECK-INST %s
+# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+experimental-xqcisls < %s \
+# RUN:     | llvm-objdump --mattr=+experimental-xqcisls -M no-aliases --no-print-imm-hex -d - \
+# RUN:     | FileCheck -check-prefix=CHECK-INST %s
+# RUN: llvm-mc %s -triple=riscv32 -mattr=+experimental-xqcisls -show-encoding \
+# RUN:     | FileCheck -check-prefixes=CHECK-ENC,CHECK-INST %s
+# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+experimental-xqcisls < %s \
+# RUN:     | llvm-objdump --mattr=+experimental-xqcisls --no-print-imm-hex -d - \
+# RUN:     | FileCheck -check-prefix=CHECK-INST %s
+
+# CHECK-INST: qc.lrb    t0, sp, tp, 4
+# CHECK-ENC: encoding: [0x8b,0x72,0x41,0x88]
+qc.lrb x5, x2, x4, 4
+
+# CHECK-INST: qc.lrh    ra, a2, t1, 2
+# CHECK-ENC: encoding: [0x8b,0x70,0x66,0x94]
+qc.lrh x1, x12, x6, 2
+
+# CHECK-INST: qc.lrw    a5, t2, a4, 1
+# CHECK-ENC: encoding: [0x8b,0xf7,0xe3,0xa2]
+qc.lrw x15, x7, x14, 1
+
+# CHECK-INST: qc.lrbu    s1, a1, tp, 7
+# CHECK-ENC: encoding: [0x8b,0xf4,0x45,0xbe]
+qc.lrbu x9, x11, x4, 7
+
+# CHECK-INST: qc.lrhu    a6, t1, a0, 4
+# CHECK-ENC: encoding: [0x0b,0x78,0xa3,0xc8]
+qc.lrhu x16, x6, x10, 4
+
+# CHECK-INST: qc.srb    zero, sp, s0, 3
+# CHECK-ENC: encoding: [0x2b,0x60,0x81,0xd6]
+qc.srb x0, x2, x8, 3
+
+# CHECK-INST: qc.srh    a3, zero, s4, 6
+# CHECK-ENC: encoding: [0xab,0x66,0x40,0xed]
+qc.srh x13, x0, x20, 6
+
+# CHECK-INST: qc.srw    a7, s2, s3, 0
+# CHECK-ENC: encoding: [0xab,0x68,0x39,0xf1]
+qc.srw x17, x18, x19, 0
diff --git a/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp b/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp
index 4b450e23627168..554568280a1b40 100644
--- a/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp
+++ b/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp
@@ -1105,6 +1105,7 @@ Experimental extensions
     ssctr                1.0
     svukte               0.3
     xqcicsr              0.2
+    xqcisls              0.2
 
 Supported Profiles
     rva20s64

``````````

</details>


https://github.com/llvm/llvm-project/pull/117987


More information about the cfe-commits mailing list