[clang] [llvm] [RISCV] Add Qualcomn uC Xqcili (load large immediates) extension (PR #130012)

via cfe-commits cfe-commits at lists.llvm.org
Tue Mar 11 03:56:12 PDT 2025


https://github.com/u4f3 updated https://github.com/llvm/llvm-project/pull/130012

>From b8d8e7d3f442d28f9771317c337fb650dd50aaa9 Mon Sep 17 00:00:00 2001
From: u4f3 <ricoafoat at gmail.com>
Date: Fri, 7 Mar 2025 15:01:57 +0800
Subject: [PATCH] [RISCV] Add Qualcomn uC Xqcili (load large immediates)
 extension

The Xqcili extension includes a two instructions that load large immediates than is available with the base RISC-V ISA.

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

This patch adds assembler only support.
---
 .../Driver/print-supported-extensions-riscv.c |  1 +
 llvm/docs/RISCVUsage.rst                      |  3 ++
 llvm/docs/ReleaseNotes.md                     |  2 +
 .../Target/RISCV/AsmParser/RISCVAsmParser.cpp | 13 ++++++
 .../RISCV/Disassembler/RISCVDisassembler.cpp  |  5 +-
 .../Target/RISCV/MCTargetDesc/RISCVBaseInfo.h |  1 +
 llvm/lib/Target/RISCV/RISCVFeatures.td        |  8 ++++
 llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td   | 15 ++++++
 llvm/lib/TargetParser/RISCVISAInfo.cpp        |  6 +--
 llvm/test/CodeGen/RISCV/attributes.ll         |  2 +
 llvm/test/MC/RISCV/xqcili-invalid.s           | 27 +++++++++++
 llvm/test/MC/RISCV/xqcili-valid.s             | 46 +++++++++++++++++++
 .../TargetParser/RISCVISAInfoTest.cpp         |  4 +-
 13 files changed, 127 insertions(+), 6 deletions(-)
 create mode 100644 llvm/test/MC/RISCV/xqcili-invalid.s
 create mode 100644 llvm/test/MC/RISCV/xqcili-valid.s

diff --git a/clang/test/Driver/print-supported-extensions-riscv.c b/clang/test/Driver/print-supported-extensions-riscv.c
index 69b76f0c4c4cd..21f79c7565295 100644
--- a/clang/test/Driver/print-supported-extensions-riscv.c
+++ b/clang/test/Driver/print-supported-extensions-riscv.c
@@ -202,6 +202,7 @@
 // CHECK-NEXT:     xqcics               0.2       'Xqcics' (Qualcomm uC Conditional Select Extension)
 // CHECK-NEXT:     xqcicsr              0.2       'Xqcicsr' (Qualcomm uC CSR Extension)
 // CHECK-NEXT:     xqciint              0.2       'Xqciint' (Qualcomm uC Interrupts Extension)
+// CHECK-NEXT:     xqcili               0.2       'Xqcili' (Qualcomm uC Load Large Immediate Extension)
 // CHECK-NEXT:     xqcilia              0.2       'Xqcilia' (Qualcomm uC Large Immediate Arithmetic Extension)
 // CHECK-NEXT:     xqcilo               0.2       'Xqcilo' (Qualcomm uC Large Offset Load Store Extension)
 // CHECK-NEXT:     xqcilsm              0.2       'Xqcilsm' (Qualcomm uC Load Store Multiple Extension)
diff --git a/llvm/docs/RISCVUsage.rst b/llvm/docs/RISCVUsage.rst
index 62c6a4fd80fd4..38c49d10d7999 100644
--- a/llvm/docs/RISCVUsage.rst
+++ b/llvm/docs/RISCVUsage.rst
@@ -456,6 +456,9 @@ The current vendor extensions supported are:
 ``experimental-Xqciint``
   LLVM implements `version 0.2 of the Qualcomm uC Interrupts 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-Xqcili``
+  LLVM implements `version 0.2 of the Qualcomm uC Load Large Immediate 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-Xqcilia``
   LLVM implements `version 0.2 of the Qualcomm uC Large Immediate Arithmetic 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.
 
diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md
index fe3b508d5c5b0..733f6947da823 100644
--- a/llvm/docs/ReleaseNotes.md
+++ b/llvm/docs/ReleaseNotes.md
@@ -107,6 +107,8 @@ Changes to the PowerPC Backend
 Changes to the RISC-V Backend
 -----------------------------
 
+* Adds experimental assembler support for the Qualcomm uC 'Xqcili` (Load Large Immediate)
+  extension.
 * Adds experimental assembler support for the Qualcomm uC 'Xqcilia` (Large Immediate Arithmetic)
   extension.
 * Adds experimental assembler support for the Qualcomm uC 'Xqcibm` (Bit Manipulation)
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index b342c18bece08..372e2e2ad8ba1 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -1076,6 +1076,16 @@ struct RISCVOperand final : public MCParsedAsmOperand {
            VK == RISCVMCExpr::VK_RISCV_None;
   }
 
+  bool isSImm20() const {
+    if (!isImm())
+      return false;
+    RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
+    int64_t Imm;
+    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
+    return IsConstantImm && (VK == RISCVMCExpr::VK_RISCV_None) &&
+           isInt<20>(fixImmediateForRV32(Imm, isRV64Imm()));
+  }
+
   bool isSImm26() const {
     if (!isImm())
       return false;
@@ -1712,6 +1722,9 @@ bool RISCVAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
   case Match_InvalidSImm26:
     return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 25),
                                       (1 << 25) - 1);
