[clang] [llvm] [RISCV] Add Qualcomm uC Xqcibi (Branch Immediate) extension (PR #130779)

via cfe-commits cfe-commits at lists.llvm.org
Tue Mar 11 07:19:40 PDT 2025


https://github.com/hchandel created https://github.com/llvm/llvm-project/pull/130779

This extension adds twelve conditional branch instructions that use an immediate operand for the source.

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.


>From ed67e38e0e2d8dbdf67bd2e5123b49f3271e9e58 Mon Sep 17 00:00:00 2001
From: Harsh Chandel <quic_hchandel at quicinc.com>
Date: Tue, 11 Mar 2025 13:01:34 +0530
Subject: [PATCH] [RISCV] Add Qualcomm uC Xqcibi (Branch Immediate) extension
 This extension adds twelve conditional branch instructions that use an
 immediate operand for the source.

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.

Change-Id: I20307dd485ec0234bc08b0ad3940563b9779ea70
---
 .../Driver/print-supported-extensions-riscv.c |   1 +
 llvm/docs/RISCVUsage.rst                      |   3 +
 llvm/docs/ReleaseNotes.md                     |   2 +
 .../Target/RISCV/AsmParser/RISCVAsmParser.cpp |  42 ++++
 .../RISCV/Disassembler/RISCVDisassembler.cpp  |  11 +-
 .../Target/RISCV/MCTargetDesc/RISCVBaseInfo.h |   3 +
 llvm/lib/Target/RISCV/RISCVFeatures.td        |   8 +
 llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td   |  68 ++++++
 llvm/lib/TargetParser/RISCVISAInfo.cpp        |   6 +-
 llvm/test/CodeGen/RISCV/attributes.ll         |   2 +
 llvm/test/MC/RISCV/xqcibi-invalid.s           | 208 ++++++++++++++++++
 llvm/test/MC/RISCV/xqcibi-valid.s             |  71 ++++++
 .../TargetParser/RISCVISAInfoTest.cpp         |   4 +-
 13 files changed, 420 insertions(+), 9 deletions(-)
 create mode 100644 llvm/test/MC/RISCV/xqcibi-invalid.s
 create mode 100644 llvm/test/MC/RISCV/xqcibi-valid.s

diff --git a/clang/test/Driver/print-supported-extensions-riscv.c b/clang/test/Driver/print-supported-extensions-riscv.c
index 69b76f0c4c4cd..87140220fea9b 100644
--- a/clang/test/Driver/print-supported-extensions-riscv.c
+++ b/clang/test/Driver/print-supported-extensions-riscv.c
@@ -196,6 +196,7 @@
 // CHECK-NEXT:     xqccmp               0.1       'Xqccmp' (Qualcomm 16-bit Push/Pop and Double Moves)
 // CHECK-NEXT:     xqcia                0.4       'Xqcia' (Qualcomm uC Arithmetic Extension)
 // CHECK-NEXT:     xqciac               0.3       'Xqciac' (Qualcomm uC Load-Store Address Calculation Extension)
+// CHECK-NEXT:     xqcibi               0.2       'Xqcibi' (Qualcomm uC Branch Immediate Extension)
 // CHECK-NEXT:     xqcibm               0.4       'Xqcibm' (Qualcomm uC Bit Manipulation Extension)
 // CHECK-NEXT:     xqcicli              0.2       'Xqcicli' (Qualcomm uC Conditional Load Immediate Extension)
 // CHECK-NEXT:     xqcicm               0.2       'Xqcicm' (Qualcomm uC Conditional Move Extension)
diff --git a/llvm/docs/RISCVUsage.rst b/llvm/docs/RISCVUsage.rst
index 62c6a4fd80fd4..ecf63eda38723 100644
--- a/llvm/docs/RISCVUsage.rst
+++ b/llvm/docs/RISCVUsage.rst
@@ -438,6 +438,9 @@ The current vendor extensions supported are:
 ``experimental-Xqciac``
   LLVM implements `version 0.3 of the Qualcomm uC Load-Store Address Calculation 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-Xqcibi``
+  LLVM implements `version 0.2 of the Qualcomm uC Branch 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-Xqcibm``
   LLVM implements `version 0.4 of the Qualcomm uC Bit Manipulation 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 d7a80ae93aa34..2f537b33577c4 100644
--- a/llvm/docs/ReleaseNotes.md
+++ b/llvm/docs/ReleaseNotes.md
@@ -111,6 +111,8 @@ Changes to the RISC-V Backend
   extension.
 * Adds experimental assembler support for the Qualcomm uC 'Xqcibm` (Bit Manipulation)
   extension.
+* Adds experimental assembler support for the Qualcomm uC 'Xqcibi` (Branch Immediate)
+  extension.
 * Adds experimental assembler and code generation support for the Qualcomm
   'Xqccmp' extension, which is a frame-pointer convention compatible version of
   Zcmp.
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index b342c18bece08..eb8396224a128 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -825,6 +825,17 @@ struct RISCVOperand final : public MCParsedAsmOperand {
            VK == RISCVMCExpr::VK_RISCV_None;
   }
 
+  bool isSImm5NonZero() const {
+    if (!isImm())
+      return false;
+    RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
+    int64_t Imm;
+    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
+    return IsConstantImm && Imm != 0 &&
+           isInt<5>(fixImmediateForRV32(Imm, isRV64Imm())) &&
+           VK == RISCVMCExpr::VK_RISCV_None;
+  }
+
   bool isSImm6() const {
     if (!isImm())
       return false;
@@ -1012,6 +1023,27 @@ struct RISCVOperand final : public MCParsedAsmOperand {
            VK == RISCVMCExpr::VK_RISCV_None;
   }
 
+  bool isSImm16NonZero() const {
+    if (!isImm())
+      return false;
+    RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
+    int64_t Imm;
+    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
+    return IsConstantImm && Imm != 0 &&
+           isInt<16>(fixImmediateForRV32(Imm, isRV64Imm())) &&
+           VK == RISCVMCExpr::VK_RISCV_None;
+  }
+
+  bool isUImm16NonZero() const {
+    if (!isImm())
+      return false;
+    int64_t Imm;
+    RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
+    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
+    return IsConstantImm && isUInt<16>(Imm) && (Imm != 0) &&
+           VK == RISCVMCExpr::VK_RISCV_None;
+  }
+
   bool isUImm20LUI() const {
     RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
     int64_t Imm;
@@ -1607,6 +1639,10 @@ bool RISCVAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
   case Match_InvalidSImm5:
     return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 4),
                                       (1 << 4) - 1);
+  case Match_InvalidSImm5NonZero:
+    return generateImmOutOfRangeError(
+        Operands, ErrorInfo, -(1 << 4), (1 << 4) - 1,
+        "immediate must be non-zero in the range");
   case Match_InvalidSImm6:
     return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 5),
                                       (1 << 5) - 1);
@@ -1661,6 +1697,8 @@ bool RISCVAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 10) - 1);
   case Match_InvalidUImm11:
     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 11) - 1);
+  case Match_InvalidUImm16NonZero:
+    return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 15) - 1);
   case Match_InvalidSImm12:
     return generateImmOutOfRangeError(
         Operands, ErrorInfo, -(1 << 11), (1 << 11) - 1,
@@ -1678,6 +1716,10 @@ bool RISCVAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
     return generateImmOutOfRangeError(
         Operands, ErrorInfo, -(1 << 12), (1 << 12) - 2,
         "immediate must be a multiple of 2 bytes in the range");
+  case Match_InvalidSImm16NonZero:
+    return generateImmOutOfRangeError(
+        Operands, ErrorInfo, -(1 << 15), (1 << 15) - 1,
+        "immediate must be non-zero in the range");
   case Match_InvalidUImm20LUI:
     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 20) - 1,
                                       "operand must be a symbol with "
diff --git a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
index de742ac428de2..677d7764f6aa1 100644
--- a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
+++ b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
@@ -657,11 +657,12 @@ static constexpr FeatureBitset XRivosFeatureGroup = {
 
 static constexpr FeatureBitset XqciFeatureGroup = {
     RISCV::FeatureVendorXqcia,   RISCV::FeatureVendorXqciac,
-    RISCV::FeatureVendorXqcibm,  RISCV::FeatureVendorXqcicli,
-    RISCV::FeatureVendorXqcicm,  RISCV::FeatureVendorXqcics,
-    RISCV::FeatureVendorXqcicsr, RISCV::FeatureVendorXqciint,
-    RISCV::FeatureVendorXqcilia, RISCV::FeatureVendorXqcilo,
-    RISCV::FeatureVendorXqcilsm, RISCV::FeatureVendorXqcisls,
+    RISCV::FeatureVendorXqcibi,  RISCV::FeatureVendorXqcibm,
+    RISCV::FeatureVendorXqcicli, RISCV::FeatureVendorXqcicm,
+    RISCV::FeatureVendorXqcics,  RISCV::FeatureVendorXqcicsr,
+    RISCV::FeatureVendorXqciint, 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..962549c84d50d 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
@@ -314,6 +314,7 @@ enum OperandType : unsigned {
   OPERAND_UIMM11,
   OPERAND_UIMM12,
   OPERAND_UIMM16,
+  OPERAND_UIMM16_NONZERO,
   OPERAND_UIMM20,
   OPERAND_UIMMLOG2XLEN,
   OPERAND_UIMMLOG2XLEN_NONZERO,
@@ -322,6 +323,7 @@ enum OperandType : unsigned {
   OPERAND_UIMM64,
   OPERAND_ZERO,
   OPERAND_SIMM5,
+  OPERAND_SIMM5_NONZERO,
   OPERAND_SIMM5_PLUS1,
   OPERAND_SIMM6,
   OPERAND_SIMM6_NONZERO,
@@ -329,6 +331,7 @@ enum OperandType : unsigned {
   OPERAND_SIMM11,
   OPERAND_SIMM12,
   OPERAND_SIMM12_LSB00000,
+  OPERAND_SIMM16_NONZERO,
   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..82b24ead6058e 100644
--- a/llvm/lib/Target/RISCV/RISCVFeatures.td
+++ b/llvm/lib/Target/RISCV/RISCVFeatures.td
@@ -1374,6 +1374,14 @@ def HasVendorXqcibm
       AssemblerPredicate<(all_of FeatureVendorXqcibm),
                          "'Xqcibm' (Qualcomm uC Bit Manipulation Extension)">;
 
+def FeatureVendorXqcibi
+    : RISCVExperimentalExtension<0, 2, "Qualcomm uC Branch Immediate Extension",
+                                 [FeatureStdExtZca]>;
+def HasVendorXqcibi
+    : Predicate<"Subtarget->hasVendorXqcibi()">,
+      AssemblerPredicate<(all_of FeatureVendorXqcibi),
+                         "'Xqcibi' (Qualcomm uC Branch Immediate Extension)">;
+
 def FeatureVendorXqcilo
     : RISCVExperimentalExtension<0, 2, "Qualcomm uC Large Offset Load Store Extension",
                                  [FeatureStdExtZca]>;
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
index 8e84a01821f56..3fa8f52ec40b1 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
@@ -54,8 +54,29 @@ def uimm10 : RISCVUImmLeafOp<10>;
 
 def uimm11 : RISCVUImmLeafOp<11>;
 
+def uimm16nonzero : RISCVOp<XLenVT>,
+                    ImmLeaf<XLenVT, [{return (Imm != 0) && isUInt<16>(Imm);}]> {
+  let ParserMatchClass = UImmAsmOperand<16, "NonZero">;
+  let DecoderMethod = "decodeUImmNonZeroOperand<16>";
+  let OperandType = "OPERAND_UIMM16_NONZERO";
+}
+
+def simm5nonzero : RISCVOp<XLenVT>,
+                   ImmLeaf<XLenVT, [{return (Imm != 0) && isInt<5>(Imm);}]> {
+  let ParserMatchClass = SImmAsmOperand<5, "NonZero">;
+  let DecoderMethod = "decodeSImmNonZeroOperand<5>";
+  let OperandType = "OPERAND_SIMM5_NONZERO";
+}
+
 def simm11 : RISCVSImmLeafOp<11>;
 
+def simm16nonzero : RISCVOp<XLenVT>,
+                    ImmLeaf<XLenVT, [{return (Imm != 0) && isInt<16>(Imm);}]> {
+  let ParserMatchClass = SImmAsmOperand<16, "NonZero">;
+  let DecoderMethod = "decodeSImmNonZeroOperand<16>";
+  let OperandType = "OPERAND_SIMM16_NONZERO";
+}
+
 def simm26 : RISCVSImmLeafOp<26>;
 
 // 32-bit Immediate, used by RV32 Instructions in 32-bit operations, so no
@@ -259,6 +280,34 @@ class QCIRVInst16CI_RS1<bits<5> funct5, string OpcodeStr>
   let Inst{6-2} = funct5{4-0};
 }
 
+class QCIBranchInst_rii<bits<3> funct3, DAGOperand InTyImm5, string opcodestr>
+    : RVInstB<funct3, OPC_CUSTOM_3, (outs),
+              (ins GPRNoX0:$rs1, InTyImm5:$rs2, simm13_lsb0:$imm12),
+              opcodestr, "$rs1, $rs2, $imm12"> {
+  let isBranch = 1;
+  let isTerminator = 1;
+}
+
+class QCIBranchInst48_rii<bits<5> funct5, DAGOperand InTyImm16, string opcodestr>
+    : RVInst48<(outs), (ins GPRNoX0:$rs1, InTyImm16:$imm16, simm13_lsb0:$imm12),
+               opcodestr, "$rs1, $imm16, $imm12", [], InstFormatOther> {
+  bits<5> rs1;
+  bits<16> imm16;
+  bits<12> imm12;
+
+  let Inst{47-32} = imm16;
+  let Inst{31} = imm12{11};
+  let Inst{30-25} = imm12{9-4};
+  let Inst{24-20} = funct5;
+  let Inst{19-15} = rs1;
+  let Inst{14-12} = 0b100;
+  let Inst{11-8} = imm12{3-0};
+  let Inst{7} = imm12{10};
+  let Inst{6-0} = 0b0011111;
+  let isBranch = 1;
+  let isTerminator = 1;
+}
+
 let hasSideEffects = 1 in
 class QCIRVInst16CI_NONE<bits<5> funct5, string OpcodeStr>
     : RVInst16CI<0b000, 0b10, (outs), (ins), OpcodeStr, ""> {
@@ -397,6 +446,25 @@ let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in {
 } // hasSideEffects = 0, mayLoad = 0, mayStore = 0
 } // Predicates = [HasVendorXqcia, IsRV32]
 
+let Predicates = [HasVendorXqcibi, IsRV32] in {
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in {
+  def QC_BEQI  : QCIBranchInst_rii<0b000, simm5nonzero, "qc.beqi">;
+  def QC_BNEI  : QCIBranchInst_rii<0b001, simm5nonzero, "qc.bnei">;
+  def QC_BLTI  : QCIBranchInst_rii<0b100, simm5nonzero, "qc.blti">;
+  def QC_BGEI  : QCIBranchInst_rii<0b101, simm5nonzero, "qc.bgei">;
+  def QC_BLTUI : QCIBranchInst_rii<0b110, uimm5nonzero, "qc.bltui">;
+  def QC_BGEUI : QCIBranchInst_rii<0b111, uimm5nonzero, "qc.bgeui">;
+
+  def QC_E_BEQI  : QCIBranchInst48_rii<0b11000, simm16nonzero, "qc.e.beqi">;
+  def QC_E_BNEI  : QCIBranchInst48_rii<0b11001, simm16nonzero, "qc.e.bnei">;
+  def QC_E_BLTI  : QCIBranchInst48_rii<0b11100, simm16nonzero, "qc.e.blti">;
+  def QC_E_BGEI  : QCIBranchInst48_rii<0b11101, simm16nonzero, "qc.e.bgei">;
+  def QC_E_BLTUI : QCIBranchInst48_rii<0b11110, uimm16nonzero, "qc.e.bltui">;
+  def QC_E_BGEUI : QCIBranchInst48_rii<0b11111, uimm16nonzero, "qc.e.bgeui">;
+} // hasSideEffects = 0, mayLoad = 0, mayStore = 0
+
+} // Predicates = [HasVendorXqcibi, IsRV32]
+
 let Predicates = [HasVendorXqcibm, IsRV32] in {
 let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in {
   def QC_INSBRI : QCIRVInstRI<0b1, simm11, "qc.insbri">;
diff --git a/llvm/lib/TargetParser/RISCVISAInfo.cpp b/llvm/lib/TargetParser/RISCVISAInfo.cpp
index dd74f79f04b92..251e4789a6bf1 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"},  {"xqcibi"},  {"xqcibm"},  {"xqcicli"},
+      {"xqcicm"}, {"xqcics"},  {"xqcicsr"}, {"xqciint"}, {"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..ff5ec438f4df8 100644
--- a/llvm/test/CodeGen/RISCV/attributes.ll
+++ b/llvm/test/CodeGen/RISCV/attributes.ll
@@ -84,6 +84,7 @@
 ; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqccmp %s -o - | FileCheck --check-prefix=RV32XQCCMP %s
 ; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcia %s -o - | FileCheck --check-prefix=RV32XQCIA %s
 ; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqciac %s -o - | FileCheck --check-prefix=RV32XQCIAC %s
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcibi %s -o - | FileCheck --check-prefix=RV32XQCIBI %s
 ; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcibm %s -o - | FileCheck --check-prefix=RV32XQCIBM %s
 ; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcicli %s -o - | FileCheck --check-prefix=RV32XQCICLI %s
 ; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcicm %s -o - | FileCheck --check-prefix=RV32XQCICM %s
@@ -406,6 +407,7 @@
 ; RV32XQCCMP: .attribute 5, "rv32i2p1_zca1p0_xqccmp0p1"
 ; RV32XQCIA: .attribute 5, "rv32i2p1_xqcia0p4"
 ; RV32XQCIAC: .attribute 5, "rv32i2p1_zca1p0_xqciac0p3"
+; RV32XQCIBI: .attribute 5, "rv32i2p1_zca1p0_xqcibi0p2"
 ; RV32XQCIBM: .attribute 5, "rv32i2p1_zca1p0_xqcibm0p4"
 ; RV32XQCICLI: .attribute 5, "rv32i2p1_xqcicli0p2"
 ; RV32XQCICM: .attribute 5, "rv32i2p1_zca1p0_xqcicm0p2"
diff --git a/llvm/test/MC/RISCV/xqcibi-invalid.s b/llvm/test/MC/RISCV/xqcibi-invalid.s
new file mode 100644
index 0000000000000..11b3b8f513632
--- /dev/null
+++ b/llvm/test/MC/RISCV/xqcibi-invalid.s
@@ -0,0 +1,208 @@
+# Xqcibi - Qualcomm uC Branch Immediate Extension
+# RUN: not llvm-mc -triple riscv32 -mattr=+experimental-xqcibi < %s 2>&1 \
+# RUN:     | FileCheck -check-prefixes=CHECK,CHECK-PLUS %s
+# RUN: not llvm-mc -triple riscv32 -mattr=-experimental-xqcibi < %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.beqi x0, 12, 346
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.beqi x8, 12
+
+# CHECK-PLUS: :[[@LINE+1]]:13: error: immediate must be non-zero in the range [-16, 15]
+qc.beqi x8, 22, 346
+
+# CHECK-PLUS: :[[@LINE+1]]:17: error: immediate must be a multiple of 2 bytes in the range [-4096, 4094]
+qc.beqi x8, 12, 1211
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcibi' (Qualcomm uC Branch Immediate Extension)
+qc.beqi x8, 12, 346
+
+
+# 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.bnei x0, 15, 4094
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.bnei x4, 15
+
+# CHECK-PLUS: :[[@LINE+1]]:13: error: immediate must be non-zero in the range [-16, 15]
+qc.bnei x4, -45, 4094
+
+# CHECK-PLUS: :[[@LINE+1]]:17: error: immediate must be a multiple of 2 bytes in the range [-4096, 4094]
+qc.bnei x4, 15, 5000
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcibi' (Qualcomm uC Branch Immediate Extension)
+qc.bnei x4, 15, 4094
+
+
+# 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.bgei x0, 1, -4096
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.bgei x10, 1
+
+# CHECK-PLUS: :[[@LINE+1]]:14: error: immediate must be non-zero in the range [-16, 15]
+qc.bgei x10, 21, -4096
+
+# CHECK-PLUS: :[[@LINE+1]]:17: error: immediate must be a multiple of 2 bytes in the range [-4096, 4094]
+qc.bgei x10, 1, -4098
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcibi' (Qualcomm uC Branch Immediate Extension)
+qc.bgei x10, 1, -4096
+
+
+# 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.blti x0, 6, 2000
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.blti x1, 6
+
+# CHECK-PLUS: :[[@LINE+1]]:13: error: immediate must be non-zero in the range [-16, 15]
+qc.blti x1, 56, 2000
+
+# CHECK-PLUS: :[[@LINE+1]]:16: error: immediate must be a multiple of 2 bytes in the range [-4096, 4094]
+qc.blti x1, 6, 12000
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcibi' (Qualcomm uC Branch Immediate Extension)
+qc.blti x1, 6, 2000
+
+
+# CHECK-PLUS: :[[@LINE+2]]:10: error: register must be a GPR excluding zero (x0)
+# CHECK-MINUS: :[[@LINE+1]]:10: error: invalid operand for instruction
+qc.bgeui x0, 11, 128
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.bgeui x12, 11
+
+# CHECK-PLUS: :[[@LINE+1]]:15: error: immediate must be an integer in the range [1, 31]
+qc.bgeui x12, 41, 128
+
+# CHECK-PLUS: :[[@LINE+1]]:19: error: immediate must be a multiple of 2 bytes in the range [-4096, 4094]
+qc.bgeui x12, 11, 11128
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcibi' (Qualcomm uC Branch Immediate Extension)
+qc.bgeui x12, 11, 128
+
+
+# CHECK-PLUS: :[[@LINE+2]]:10: error: register must be a GPR excluding zero (x0)
+# CHECK-MINUS: :[[@LINE+1]]:10: error: invalid operand for instruction
+qc.bltui x0, 7, 666
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.bltui x2, 7
+
+# CHECK-PLUS: :[[@LINE+1]]:14: error: immediate must be an integer in the range [1, 31]
+qc.bltui x2, -7, 666
+
+# CHECK-PLUS: :[[@LINE+1]]:17: error: immediate must be a multiple of 2 bytes in the range [-4096, 4094]
+qc.bltui x2, 7, -6666
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcibi' (Qualcomm uC Branch Immediate Extension)
+qc.bltui x2, 7, 666
+
+
+# CHECK-PLUS: :[[@LINE+2]]:11: error: register must be a GPR excluding zero (x0)
+# CHECK-MINUS: :[[@LINE+1]]:11: error: invalid operand for instruction
+qc.e.beqi x0, 1, 2
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.e.beqi x1, 1
+
+# CHECK-PLUS: :[[@LINE+1]]:15: error: immediate must be non-zero in the range [-32768, 32767]
+qc.e.beqi x1, 32768, 2
+
+# CHECK-PLUS: :[[@LINE+1]]:18: error: immediate must be a multiple of 2 bytes in the range [-4096, 4094]
+qc.e.beqi x1, 1, 21
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcibi' (Qualcomm uC Branch Immediate Extension)
+qc.e.beqi x1, 1, 2
+
+
+# CHECK-PLUS: :[[@LINE+2]]:11: error: register must be a GPR excluding zero (x0)
+# CHECK-MINUS: :[[@LINE+1]]:11: error: invalid operand for instruction
+qc.e.bnei x0, 115, 4094
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.e.bnei x4, 115
+
+# CHECK-PLUS: :[[@LINE+1]]:15: error: immediate must be non-zero in the range [-32768, 32767]
+qc.e.bnei x4, -33115, 4094
+
+# CHECK-PLUS: :[[@LINE+1]]:20: error: immediate must be a multiple of 2 bytes in the range [-4096, 4094]
+qc.e.bnei x4, 115, 211
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcibi' (Qualcomm uC Branch Immediate Extension)
+qc.e.bnei x4, 115, 4094
+
+
+# CHECK-PLUS: :[[@LINE+2]]:11: error: register must be a GPR excluding zero (x0)
+# CHECK-MINUS: :[[@LINE+1]]:11: error: invalid operand for instruction
+qc.e.bgei x0, -32768, -4096
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.e.bgei x10, -32768
+
+# CHECK-PLUS: :[[@LINE+1]]:16: error: immediate must be non-zero in the range [-32768, 32767]
+qc.e.bgei x10, -32769, -4096
+
+# CHECK-PLUS: :[[@LINE+1]]:24: error: immediate must be a multiple of 2 bytes in the range [-4096, 4094]
+qc.e.bgei x10, -32768, -4097
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcibi' (Qualcomm uC Branch Immediate Extension)
+qc.e.bgei x10, -32768, -4096
+
+
+# CHECK-PLUS: :[[@LINE+2]]:11: error: register must be a GPR excluding zero (x0)
+# CHECK-MINUS: :[[@LINE+1]]:11: error: invalid operand for instruction
+qc.e.blti x0, 32767, 2000
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.e.blti x1, 32767
+
+# CHECK-PLUS: :[[@LINE+1]]:15: error: immediate must be non-zero in the range [-32768, 32767]
+qc.e.blti x1, 42767, 2000
+
+# CHECK-PLUS: :[[@LINE+1]]:22: error: immediate must be a multiple of 2 bytes in the range [-4096, 4094]
+qc.e.blti x1, 32767, 2001
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcibi' (Qualcomm uC Branch Immediate Extension)
+qc.e.blti x1, 32767, 2000
+
+
+# CHECK-PLUS: :[[@LINE+2]]:12: error: register must be a GPR excluding zero (x0)
+# CHECK-MINUS: :[[@LINE+1]]:12: error: invalid operand for instruction
+qc.e.bgeui x0, 711, 128
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.e.bgeui x12, 711
+
+# CHECK-PLUS: :[[@LINE+1]]:17: error: immediate must be an integer in the range [1, 32767]
+qc.e.bgeui x12, 0, 128
+
+# CHECK-PLUS: :[[@LINE+1]]:22: error: immediate must be a multiple of 2 bytes in the range [-4096, 4094]
+qc.e.bgeui x12, 711, 129
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcibi' (Qualcomm uC Branch Immediate Extension)
+qc.e.bgeui x12, 711, 128
+
+
+# CHECK-PLUS: :[[@LINE+2]]:12: error: register must be a GPR excluding zero (x0)
+# CHECK-MINUS: :[[@LINE+1]]:12: error: invalid operand for instruction
+qc.e.bltui x0, 7, 666
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.e.bltui x2, 7
+
+# CHECK-PLUS: :[[@LINE+1]]:16: error: immediate must be an integer in the range [1, 32767]
+qc.e.bltui x2, -7, 666
+
+# CHECK-PLUS: :[[@LINE+1]]:19: error: immediate must be a multiple of 2 bytes in the range [-4096, 4094]
+qc.e.bltui x2, 7, 667
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcibi' (Qualcomm uC Branch Immediate Extension)
+qc.e.bltui x2, 7, 666
diff --git a/llvm/test/MC/RISCV/xqcibi-valid.s b/llvm/test/MC/RISCV/xqcibi-valid.s
new file mode 100644
index 0000000000000..194f02f041771
--- /dev/null
+++ b/llvm/test/MC/RISCV/xqcibi-valid.s
@@ -0,0 +1,71 @@
+# Xqcibi - Qualcomm uC Branch Immediate Extension
+# RUN: llvm-mc %s -triple=riscv32 -mattr=+experimental-xqcibi -riscv-no-aliases -show-encoding \
+# RUN:     | FileCheck -check-prefixes=CHECK-ENC,CHECK-INST %s
+# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+experimental-xqcibi < %s \
+# RUN:     | llvm-objdump --mattr=+experimental-xqcibi -M no-aliases -d - \
+# RUN:     | FileCheck -check-prefix=CHECK-OBJ %s
+# RUN: llvm-mc %s -triple=riscv32 -mattr=+experimental-xqcibi -show-encoding \
+# RUN:     | FileCheck -check-prefixes=CHECK-ENC,CHECK-INST %s
+# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+experimental-xqcibi < %s \
+# RUN:     | llvm-objdump --mattr=+experimental-xqcibi -d - \
+# RUN:     | FileCheck -check-prefix=CHECK-OBJ %s
+
+# CHECK-INST:  qc.beqi     s0, 12, 346
+# CHECK-OBJ:  qc.beqi     s0, 0xc, 0x15a
+# CHECK-ENC: encoding: [0x7b,0x0d,0xc4,0x14]
+qc.beqi x8, 12, 346
+
+# CHECK-INST: qc.bnei     tp, 15, 4094
+# CHECK-OBJ: qc.bnei     tp, 0xf, 0x1002
+# CHECK-ENC: encoding: [0xfb,0x1f,0xf2,0x7e]
+qc.bnei x4, 15, 4094
+
+# CHECK-INST: qc.bgei     a0, 1, -4096
+# CHECK-OBJ: qc.bgei     a0, 0x1, 0xfffff008
+# CHECK-ENC: encoding: [0x7b,0x50,0x15,0x80]
+qc.bgei x10, 1, -4096
+
+# CHECK-INST: qc.blti     ra, 6, 2000
+# CHECK-OBJ: qc.blti     ra, 0x6, 0x7dc
+# CHECK-ENC: encoding: [0x7b,0xc8,0x60,0x7c]
+qc.blti x1, 6, 2000
+
+# CHECK-INST: qc.bgeui    a2, 11, 128
+# CHECK-OBJ: qc.bgeui    a2, 0xb, 0x90
+# CHECK-ENC: encoding: [0x7b,0x70,0xb6,0x08]
+qc.bgeui x12, 11, 128
+
+# CHECK-INST: qc.bltui    sp, 7, 666
+# CHECK-OBJ: qc.bltui    sp, 0x7, 0x2ae
+# CHECK-ENC: encoding: [0x7b,0x6d,0x71,0x28]
+qc.bltui x2, 7, 666
+
+# CHECK-INST:  qc.e.beqi   ra, 1, 2
+# CHECK-OBJ:  qc.e.beqi   ra, 0x1, 0x1a
+# CHECK-ENC: encoding: [0x1f,0xc1,0x80,0x01,0x01,0x00]
+qc.e.beqi x1, 1, 2
+
+# CHECK-INST: qc.e.bnei   tp, 115, 4094
+# CHECK-OBJ: qc.e.bnei   tp, 0x73, 0x101c
+# CHECK-ENC: encoding: [0x9f,0x4f,0x92,0x7f,0x73,0x00]
+qc.e.bnei x4, 115, 4094
+
+# CHECK-INST: qc.e.bgei   a0, -32768, -4096
+# CHECK-OBJ: qc.e.bgei   a0, -0x8000, 0xfffff024
+# CHECK-ENC: encoding: [0x1f,0x40,0xd5,0x81,0x00,0x80]
+qc.e.bgei x10, -32768, -4096
+
+# CHECK-INST: qc.e.blti   ra, 32767, 2000
+# CHECK-OBJ: qc.e.blti   ra, 0x7fff, 0x7fa
+# CHECK-ENC: encoding: [0x1f,0xc8,0xc0,0x7d,0xff,0x7f]
+qc.e.blti x1, 32767, 2000
+
+# CHECK-INST: qc.e.bgeui  a2, 711, 128
+# CHECK-OBJ: qc.e.bgeui  a2, 0x2c7, 0xb0
+# CHECK-ENC: encoding: [0x1f,0x40,0xf6,0x09,0xc7,0x02]
+qc.e.bgeui x12, 711, 128
+
+# CHECK-INST: qc.e.bltui  sp, 7, 666
+# CHECK-OBJ: qc.e.bltui  sp, 0x7, 0x2d0
+# CHECK-ENC: encoding: [0x1f,0x4d,0xe1,0x29,0x07,0x00]
+qc.e.bltui x2, 7, 666
diff --git a/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp b/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp
index 00dc160c39a36..503d261d7f153 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_xqcilia0p2", "rv64i_xqcibm0p4",
+        "rv64i_xqcibi0p2"}) {
     EXPECT_THAT(
         toString(RISCVISAInfo::parseArchString(Input, true).takeError()),
         ::testing::EndsWith(" is only supported for 'rv32'"));
@@ -1127,6 +1128,7 @@ Experimental extensions
     xqccmp               0.1
     xqcia                0.4
     xqciac               0.3
+    xqcibi               0.2
     xqcibm               0.4
     xqcicli              0.2
     xqcicm               0.2



More information about the cfe-commits mailing list