+  case Match_InvalidSImm20:
+    return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 19),
+                                      (1 << 19) - 1);
   case Match_InvalidSImm32:
     return generateImmOutOfRangeError(Operands, ErrorInfo,
                                       std::numeric_limits<int32_t>::min(),
diff --git a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
index 6dfebc1989e92..3972a34a803e0 100644
--- a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
+++ b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
@@ -654,8 +654,9 @@ static constexpr FeatureBitset XqciFeatureGroup = {
     RISCV::FeatureVendorXqcibm,  RISCV::FeatureVendorXqcicli,
     RISCV::FeatureVendorXqcicm,  RISCV::FeatureVendorXqcics,
     RISCV::FeatureVendorXqcicsr, RISCV::FeatureVendorXqciint,
-    RISCV::FeatureVendorXqcilia, RISCV::FeatureVendorXqcilo,
-    RISCV::FeatureVendorXqcilsm, RISCV::FeatureVendorXqcisls,
+    RISCV::FeatureVendorXqcili,  RISCV::FeatureVendorXqcilia,
+    RISCV::FeatureVendorXqcilo,  RISCV::FeatureVendorXqcilsm,
+    RISCV::FeatureVendorXqcisls,
 };
 
 static constexpr FeatureBitset XSfVectorGroup = {
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
index 863bfc76d45c0..96ffbfd5476b5 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
@@ -329,6 +329,7 @@ enum OperandType : unsigned {
   OPERAND_SIMM11,
   OPERAND_SIMM12,
   OPERAND_SIMM12_LSB00000,
+  OPERAND_SIMM20,
   OPERAND_SIMM26,
   OPERAND_SIMM32,
   OPERAND_CLUI_IMM,
diff --git a/llvm/lib/Target/RISCV/RISCVFeatures.td b/llvm/lib/Target/RISCV/RISCVFeatures.td
index 35db027509d94..b50f9e52a2964 100644
--- a/llvm/lib/Target/RISCV/RISCVFeatures.td
+++ b/llvm/lib/Target/RISCV/RISCVFeatures.td
@@ -1358,6 +1358,14 @@ def HasVendorXqciint
       AssemblerPredicate<(all_of FeatureVendorXqciint),
                          "'Xqciint' (Qualcomm uC Interrupts Extension)">;
 
+def FeatureVendorXqcili
+    : RISCVExperimentalExtension<0, 2, "Qualcomm uC Load Large Immediate Extension",
+                                 [FeatureStdExtZca]>;
+
+def HasVendorXqcili : Predicate<"Subtarget->hasVendorXqcili()">,
+                      AssemblerPredicate<(all_of FeatureVendorXqcili),
+                         "'Xqcili' (Qualcomm uC Load Large Immediate Extension)">;
+
 def FeatureVendorXqcilia
     : RISCVExperimentalExtension<0, 2, "Qualcomm uC Large Immediate Arithmetic Extension",
                                  [FeatureStdExtZca]>;
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
index e47e4a993c13b..492cf016f39b0 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
@@ -56,6 +56,8 @@ def uimm11 : RISCVUImmLeafOp<11>;
 
 def simm11 : RISCVSImmLeafOp<11>;
 
+def simm20 : RISCVSImmLeafOp<20>;
+
 def simm26 : RISCVSImmLeafOp<26>;
 
 // 32-bit Immediate, used by RV32 Instructions in 32-bit operations, so no
@@ -588,6 +590,19 @@ let Predicates = [HasVendorXqcilo, IsRV32] in {
   def QC_E_SW    : QCIRVInstESStore<0b110, 0b11, "qc.e.sw">;
 } // Predicates = [HasVendorXqcilo, IsRV32]
 
+let Predicates = [HasVendorXqcili, IsRV32] in {
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in {
+  def QC_LI : RVInstU<OPC_OP_IMM_32, (outs GPRNoX0:$rd), (ins simm20:$imm20),
+                      "qc.li", "$rd, $imm20"> {
+    let Inst{31} = imm20{19};
+    let Inst{30-16} = imm20{14-0};
+    let Inst{15-12} = imm20{18-15};
+  }
+
+  def QC_E_LI : QCIRVInstEAI<0b000, 0b0, "qc.e.li">;
+} // hasSideEffects = 0, mayLoad = 0, mayStore = 0
+} // Predicates = [HasVendorXqcili, IsRV32]
+
 let Predicates = [HasVendorXqcilia, IsRV32] in {
 let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in {
   def QC_E_XORAI : QCIRVInstEAI<0b001, 0b0, "qc.e.xorai">;
diff --git a/llvm/lib/TargetParser/RISCVISAInfo.cpp b/llvm/lib/TargetParser/RISCVISAInfo.cpp
index dd74f79f04b92..e9373085941da 100644
--- a/llvm/lib/TargetParser/RISCVISAInfo.cpp
+++ b/llvm/lib/TargetParser/RISCVISAInfo.cpp
@@ -742,9 +742,9 @@ Error RISCVISAInfo::checkDependency() {
   bool HasZvl = MinVLen != 0;
   bool HasZcmt = Exts.count("zcmt") != 0;
   static constexpr StringLiteral XqciExts[] = {
-      {"xqcia"},   {"xqciac"}, {"xqcibm"},  {"xqcicli"},
-      {"xqcicm"},  {"xqcics"}, {"xqcicsr"}, {"xqciint"},
-      {"xqcilia"}, {"xqcilo"}, {"xqcilsm"}, {"xqcisls"}};
+      {"xqcia"},  {"xqciac"},  {"xqcibm"},  {"xqcicli"}, {"xqcicm"},
+      {"xqcics"}, {"xqcicsr"}, {"xqciint"}, {"xqcili"},  {"xqcilia"},
+      {"xqcilo"}, {"xqcilsm"}, {"xqcisls"}};
   bool HasZcmp = Exts.count("zcmp") != 0;
   bool HasXqccmp = Exts.count("xqccmp") != 0;
 
diff --git a/llvm/test/CodeGen/RISCV/attributes.ll b/llvm/test/CodeGen/RISCV/attributes.ll
index 85e5a71fc7b62..d53130a18dbd2 100644
--- a/llvm/test/CodeGen/RISCV/attributes.ll
+++ b/llvm/test/CodeGen/RISCV/attributes.ll
@@ -90,6 +90,7 @@
 ; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcics %s -o - | FileCheck --check-prefix=RV32XQCICS %s
 ; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcicsr %s -o - | FileCheck --check-prefix=RV32XQCICSR %s
 ; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqciint %s -o - | FileCheck --check-prefix=RV32XQCIINT %s
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcili %s -o - | FileCheck --check-prefix=RV32XQCILI %s
 ; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcilia %s -o - | FileCheck --check-prefix=RV32XQCILIA %s
 ; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcilo %s -o - | FileCheck --check-prefix=RV32XQCILO %s
 ; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcilsm %s -o - | FileCheck --check-prefix=RV32XQCILSM %s
@@ -412,6 +413,7 @@
 ; RV32XQCICS: .attribute 5, "rv32i2p1_xqcics0p2"
 ; RV32XQCICSR: .attribute 5, "rv32i2p1_xqcicsr0p2"
 ; RV32XQCIINT: .attribute 5, "rv32i2p1_zca1p0_xqciint0p2"
+; RV32XQCILI: .attribute 5, "rv32i2p1_zca1p0_xqcili0p2"
 ; RV32XQCILIA: .attribute 5, "rv32i2p1_zca1p0_xqcilia0p2"
 ; RV32XQCILO: .attribute 5, "rv32i2p1_zca1p0_xqcilo0p2"
 ; RV32XQCILSM: .attribute 5, "rv32i2p1_xqcilsm0p2"
diff --git a/llvm/test/MC/RISCV/xqcili-invalid.s b/llvm/test/MC/RISCV/xqcili-invalid.s
new file mode 100644
index 0000000000000..7f0bdbc62c362
--- /dev/null
+++ b/llvm/test/MC/RISCV/xqcili-invalid.s
@@ -0,0 +1,27 @@
+# Xqcili - Qualcomm uC Load Large Immediate Extension
+# RUN: not llvm-mc -triple riscv32 -mattr=+experimental-xqcili < %s 2>&1 \
+# RUN:     | FileCheck -check-prefixes=CHECK,CHECK-PLUS %s
+# RUN: not llvm-mc -triple riscv32 -mattr=-experimental-xqcili < %s 2>&1 \
+# RUN:     | FileCheck -check-prefixes=CHECK,CHECK-MINUS %s
+
+# CHECK-PLUS: :[[@LINE+2]]:9: error: register must be a GPR excluding zero (x0)
+# CHECK_MINUS: :[[@LINE+1]]:9: error: invalid operand for instruction
+qc.e.li 9, 33554432
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.e.li x9
+
+# CHECK-PLUS: :[[@LINE+2]]:13: error: immediate must be an integer in the range [-2147483648, 4294967295]
+# CHECK_MINUS: :[[@LINE+1]]:13: error: invalid operand for instruction
+qc.e.li x9, 4294967296
+
+# CHECK-PLUS: :[[@LINE+2]]:7: error: register must be a GPR excluding zero (x0)
+# CHECK_MINUS: :[[@LINE+1]]:7: error: invalid operand for instruction
+qc.li x0, 114514
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.li x10
+
+# CHECK-PLUS: :[[@LINE+2]]:12: error: immediate must be an integer in the range [-524288, 524287]
+# CHECK-MINUS: :[[@LINE+1]]:12: error: invalid operand for instruction
+qc.li x10, 33554432
diff --git a/llvm/test/MC/RISCV/xqcili-valid.s b/llvm/test/MC/RISCV/xqcili-valid.s
new file mode 100644
index 0000000000000..5e372c3dbd82f
--- /dev/null
+++ b/llvm/test/MC/RISCV/xqcili-valid.s
@@ -0,0 +1,46 @@
+# Xqcili - Qualcomm uC Load Large Immediate Extension
+# RUN: llvm-mc %s -triple=riscv32 -mattr=+experimental-xqcili -riscv-no-aliases -show-encoding \
+# RUN:     | FileCheck -check-prefixes=CHECK-ENC,CHECK-INST %s
+
+# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+experimental-xqcili < %s \
+# RUN:     | llvm-objdump --mattr=+experimental-xqcili -M no-aliases --no-print-imm-hex -d - \
+# RUN:     | FileCheck -check-prefix=CHECK-INST %s
+
+# RUN: llvm-mc %s -triple=riscv32 -mattr=+experimental-xqcili -show-encoding \
+# RUN:     | FileCheck -check-prefixes=CHECK-ENC,CHECK-INST %s
+
+# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+experimental-xqcili < %s \
+# RUN:     | llvm-objdump --mattr=+experimental-xqcili --no-print-imm-hex -d - \
+# RUN:     | FileCheck -check-prefix=CHECK-INST %s
+
+# CHECK-INST: qc.e.li a0, -1
+# CHECK-ENC: encoding: [0x1f,0x05,0xff,0xff,0xff,0xff]
+qc.e.li x10, 4294967295
+
+# CHECK-INST: qc.e.li a0, -2147483648
+# CHECK-ENC: encoding: [0x1f,0x05,0x00,0x00,0x00,0x80]
+qc.e.li x10, -2147483648
+
+# CHECK-INST: qc.e.li s1, -33554432
+# CHECK-ENC: encoding: [0x9f,0x04,0x00,0x00,0x00,0xfe]
+qc.e.li x9, -33554432
+
+# CHECK-INST: qc.e.li s1, 33554431
+# CHECK-ENC: encoding: [0x9f,0x04,0xff,0xff,0xff,0x01]
+qc.e.li x9, 33554431
+
+# CHECK-INST: qc.li   s1, 524287
+# CHECK-ENC: encoding: [0x9b,0xf4,0xff,0x7f]
+qc.li x9, 524287
+
+# CHECK-INST: qc.li   s1, -524288
+# CHECK-ENC: encoding: [0x9b,0x04,0x00,0x80]
+qc.li x9, -524288
+
+# CHECK-INST: qc.li   a0, 12345
+# CHECK-ENC: encoding: [0x1b,0x05,0x39,0x30]
+qc.li x10, 12345
+
+# CHECK-INST: qc.li   a0, -12346
+# CHECK-ENC: encoding: [0x1b,0xf5,0xc6,0xcf]
+qc.li x10, -12346
diff --git a/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp b/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp
index 00dc160c39a36..968c006101cd4 100644
--- a/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp
+++ b/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp
@@ -657,7 +657,8 @@ TEST(ParseArchString, RejectsConflictingExtensions) {
        {"rv64i_xqcisls0p2", "rv64i_xqcia0p4", "rv64i_xqciac0p3",
         "rv64i_xqcicsr0p2", "rv64i_xqcilsm0p2", "rv64i_xqcicm0p2",
         "rv64i_xqcics0p2", "rv64i_xqcicli0p2", "rv64i_xqciint0p2",
-        "rv64i_xqcilo0p2", "rv64i_xqcilia0p2", "rv64i_xqcibm0p4"}) {
+        "rv64i_xqcilo0p2", "rv64i_xqcili0p2", "rv64i_xqcilia0p2",
+        "rv64i_xqcibm0p4"}) {
     EXPECT_THAT(
         toString(RISCVISAInfo::parseArchString(Input, true).takeError()),
         ::testing::EndsWith(" is only supported for 'rv32'"));
@@ -1133,6 +1134,7 @@ Experimental extensions
     xqcics               0.2
     xqcicsr              0.2
     xqciint              0.2
+    xqcili               0.2
     xqcilia              0.2
     xqcilo               0.2
     xqcilsm              0.2



More information about the cfe-commits mailing list