Skip to content

Revert "Revert "[RISCV] Add Qualcomm uC Xqcisync (Sync Delay) extensi… #132520

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 22, 2025

Conversation

svs-quic
Copy link
Contributor

…on (#132184)""

This reverts commit fe7776e.

With a minor fix for the build failures.

@svs-quic svs-quic requested a review from lenary March 22, 2025 04:45
@llvmbot llvmbot added clang Clang issues not falling into any other category backend:RISC-V clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' mc Machine (object) code labels Mar 22, 2025
@svs-quic svs-quic requested review from topperc and hchandel March 22, 2025 04:46
@llvmbot
Copy link
Member

llvmbot commented Mar 22, 2025

@llvm/pr-subscribers-backend-risc-v

Author: Sudharsan Veeravalli (svs-quic)

Changes

…on (#132184)""

This reverts commit fe7776e.

With a minor fix for the build failures.


Patch is 21.58 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/132520.diff

14 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/AsmParser/RISCVAsmParser.cpp (+17)
  • (modified) llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp (+18-8)
  • (modified) llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h (+1)
  • (modified) llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp (+34)
  • (modified) llvm/lib/Target/RISCV/RISCVFeatures.td (+8)
  • (modified) llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td (+57)
  • (modified) llvm/lib/TargetParser/RISCVISAInfo.cpp (+4-4)
  • (modified) llvm/test/CodeGen/RISCV/attributes.ll (+2)
  • (added) llvm/test/MC/RISCV/xqcisync-invalid.s (+121)
  • (added) llvm/test/MC/RISCV/xqcisync-valid.s (+47)
  • (modified) llvm/unittests/TargetParser/RISCVISAInfoTest.cpp (+2-1)
diff --git a/clang/test/Driver/print-supported-extensions-riscv.c b/clang/test/Driver/print-supported-extensions-riscv.c
index d6c50da75fe4f..b5533b54347b9 100644
--- a/clang/test/Driver/print-supported-extensions-riscv.c
+++ b/clang/test/Driver/print-supported-extensions-riscv.c
@@ -213,6 +213,7 @@
 // CHECK-NEXT:     xqcilsm              0.2       'Xqcilsm' (Qualcomm uC Load Store Multiple Extension)
 // CHECK-NEXT:     xqcisim              0.2       'Xqcisim' (Qualcomm uC Simulation Hint Extension)
 // CHECK-NEXT:     xqcisls              0.2       'Xqcisls' (Qualcomm uC Scaled Load Store Extension)
+// CHECK-NEXT:     xqcisync             0.2       'Xqcisync' (Qualcomm uC Sync Delay Extension)
 // CHECK-NEXT:     xrivosvisni          0.1       'XRivosVisni' (Rivos Vector Integer Small New)
 // CHECK-NEXT:     xrivosvizip          0.1       'XRivosVizip' (Rivos Vector Register Zips)
 // CHECK-EMPTY:
diff --git a/llvm/docs/RISCVUsage.rst b/llvm/docs/RISCVUsage.rst
index 4f261f06ce633..8735b274a805f 100644
--- a/llvm/docs/RISCVUsage.rst
+++ b/llvm/docs/RISCVUsage.rst
@@ -485,6 +485,9 @@ The current vendor extensions supported are:
 ``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-Xqcisync``
+  LLVM implements `version 0.2 of the Qualcomm uC Sync Delay 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.
+
 ``Xmipscmove``
   LLVM implements conditional move for the `p8700 processor <https://mips.com/products/hardware/p8700/>` by MIPS.
 
diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md
index 157065cb86214..1e39f761ecdad 100644
--- a/llvm/docs/ReleaseNotes.md
+++ b/llvm/docs/ReleaseNotes.md
@@ -140,6 +140,8 @@ 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 experimental assembler support for the Qualcomm uC 'Xqcisync` (Sync Delay)
+  extension.
 * Adds assembler support for the 'Zilsd` (Load/Store Pair Instructions)
   extension.
 * Adds assembler support for the 'Zclsd` (Compressed Load/Store Pair Instructions)
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index 5833ce2270e72..ccaa8ac1c7dbb 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -772,6 +772,18 @@ struct RISCVOperand final : public MCParsedAsmOperand {
            VK == RISCVMCExpr::VK_None;
   }
 
+  bool isUImm5Slist() const {
+    if (!isImm())
+      return false;
+    RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
+    int64_t Imm;
+    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
+    return IsConstantImm &&
+           ((Imm == 0) || (Imm == 1) || (Imm == 2) || (Imm == 4) ||
+            (Imm == 8) || (Imm == 16) || (Imm == 15) || (Imm == 31)) &&
+           VK == RISCVMCExpr::VK_None;
+  }
+
   bool isUImm8GE32() const {
     int64_t Imm;
     RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
@@ -1655,6 +1667,11 @@ bool RISCVAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
     return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 5));
   case Match_InvalidUImm5GE6Plus1:
     return generateImmOutOfRangeError(Operands, ErrorInfo, 6, (1 << 5));
+  case Match_InvalidUImm5Slist: {
+    SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
+    return Error(ErrorLoc,
+                 "immediate must be one of: 0, 1, 2, 4, 8, 15, 16, 31");
+  }
   case Match_InvalidUImm6:
     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 6) - 1);
   case Match_InvalidUImm7:
diff --git a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
index 5abf15a404dfb..93cbf662bfa32 100644
--- a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
+++ b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
@@ -370,6 +370,15 @@ static DecodeStatus decodeUImmPlus1OperandGE(MCInst &Inst, uint32_t Imm,
   return MCDisassembler::Success;
 }
 
+static DecodeStatus decodeUImmSlistOperand(MCInst &Inst, uint32_t Imm,
+                                           int64_t Address,
+                                           const MCDisassembler *Decoder) {
+  assert(isUInt<3>(Imm) && "Invalid Slist immediate");
+  const uint8_t Slist[] = {0, 1, 2, 4, 8, 16, 15, 31};
+  Inst.addOperand(MCOperand::createImm(Slist[Imm]));
+  return MCDisassembler::Success;
+}
+
 static DecodeStatus decodeUImmLog2XLenOperand(MCInst &Inst, uint32_t Imm,
                                               int64_t Address,
                                               const MCDisassembler *Decoder) {
@@ -663,14 +672,15 @@ static constexpr FeatureBitset XRivosFeatureGroup = {
 };
 
 static constexpr FeatureBitset XqciFeatureGroup = {
-    RISCV::FeatureVendorXqcia,   RISCV::FeatureVendorXqciac,
-    RISCV::FeatureVendorXqcibi,  RISCV::FeatureVendorXqcibm,
-    RISCV::FeatureVendorXqcicli, RISCV::FeatureVendorXqcicm,
-    RISCV::FeatureVendorXqcics,  RISCV::FeatureVendorXqcicsr,
-    RISCV::FeatureVendorXqciint, RISCV::FeatureVendorXqcilb,
-    RISCV::FeatureVendorXqcili,  RISCV::FeatureVendorXqcilia,
-    RISCV::FeatureVendorXqcilo,  RISCV::FeatureVendorXqcilsm,
-    RISCV::FeatureVendorXqcisim, RISCV::FeatureVendorXqcisls,
+    RISCV::FeatureVendorXqcia,    RISCV::FeatureVendorXqciac,
+    RISCV::FeatureVendorXqcibi,   RISCV::FeatureVendorXqcibm,
+    RISCV::FeatureVendorXqcicli,  RISCV::FeatureVendorXqcicm,
+    RISCV::FeatureVendorXqcics,   RISCV::FeatureVendorXqcicsr,
+    RISCV::FeatureVendorXqciint,  RISCV::FeatureVendorXqcilb,
+    RISCV::FeatureVendorXqcili,   RISCV::FeatureVendorXqcilia,
+    RISCV::FeatureVendorXqcilo,   RISCV::FeatureVendorXqcilsm,
+    RISCV::FeatureVendorXqcisim,  RISCV::FeatureVendorXqcisls,
+    RISCV::FeatureVendorXqcisync,
 };
 
 static constexpr FeatureBitset XSfVectorGroup = {
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
index 0b08dfb31741d..db305b0083415 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
@@ -299,6 +299,7 @@ enum OperandType : unsigned {
   OPERAND_UIMM5_PLUS1,
   OPERAND_UIMM5_GE6_PLUS1,
   OPERAND_UIMM5_LSB0,
+  OPERAND_UIMM5_SLIST,
   OPERAND_UIMM6,
   OPERAND_UIMM6_LSB0,
   OPERAND_UIMM7,
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
index f045c89a972cb..3ff3368f02461 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
@@ -84,6 +84,10 @@ class RISCVMCCodeEmitter : public MCCodeEmitter {
                                SmallVectorImpl<MCFixup> &Fixups,
                                const MCSubtargetInfo &STI) const;
 
+  uint64_t getImmOpValueSlist(const MCInst &MI, unsigned OpNo,
+                              SmallVectorImpl<MCFixup> &Fixups,
+                              const MCSubtargetInfo &STI) const;
+
   uint64_t getImmOpValueAsr1(const MCInst &MI, unsigned OpNo,
                              SmallVectorImpl<MCFixup> &Fixups,
                              const MCSubtargetInfo &STI) const;
@@ -404,6 +408,36 @@ RISCVMCCodeEmitter::getImmOpValueMinus1(const MCInst &MI, unsigned OpNo,
   return 0;
 }
 
+uint64_t
+RISCVMCCodeEmitter::getImmOpValueSlist(const MCInst &MI, unsigned OpNo,
+                                       SmallVectorImpl<MCFixup> &Fixups,
+                                       const MCSubtargetInfo &STI) const {
+  const MCOperand &MO = MI.getOperand(OpNo);
+  assert(MO.isImm() && "Slist operand must be immediate");
+
+  uint64_t Res = MO.getImm();
+  switch (Res) {
+  case 0:
+    return 0;
+  case 1:
+    return 1;
+  case 2:
+    return 2;
+  case 4:
+    return 3;
+  case 8:
+    return 4;
+  case 16:
+    return 5;
+  case 15:
+    return 6;
+  case 31:
+    return 7;
+  default:
+    llvm_unreachable("Unhandled Slist value!");
+  }
+}
+
 uint64_t
 RISCVMCCodeEmitter::getImmOpValueAsr1(const MCInst &MI, unsigned OpNo,
                                       SmallVectorImpl<MCFixup> &Fixups,
diff --git a/llvm/lib/Target/RISCV/RISCVFeatures.td b/llvm/lib/Target/RISCV/RISCVFeatures.td
index c1223beb304ad..70718113a3b39 100644
--- a/llvm/lib/Target/RISCV/RISCVFeatures.td
+++ b/llvm/lib/Target/RISCV/RISCVFeatures.td
@@ -1448,6 +1448,14 @@ def HasVendorXqcisim
                 AssemblerPredicate<(all_of FeatureVendorXqcisim),
                 "'Xqcisim' (Qualcomm uC Simulation Hint Extension)">;
 
+def FeatureVendorXqcisync
+    : RISCVExperimentalExtension<0, 2, "Qualcomm uC Sync Delay Extension",
+                                 [FeatureStdExtZca]>;
+def HasVendorXqcisync
+    : Predicate<"Subtarget->hasVendorXqcisync()">,
+                AssemblerPredicate<(all_of FeatureVendorXqcisync),
+                "'Xqcisync' (Qualcomm uC Sync Delay Extension)">;
+
 // Rivos Extension(s)
 
 def FeatureVendorXRivosVisni
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
index 86d31937ab7a2..caa66dd8fa739 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
@@ -50,6 +50,21 @@ def uimm5ge6_plus1 : RISCVOp<XLenVT>, ImmLeaf<XLenVT,
   let OperandType = "OPERAND_UIMM5_GE6_PLUS1";
 }
 
+def uimm5slist : RISCVOp<XLenVT>, ImmLeaf<XLenVT,
+  [{return ((Imm == 0)  ||
+            (Imm == 1)  ||
+            (Imm == 2)  ||
+            (Imm == 4)  ||
+            (Imm == 8)  ||
+            (Imm == 16) ||
+            (Imm == 15) ||
+            (Imm == 31));}]> {
+  let ParserMatchClass = UImmAsmOperand<5, "Slist">;
+  let EncoderMethod = "getImmOpValueSlist";
+  let DecoderMethod = "decodeUImmSlistOperand";
+  let OperandType = "OPERAND_UIMM5_SLIST";
+}
+
 def uimm10 : RISCVUImmLeafOp<10>;
 
 def uimm11 : RISCVUImmLeafOp<11>;
@@ -364,6 +379,27 @@ class QCISim_RS1<bits<4> imm11_8, string opcodestr>
   let imm12 = {imm11_8, 0b00000000};
 }
 
+let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
+class QCISync_UIMM5<bits<4> imm11_8, string opcodestr>
+    : RVInstI<0b011, OPC_OP_IMM, (outs), (ins uimm5:$imm5), opcodestr, "$imm5">
+{
+  bits<5> imm5;
+
+  let rs1 = 0;
+  let rd = 0;
+  let imm12 = {imm11_8, 0b000, imm5};
+}
+
+let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
+class QCIRVInst16CBSYNC<bits<3> imm5_func2, string OpcodeStr>
+    : RVInst16CB<0b100, 0b01, (outs), (ins uimm5slist:$slist), OpcodeStr, "$slist"> {
+    bits<3> slist;
+
+    let Inst{6-2} = 0;
+    let Inst{9-7} = slist;
+    let Inst{12-10} = imm5_func2;
+}
+
 class QCIRVInstEIBase<bits<3> funct3, bits<2> funct2, dag outs,
                       dag ins, string opcodestr, string argstr>
     : RVInst48<outs, ins, opcodestr, argstr, [], InstFormatOther> {
@@ -753,6 +789,27 @@ let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in {
 } // hasSideEffects = 0, mayLoad = 0, mayStore = 0
 } // Predicates = [HasVendorXqcilia, IsRV32]
 
+let Predicates = [HasVendorXqcisync, IsRV32] in {
+  def QC_SYNC : QCISync_UIMM5<0b0001, "qc.sync">;
+  def QC_SYNCR : QCISync_UIMM5<0b0010, "qc.syncr">;
+  def QC_SYNCWF : QCISync_UIMM5<0b0100, "qc.syncwf">;
+  def QC_SYNCWL : QCISync_UIMM5<0b1000, "qc.syncwl">;
+
+  def QC_C_SYNC   : QCIRVInst16CBSYNC<0b000, "qc.c.sync">;
+  def QC_C_SYNCR  : QCIRVInst16CBSYNC<0b001, "qc.c.syncr">;
+  def QC_C_SYNCWF : QCIRVInst16CBSYNC<0b100, "qc.c.syncwf">;
+  def QC_C_SYNCWL : QCIRVInst16CBSYNC<0b101, "qc.c.syncwl">;
+
+  let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
+  def QC_C_DELAY : RVInst16CI<0b000, 0b10, (outs),
+                              (ins uimm5nonzero:$imm),
+                              "qc.c.delay", "$imm"> {
+    let Inst{12} = 0;
+    let Inst{11-7} = 0;
+    let Inst{6-2} = imm{4-0};
+  }
+} // Predicates = [HasVendorXqcisync, IsRV32]
+
 let Predicates = [HasVendorXqcisim, IsRV32] in {
 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in {
   def QC_PSYSCALLI : RVInstI<0b010, OPC_OP_IMM, (outs), (ins uimm10:$imm10),
diff --git a/llvm/lib/TargetParser/RISCVISAInfo.cpp b/llvm/lib/TargetParser/RISCVISAInfo.cpp
index 4cb263b028625..cb161b0bfad5f 100644
--- a/llvm/lib/TargetParser/RISCVISAInfo.cpp
+++ b/llvm/lib/TargetParser/RISCVISAInfo.cpp
@@ -744,10 +744,10 @@ Error RISCVISAInfo::checkDependency() {
   bool HasXqccmp = Exts.count("xqccmp") != 0;
 
   static constexpr StringLiteral XqciExts[] = {
-      {"xqcia"},   {"xqciac"},  {"xqcibi"},  {"xqcibm"},
-      {"xqcicli"}, {"xqcicm"},  {"xqcics"},  {"xqcicsr"},
-      {"xqciint"}, {"xqcilb"},  {"xqcili"},  {"xqcilia"},
-      {"xqcilo"},  {"xqcilsm"}, {"xqcisim"}, {"xqcisls"}};
+      {"xqcia"},   {"xqciac"},  {"xqcibi"},  {"xqcibm"},  {"xqcicli"},
+      {"xqcicm"},  {"xqcics"},  {"xqcicsr"}, {"xqciint"}, {"xqcilb"},
+      {"xqcili"},  {"xqcilia"}, {"xqcilo"},  {"xqcilsm"}, {"xqcisim"},
+      {"xqcisls"}, {"xqcisync"}};
   static constexpr StringLiteral ZcdOverlaps[] = {
       {"zcmt"}, {"zcmp"}, {"xqccmp"}, {"xqciac"}, {"xqcicm"}};
 
diff --git a/llvm/test/CodeGen/RISCV/attributes.ll b/llvm/test/CodeGen/RISCV/attributes.ll
index cc2ce1a572d9a..71fe6ce38fd46 100644
--- a/llvm/test/CodeGen/RISCV/attributes.ll
+++ b/llvm/test/CodeGen/RISCV/attributes.ll
@@ -97,6 +97,7 @@
 ; 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
 ; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcisim %s -o - | FileCheck --check-prefix=RV32XQCISIM %s
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcisync %s -o - | FileCheck --check-prefix=RV32XQCISYNC %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
@@ -427,6 +428,7 @@
 ; RV32XQCILO: .attribute 5, "rv32i2p1_zca1p0_xqcilo0p2"
 ; RV32XQCILSM: .attribute 5, "rv32i2p1_xqcilsm0p2"
 ; RV32XQCISIM: attribute 5, "rv32i2p1_zca1p0_xqcisim0p2"
+; RV32XQCISYNC: attribute 5, "rv32i2p1_zca1p0_xqcisync0p2"
 ; RV32XQCISLS: .attribute 5, "rv32i2p1_xqcisls0p2"
 ; RV32ZAAMO: .attribute 5, "rv32i2p1_zaamo1p0"
 ; RV32ZALRSC: .attribute 5, "rv32i2p1_zalrsc1p0"
diff --git a/llvm/test/MC/RISCV/xqcisync-invalid.s b/llvm/test/MC/RISCV/xqcisync-invalid.s
new file mode 100644
index 0000000000000..6c945c9e5cfb0
--- /dev/null
+++ b/llvm/test/MC/RISCV/xqcisync-invalid.s
@@ -0,0 +1,121 @@
+# Xqcisync - Qualcomm uC Sync Delay Extension
+# RUN: not llvm-mc -triple riscv32 -mattr=+experimental-xqcisync < %s 2>&1 \
+# RUN:     | FileCheck -check-prefixes=CHECK,CHECK-PLUS %s
+# RUN: not llvm-mc -triple riscv32 -mattr=-experimental-xqcisync < %s 2>&1 \
+# RUN:     | FileCheck -check-prefixes=CHECK,CHECK-MINUS %s
+
+# CHECK-PLUS: :[[@LINE+1]]:12: error: immediate must be an integer in the range [1, 31]
+qc.c.delay 34
+
+# CHECK: :[[@LINE+1]]:16: error: invalid operand for instruction
+qc.c.delay 11, 12
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.c.delay
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcisync' (Qualcomm uC Sync Delay Extension)
+qc.c.delay   10
+
+
+# CHECK-PLUS: :[[@LINE+1]]:9: error: immediate must be an integer in the range [0, 31]
+qc.sync 45
+
+# CHECK: :[[@LINE+1]]:13: error: invalid operand for instruction
+qc.sync 22, x4
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.sync
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcisync' (Qualcomm uC Sync Delay Extension)
+qc.sync 8
+
+
+# CHECK-PLUS: :[[@LINE+1]]:10: error: immediate must be an integer in the range [0, 31]
+qc.syncr 56
+
+# CHECK: :[[@LINE+1]]:14: error: invalid operand for instruction
+qc.syncr 31, 45
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.syncr
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcisync' (Qualcomm uC Sync Delay Extension)
+qc.syncr   23
+
+
+# CHECK-PLUS: :[[@LINE+1]]:11: error: immediate must be an integer in the range [0, 31]
+qc.syncwf 88
+
+# CHECK: :[[@LINE+1]]:14: error: invalid operand for instruction
+qc.syncwf 5, 44
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.syncwf
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcisync' (Qualcomm uC Sync Delay Extension)
+qc.syncwf  31
+
+
+# CHECK-PLUS: :[[@LINE+1]]:11: error: immediate must be an integer in the range [0, 31]
+qc.syncwl 99
+
+# CHECK: :[[@LINE+1]]:15: error: invalid operand for instruction
+qc.syncwl 11, x10
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.syncwl
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcisync' (Qualcomm uC Sync Delay Extension)
+qc.syncwl  1
+
+
+# CHECK-PLUS: :[[@LINE+1]]:11: error: immediate must be one of: 0, 1, 2, 4, 8, 15, 16, 31
+qc.c.sync 45
+
+# CHECK: :[[@LINE+1]]:15: error: invalid operand for instruction
+qc.c.sync 31, x4
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.c.sync
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcisync' (Qualcomm uC Sync Delay Extension)
+qc.c.sync 8
+
+
+# CHECK-PLUS: :[[@LINE+1]]:12: error: immediate must be one of: 0, 1, 2, 4, 8, 15, 16, 31
+qc.c.syncr 56
+
+# CHECK: :[[@LINE+1]]:16: error: invalid operand for instruction
+qc.c.syncr 31, 45
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.c.syncr
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcisync' (Qualcomm uC Sync Delay Extension)
+qc.c.syncr   8
+
+
+# CHECK-PLUS: :[[@LINE+1]]:13: error: immediate must be one of: 0, 1, 2, 4, 8, 15, 16, 31
+qc.c.syncwf 88
+
+# CHECK: :[[@LINE+1]]:16: error: invalid operand for instruction
+qc.c.syncwf 8, 44
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.c.syncwf
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcisync' (Qualcomm uC Sync Delay Extension)
+qc.c.syncwf  31
+
+
+# CHECK-PLUS: :[[@LINE+1]]:13: error: immediate must be one of: 0, 1, 2, 4, 8, 15, 16, 31
+qc.c.syncwl 99
+
+# CHECK: :[[@LINE+1]]:17: error: invalid operand for instruction
+qc.c.syncwl 15, x10
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.c.syncwl
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcisync' (Qualcomm uC Sync Delay Extension)
+qc.c.syncwl  1
diff --git a/llvm/test/MC/RISCV/xqcisync-valid.s b/llvm/test/MC/RISCV/xqcisync-valid.s
new file mode 100644
index 0000000000000..3eedf99247b22
--- /dev/null
+++ b/llvm/test/MC/RISCV/xqcisync-valid.s
@@ -0,0 +1,47 @@
+# Xqcisync - Qualcomm uC Sync Delay Extension
+# RUN: llvm-mc %s -triple=riscv32 -mattr=+experimental-xqcisync -riscv-no-aliases -show-encoding \
+# RUN:     | FileCheck -check-prefixes=CHECK-ENC,CHECK-INST %s
+# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+experimental-xqcisync < %s \
+# RUN:     | llvm-objdump --mattr=+experimental-xqcisync -M no-aliases --no-print-imm-hex -d - \
+# RUN:     | FileCheck -check-prefix=CHECK-INST %s
+# RUN: llvm-mc %s -triple=riscv32 -mattr=+experimental-xqcisync -show-encoding \
+# RUN:     | FileCheck -check-prefixes=CHECK-ENC,CHECK-INST %s
+# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+experimental-xqcisync < %s \
+# RUN:     | llvm-objdump --mattr=+experimental-xqcisync --no-print-imm-hex -d - \
+# RUN:     | FileCheck -check-prefix=CHECK-INST %s
+
+# CHECK-INST: qc.c.delay     10
+# CHECK-ENC: encoding: [0x2a,0x00]
+qc.c.delay 10
+
+# CHECK-INST: qc.sync      8
+# CHECK-ENC: encoding: [0x13,0x30,0x80,0x10]
+qc.sync 8
+
+...
[truncated]

@llvmbot
Copy link
Member

llvmbot commented Mar 22, 2025

@llvm/pr-subscribers-clang

Author: Sudharsan Veeravalli (svs-quic)

Changes

…on (#132184)""

This reverts commit fe7776e.

With a minor fix for the build failures.


Patch is 21.58 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/132520.diff

14 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/AsmParser/RISCVAsmParser.cpp (+17)
  • (modified) llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp (+18-8)
  • (modified) llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h (+1)
  • (modified) llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp (+34)
  • (modified) llvm/lib/Target/RISCV/RISCVFeatures.td (+8)
  • (modified) llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td (+57)
  • (modified) llvm/lib/TargetParser/RISCVISAInfo.cpp (+4-4)
  • (modified) llvm/test/CodeGen/RISCV/attributes.ll (+2)
  • (added) llvm/test/MC/RISCV/xqcisync-invalid.s (+121)
  • (added) llvm/test/MC/RISCV/xqcisync-valid.s (+47)
  • (modified) llvm/unittests/TargetParser/RISCVISAInfoTest.cpp (+2-1)
diff --git a/clang/test/Driver/print-supported-extensions-riscv.c b/clang/test/Driver/print-supported-extensions-riscv.c
index d6c50da75fe4f..b5533b54347b9 100644
--- a/clang/test/Driver/print-supported-extensions-riscv.c
+++ b/clang/test/Driver/print-supported-extensions-riscv.c
@@ -213,6 +213,7 @@
 // CHECK-NEXT:     xqcilsm              0.2       'Xqcilsm' (Qualcomm uC Load Store Multiple Extension)
 // CHECK-NEXT:     xqcisim              0.2       'Xqcisim' (Qualcomm uC Simulation Hint Extension)
 // CHECK-NEXT:     xqcisls              0.2       'Xqcisls' (Qualcomm uC Scaled Load Store Extension)
+// CHECK-NEXT:     xqcisync             0.2       'Xqcisync' (Qualcomm uC Sync Delay Extension)
 // CHECK-NEXT:     xrivosvisni          0.1       'XRivosVisni' (Rivos Vector Integer Small New)
 // CHECK-NEXT:     xrivosvizip          0.1       'XRivosVizip' (Rivos Vector Register Zips)
 // CHECK-EMPTY:
diff --git a/llvm/docs/RISCVUsage.rst b/llvm/docs/RISCVUsage.rst
index 4f261f06ce633..8735b274a805f 100644
--- a/llvm/docs/RISCVUsage.rst
+++ b/llvm/docs/RISCVUsage.rst
@@ -485,6 +485,9 @@ The current vendor extensions supported are:
 ``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-Xqcisync``
+  LLVM implements `version 0.2 of the Qualcomm uC Sync Delay 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.
+
 ``Xmipscmove``
   LLVM implements conditional move for the `p8700 processor <https://mips.com/products/hardware/p8700/>` by MIPS.
 
diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md
index 157065cb86214..1e39f761ecdad 100644
--- a/llvm/docs/ReleaseNotes.md
+++ b/llvm/docs/ReleaseNotes.md
@@ -140,6 +140,8 @@ 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 experimental assembler support for the Qualcomm uC 'Xqcisync` (Sync Delay)
+  extension.
 * Adds assembler support for the 'Zilsd` (Load/Store Pair Instructions)
   extension.
 * Adds assembler support for the 'Zclsd` (Compressed Load/Store Pair Instructions)
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index 5833ce2270e72..ccaa8ac1c7dbb 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -772,6 +772,18 @@ struct RISCVOperand final : public MCParsedAsmOperand {
            VK == RISCVMCExpr::VK_None;
   }
 
+  bool isUImm5Slist() const {
+    if (!isImm())
+      return false;
+    RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
+    int64_t Imm;
+    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
+    return IsConstantImm &&
+           ((Imm == 0) || (Imm == 1) || (Imm == 2) || (Imm == 4) ||
+            (Imm == 8) || (Imm == 16) || (Imm == 15) || (Imm == 31)) &&
+           VK == RISCVMCExpr::VK_None;
+  }
+
   bool isUImm8GE32() const {
     int64_t Imm;
     RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
@@ -1655,6 +1667,11 @@ bool RISCVAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
     return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 5));
   case Match_InvalidUImm5GE6Plus1:
     return generateImmOutOfRangeError(Operands, ErrorInfo, 6, (1 << 5));
+  case Match_InvalidUImm5Slist: {
+    SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
+    return Error(ErrorLoc,
+                 "immediate must be one of: 0, 1, 2, 4, 8, 15, 16, 31");
+  }
   case Match_InvalidUImm6:
     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 6) - 1);
   case Match_InvalidUImm7:
diff --git a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
index 5abf15a404dfb..93cbf662bfa32 100644
--- a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
+++ b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
@@ -370,6 +370,15 @@ static DecodeStatus decodeUImmPlus1OperandGE(MCInst &Inst, uint32_t Imm,
   return MCDisassembler::Success;
 }
 
+static DecodeStatus decodeUImmSlistOperand(MCInst &Inst, uint32_t Imm,
+                                           int64_t Address,
+                                           const MCDisassembler *Decoder) {
+  assert(isUInt<3>(Imm) && "Invalid Slist immediate");
+  const uint8_t Slist[] = {0, 1, 2, 4, 8, 16, 15, 31};
+  Inst.addOperand(MCOperand::createImm(Slist[Imm]));
+  return MCDisassembler::Success;
+}
+
 static DecodeStatus decodeUImmLog2XLenOperand(MCInst &Inst, uint32_t Imm,
                                               int64_t Address,
                                               const MCDisassembler *Decoder) {
@@ -663,14 +672,15 @@ static constexpr FeatureBitset XRivosFeatureGroup = {
 };
 
 static constexpr FeatureBitset XqciFeatureGroup = {
-    RISCV::FeatureVendorXqcia,   RISCV::FeatureVendorXqciac,
-    RISCV::FeatureVendorXqcibi,  RISCV::FeatureVendorXqcibm,
-    RISCV::FeatureVendorXqcicli, RISCV::FeatureVendorXqcicm,
-    RISCV::FeatureVendorXqcics,  RISCV::FeatureVendorXqcicsr,
-    RISCV::FeatureVendorXqciint, RISCV::FeatureVendorXqcilb,
-    RISCV::FeatureVendorXqcili,  RISCV::FeatureVendorXqcilia,
-    RISCV::FeatureVendorXqcilo,  RISCV::FeatureVendorXqcilsm,
-    RISCV::FeatureVendorXqcisim, RISCV::FeatureVendorXqcisls,
+    RISCV::FeatureVendorXqcia,    RISCV::FeatureVendorXqciac,
+    RISCV::FeatureVendorXqcibi,   RISCV::FeatureVendorXqcibm,
+    RISCV::FeatureVendorXqcicli,  RISCV::FeatureVendorXqcicm,
+    RISCV::FeatureVendorXqcics,   RISCV::FeatureVendorXqcicsr,
+    RISCV::FeatureVendorXqciint,  RISCV::FeatureVendorXqcilb,
+    RISCV::FeatureVendorXqcili,   RISCV::FeatureVendorXqcilia,
+    RISCV::FeatureVendorXqcilo,   RISCV::FeatureVendorXqcilsm,
+    RISCV::FeatureVendorXqcisim,  RISCV::FeatureVendorXqcisls,
+    RISCV::FeatureVendorXqcisync,
 };
 
 static constexpr FeatureBitset XSfVectorGroup = {
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
index 0b08dfb31741d..db305b0083415 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
@@ -299,6 +299,7 @@ enum OperandType : unsigned {
   OPERAND_UIMM5_PLUS1,
   OPERAND_UIMM5_GE6_PLUS1,
   OPERAND_UIMM5_LSB0,
+  OPERAND_UIMM5_SLIST,
   OPERAND_UIMM6,
   OPERAND_UIMM6_LSB0,
   OPERAND_UIMM7,
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
index f045c89a972cb..3ff3368f02461 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
@@ -84,6 +84,10 @@ class RISCVMCCodeEmitter : public MCCodeEmitter {
                                SmallVectorImpl<MCFixup> &Fixups,
                                const MCSubtargetInfo &STI) const;
 
+  uint64_t getImmOpValueSlist(const MCInst &MI, unsigned OpNo,
+                              SmallVectorImpl<MCFixup> &Fixups,
+                              const MCSubtargetInfo &STI) const;
+
   uint64_t getImmOpValueAsr1(const MCInst &MI, unsigned OpNo,
                              SmallVectorImpl<MCFixup> &Fixups,
                              const MCSubtargetInfo &STI) const;
@@ -404,6 +408,36 @@ RISCVMCCodeEmitter::getImmOpValueMinus1(const MCInst &MI, unsigned OpNo,
   return 0;
 }
 
+uint64_t
+RISCVMCCodeEmitter::getImmOpValueSlist(const MCInst &MI, unsigned OpNo,
+                                       SmallVectorImpl<MCFixup> &Fixups,
+                                       const MCSubtargetInfo &STI) const {
+  const MCOperand &MO = MI.getOperand(OpNo);
+  assert(MO.isImm() && "Slist operand must be immediate");
+
+  uint64_t Res = MO.getImm();
+  switch (Res) {
+  case 0:
+    return 0;
+  case 1:
+    return 1;
+  case 2:
+    return 2;
+  case 4:
+    return 3;
+  case 8:
+    return 4;
+  case 16:
+    return 5;
+  case 15:
+    return 6;
+  case 31:
+    return 7;
+  default:
+    llvm_unreachable("Unhandled Slist value!");
+  }
+}
+
 uint64_t
 RISCVMCCodeEmitter::getImmOpValueAsr1(const MCInst &MI, unsigned OpNo,
                                       SmallVectorImpl<MCFixup> &Fixups,
diff --git a/llvm/lib/Target/RISCV/RISCVFeatures.td b/llvm/lib/Target/RISCV/RISCVFeatures.td
index c1223beb304ad..70718113a3b39 100644
--- a/llvm/lib/Target/RISCV/RISCVFeatures.td
+++ b/llvm/lib/Target/RISCV/RISCVFeatures.td
@@ -1448,6 +1448,14 @@ def HasVendorXqcisim
                 AssemblerPredicate<(all_of FeatureVendorXqcisim),
                 "'Xqcisim' (Qualcomm uC Simulation Hint Extension)">;
 
+def FeatureVendorXqcisync
+    : RISCVExperimentalExtension<0, 2, "Qualcomm uC Sync Delay Extension",
+                                 [FeatureStdExtZca]>;
+def HasVendorXqcisync
+    : Predicate<"Subtarget->hasVendorXqcisync()">,
+                AssemblerPredicate<(all_of FeatureVendorXqcisync),
+                "'Xqcisync' (Qualcomm uC Sync Delay Extension)">;
+
 // Rivos Extension(s)
 
 def FeatureVendorXRivosVisni
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
index 86d31937ab7a2..caa66dd8fa739 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
@@ -50,6 +50,21 @@ def uimm5ge6_plus1 : RISCVOp<XLenVT>, ImmLeaf<XLenVT,
   let OperandType = "OPERAND_UIMM5_GE6_PLUS1";
 }
 
+def uimm5slist : RISCVOp<XLenVT>, ImmLeaf<XLenVT,
+  [{return ((Imm == 0)  ||
+            (Imm == 1)  ||
+            (Imm == 2)  ||
+            (Imm == 4)  ||
+            (Imm == 8)  ||
+            (Imm == 16) ||
+            (Imm == 15) ||
+            (Imm == 31));}]> {
+  let ParserMatchClass = UImmAsmOperand<5, "Slist">;
+  let EncoderMethod = "getImmOpValueSlist";
+  let DecoderMethod = "decodeUImmSlistOperand";
+  let OperandType = "OPERAND_UIMM5_SLIST";
+}
+
 def uimm10 : RISCVUImmLeafOp<10>;
 
 def uimm11 : RISCVUImmLeafOp<11>;
@@ -364,6 +379,27 @@ class QCISim_RS1<bits<4> imm11_8, string opcodestr>
   let imm12 = {imm11_8, 0b00000000};
 }
 
+let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
+class QCISync_UIMM5<bits<4> imm11_8, string opcodestr>
+    : RVInstI<0b011, OPC_OP_IMM, (outs), (ins uimm5:$imm5), opcodestr, "$imm5">
+{
+  bits<5> imm5;
+
+  let rs1 = 0;
+  let rd = 0;
+  let imm12 = {imm11_8, 0b000, imm5};
+}
+
+let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
+class QCIRVInst16CBSYNC<bits<3> imm5_func2, string OpcodeStr>
+    : RVInst16CB<0b100, 0b01, (outs), (ins uimm5slist:$slist), OpcodeStr, "$slist"> {
+    bits<3> slist;
+
+    let Inst{6-2} = 0;
+    let Inst{9-7} = slist;
+    let Inst{12-10} = imm5_func2;
+}
+
 class QCIRVInstEIBase<bits<3> funct3, bits<2> funct2, dag outs,
                       dag ins, string opcodestr, string argstr>
     : RVInst48<outs, ins, opcodestr, argstr, [], InstFormatOther> {
@@ -753,6 +789,27 @@ let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in {
 } // hasSideEffects = 0, mayLoad = 0, mayStore = 0
 } // Predicates = [HasVendorXqcilia, IsRV32]
 
+let Predicates = [HasVendorXqcisync, IsRV32] in {
+  def QC_SYNC : QCISync_UIMM5<0b0001, "qc.sync">;
+  def QC_SYNCR : QCISync_UIMM5<0b0010, "qc.syncr">;
+  def QC_SYNCWF : QCISync_UIMM5<0b0100, "qc.syncwf">;
+  def QC_SYNCWL : QCISync_UIMM5<0b1000, "qc.syncwl">;
+
+  def QC_C_SYNC   : QCIRVInst16CBSYNC<0b000, "qc.c.sync">;
+  def QC_C_SYNCR  : QCIRVInst16CBSYNC<0b001, "qc.c.syncr">;
+  def QC_C_SYNCWF : QCIRVInst16CBSYNC<0b100, "qc.c.syncwf">;
+  def QC_C_SYNCWL : QCIRVInst16CBSYNC<0b101, "qc.c.syncwl">;
+
+  let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
+  def QC_C_DELAY : RVInst16CI<0b000, 0b10, (outs),
+                              (ins uimm5nonzero:$imm),
+                              "qc.c.delay", "$imm"> {
+    let Inst{12} = 0;
+    let Inst{11-7} = 0;
+    let Inst{6-2} = imm{4-0};
+  }
+} // Predicates = [HasVendorXqcisync, IsRV32]
+
 let Predicates = [HasVendorXqcisim, IsRV32] in {
 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in {
   def QC_PSYSCALLI : RVInstI<0b010, OPC_OP_IMM, (outs), (ins uimm10:$imm10),
diff --git a/llvm/lib/TargetParser/RISCVISAInfo.cpp b/llvm/lib/TargetParser/RISCVISAInfo.cpp
index 4cb263b028625..cb161b0bfad5f 100644
--- a/llvm/lib/TargetParser/RISCVISAInfo.cpp
+++ b/llvm/lib/TargetParser/RISCVISAInfo.cpp
@@ -744,10 +744,10 @@ Error RISCVISAInfo::checkDependency() {
   bool HasXqccmp = Exts.count("xqccmp") != 0;
 
   static constexpr StringLiteral XqciExts[] = {
-      {"xqcia"},   {"xqciac"},  {"xqcibi"},  {"xqcibm"},
-      {"xqcicli"}, {"xqcicm"},  {"xqcics"},  {"xqcicsr"},
-      {"xqciint"}, {"xqcilb"},  {"xqcili"},  {"xqcilia"},
-      {"xqcilo"},  {"xqcilsm"}, {"xqcisim"}, {"xqcisls"}};
+      {"xqcia"},   {"xqciac"},  {"xqcibi"},  {"xqcibm"},  {"xqcicli"},
+      {"xqcicm"},  {"xqcics"},  {"xqcicsr"}, {"xqciint"}, {"xqcilb"},
+      {"xqcili"},  {"xqcilia"}, {"xqcilo"},  {"xqcilsm"}, {"xqcisim"},
+      {"xqcisls"}, {"xqcisync"}};
   static constexpr StringLiteral ZcdOverlaps[] = {
       {"zcmt"}, {"zcmp"}, {"xqccmp"}, {"xqciac"}, {"xqcicm"}};
 
diff --git a/llvm/test/CodeGen/RISCV/attributes.ll b/llvm/test/CodeGen/RISCV/attributes.ll
index cc2ce1a572d9a..71fe6ce38fd46 100644
--- a/llvm/test/CodeGen/RISCV/attributes.ll
+++ b/llvm/test/CodeGen/RISCV/attributes.ll
@@ -97,6 +97,7 @@
 ; 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
 ; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcisim %s -o - | FileCheck --check-prefix=RV32XQCISIM %s
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcisync %s -o - | FileCheck --check-prefix=RV32XQCISYNC %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
@@ -427,6 +428,7 @@
 ; RV32XQCILO: .attribute 5, "rv32i2p1_zca1p0_xqcilo0p2"
 ; RV32XQCILSM: .attribute 5, "rv32i2p1_xqcilsm0p2"
 ; RV32XQCISIM: attribute 5, "rv32i2p1_zca1p0_xqcisim0p2"
+; RV32XQCISYNC: attribute 5, "rv32i2p1_zca1p0_xqcisync0p2"
 ; RV32XQCISLS: .attribute 5, "rv32i2p1_xqcisls0p2"
 ; RV32ZAAMO: .attribute 5, "rv32i2p1_zaamo1p0"
 ; RV32ZALRSC: .attribute 5, "rv32i2p1_zalrsc1p0"
diff --git a/llvm/test/MC/RISCV/xqcisync-invalid.s b/llvm/test/MC/RISCV/xqcisync-invalid.s
new file mode 100644
index 0000000000000..6c945c9e5cfb0
--- /dev/null
+++ b/llvm/test/MC/RISCV/xqcisync-invalid.s
@@ -0,0 +1,121 @@
+# Xqcisync - Qualcomm uC Sync Delay Extension
+# RUN: not llvm-mc -triple riscv32 -mattr=+experimental-xqcisync < %s 2>&1 \
+# RUN:     | FileCheck -check-prefixes=CHECK,CHECK-PLUS %s
+# RUN: not llvm-mc -triple riscv32 -mattr=-experimental-xqcisync < %s 2>&1 \
+# RUN:     | FileCheck -check-prefixes=CHECK,CHECK-MINUS %s
+
+# CHECK-PLUS: :[[@LINE+1]]:12: error: immediate must be an integer in the range [1, 31]
+qc.c.delay 34
+
+# CHECK: :[[@LINE+1]]:16: error: invalid operand for instruction
+qc.c.delay 11, 12
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.c.delay
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcisync' (Qualcomm uC Sync Delay Extension)
+qc.c.delay   10
+
+
+# CHECK-PLUS: :[[@LINE+1]]:9: error: immediate must be an integer in the range [0, 31]
+qc.sync 45
+
+# CHECK: :[[@LINE+1]]:13: error: invalid operand for instruction
+qc.sync 22, x4
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.sync
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcisync' (Qualcomm uC Sync Delay Extension)
+qc.sync 8
+
+
+# CHECK-PLUS: :[[@LINE+1]]:10: error: immediate must be an integer in the range [0, 31]
+qc.syncr 56
+
+# CHECK: :[[@LINE+1]]:14: error: invalid operand for instruction
+qc.syncr 31, 45
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.syncr
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcisync' (Qualcomm uC Sync Delay Extension)
+qc.syncr   23
+
+
+# CHECK-PLUS: :[[@LINE+1]]:11: error: immediate must be an integer in the range [0, 31]
+qc.syncwf 88
+
+# CHECK: :[[@LINE+1]]:14: error: invalid operand for instruction
+qc.syncwf 5, 44
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.syncwf
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcisync' (Qualcomm uC Sync Delay Extension)
+qc.syncwf  31
+
+
+# CHECK-PLUS: :[[@LINE+1]]:11: error: immediate must be an integer in the range [0, 31]
+qc.syncwl 99
+
+# CHECK: :[[@LINE+1]]:15: error: invalid operand for instruction
+qc.syncwl 11, x10
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.syncwl
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcisync' (Qualcomm uC Sync Delay Extension)
+qc.syncwl  1
+
+
+# CHECK-PLUS: :[[@LINE+1]]:11: error: immediate must be one of: 0, 1, 2, 4, 8, 15, 16, 31
+qc.c.sync 45
+
+# CHECK: :[[@LINE+1]]:15: error: invalid operand for instruction
+qc.c.sync 31, x4
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.c.sync
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcisync' (Qualcomm uC Sync Delay Extension)
+qc.c.sync 8
+
+
+# CHECK-PLUS: :[[@LINE+1]]:12: error: immediate must be one of: 0, 1, 2, 4, 8, 15, 16, 31
+qc.c.syncr 56
+
+# CHECK: :[[@LINE+1]]:16: error: invalid operand for instruction
+qc.c.syncr 31, 45
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.c.syncr
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcisync' (Qualcomm uC Sync Delay Extension)
+qc.c.syncr   8
+
+
+# CHECK-PLUS: :[[@LINE+1]]:13: error: immediate must be one of: 0, 1, 2, 4, 8, 15, 16, 31
+qc.c.syncwf 88
+
+# CHECK: :[[@LINE+1]]:16: error: invalid operand for instruction
+qc.c.syncwf 8, 44
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.c.syncwf
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcisync' (Qualcomm uC Sync Delay Extension)
+qc.c.syncwf  31
+
+
+# CHECK-PLUS: :[[@LINE+1]]:13: error: immediate must be one of: 0, 1, 2, 4, 8, 15, 16, 31
+qc.c.syncwl 99
+
+# CHECK: :[[@LINE+1]]:17: error: invalid operand for instruction
+qc.c.syncwl 15, x10
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.c.syncwl
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcisync' (Qualcomm uC Sync Delay Extension)
+qc.c.syncwl  1
diff --git a/llvm/test/MC/RISCV/xqcisync-valid.s b/llvm/test/MC/RISCV/xqcisync-valid.s
new file mode 100644
index 0000000000000..3eedf99247b22
--- /dev/null
+++ b/llvm/test/MC/RISCV/xqcisync-valid.s
@@ -0,0 +1,47 @@
+# Xqcisync - Qualcomm uC Sync Delay Extension
+# RUN: llvm-mc %s -triple=riscv32 -mattr=+experimental-xqcisync -riscv-no-aliases -show-encoding \
+# RUN:     | FileCheck -check-prefixes=CHECK-ENC,CHECK-INST %s
+# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+experimental-xqcisync < %s \
+# RUN:     | llvm-objdump --mattr=+experimental-xqcisync -M no-aliases --no-print-imm-hex -d - \
+# RUN:     | FileCheck -check-prefix=CHECK-INST %s
+# RUN: llvm-mc %s -triple=riscv32 -mattr=+experimental-xqcisync -show-encoding \
+# RUN:     | FileCheck -check-prefixes=CHECK-ENC,CHECK-INST %s
+# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+experimental-xqcisync < %s \
+# RUN:     | llvm-objdump --mattr=+experimental-xqcisync --no-print-imm-hex -d - \
+# RUN:     | FileCheck -check-prefix=CHECK-INST %s
+
+# CHECK-INST: qc.c.delay     10
+# CHECK-ENC: encoding: [0x2a,0x00]
+qc.c.delay 10
+
+# CHECK-INST: qc.sync      8
+# CHECK-ENC: encoding: [0x13,0x30,0x80,0x10]
+qc.sync 8
+
+...
[truncated]

@llvmbot
Copy link
Member

llvmbot commented Mar 22, 2025

@llvm/pr-subscribers-mc

Author: Sudharsan Veeravalli (svs-quic)

Changes

…on (#132184)""

This reverts commit fe7776e.

With a minor fix for the build failures.


Patch is 21.58 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/132520.diff

14 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/AsmParser/RISCVAsmParser.cpp (+17)
  • (modified) llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp (+18-8)
  • (modified) llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h (+1)
  • (modified) llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp (+34)
  • (modified) llvm/lib/Target/RISCV/RISCVFeatures.td (+8)
  • (modified) llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td (+57)
  • (modified) llvm/lib/TargetParser/RISCVISAInfo.cpp (+4-4)
  • (modified) llvm/test/CodeGen/RISCV/attributes.ll (+2)
  • (added) llvm/test/MC/RISCV/xqcisync-invalid.s (+121)
  • (added) llvm/test/MC/RISCV/xqcisync-valid.s (+47)
  • (modified) llvm/unittests/TargetParser/RISCVISAInfoTest.cpp (+2-1)
diff --git a/clang/test/Driver/print-supported-extensions-riscv.c b/clang/test/Driver/print-supported-extensions-riscv.c
index d6c50da75fe4f..b5533b54347b9 100644
--- a/clang/test/Driver/print-supported-extensions-riscv.c
+++ b/clang/test/Driver/print-supported-extensions-riscv.c
@@ -213,6 +213,7 @@
 // CHECK-NEXT:     xqcilsm              0.2       'Xqcilsm' (Qualcomm uC Load Store Multiple Extension)
 // CHECK-NEXT:     xqcisim              0.2       'Xqcisim' (Qualcomm uC Simulation Hint Extension)
 // CHECK-NEXT:     xqcisls              0.2       'Xqcisls' (Qualcomm uC Scaled Load Store Extension)
+// CHECK-NEXT:     xqcisync             0.2       'Xqcisync' (Qualcomm uC Sync Delay Extension)
 // CHECK-NEXT:     xrivosvisni          0.1       'XRivosVisni' (Rivos Vector Integer Small New)
 // CHECK-NEXT:     xrivosvizip          0.1       'XRivosVizip' (Rivos Vector Register Zips)
 // CHECK-EMPTY:
diff --git a/llvm/docs/RISCVUsage.rst b/llvm/docs/RISCVUsage.rst
index 4f261f06ce633..8735b274a805f 100644
--- a/llvm/docs/RISCVUsage.rst
+++ b/llvm/docs/RISCVUsage.rst
@@ -485,6 +485,9 @@ The current vendor extensions supported are:
 ``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-Xqcisync``
+  LLVM implements `version 0.2 of the Qualcomm uC Sync Delay 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.
+
 ``Xmipscmove``
   LLVM implements conditional move for the `p8700 processor <https://mips.com/products/hardware/p8700/>` by MIPS.
 
diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md
index 157065cb86214..1e39f761ecdad 100644
--- a/llvm/docs/ReleaseNotes.md
+++ b/llvm/docs/ReleaseNotes.md
@@ -140,6 +140,8 @@ 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 experimental assembler support for the Qualcomm uC 'Xqcisync` (Sync Delay)
+  extension.
 * Adds assembler support for the 'Zilsd` (Load/Store Pair Instructions)
   extension.
 * Adds assembler support for the 'Zclsd` (Compressed Load/Store Pair Instructions)
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index 5833ce2270e72..ccaa8ac1c7dbb 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -772,6 +772,18 @@ struct RISCVOperand final : public MCParsedAsmOperand {
            VK == RISCVMCExpr::VK_None;
   }
 
+  bool isUImm5Slist() const {
+    if (!isImm())
+      return false;
+    RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
+    int64_t Imm;
+    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
+    return IsConstantImm &&
+           ((Imm == 0) || (Imm == 1) || (Imm == 2) || (Imm == 4) ||
+            (Imm == 8) || (Imm == 16) || (Imm == 15) || (Imm == 31)) &&
+           VK == RISCVMCExpr::VK_None;
+  }
+
   bool isUImm8GE32() const {
     int64_t Imm;
     RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
@@ -1655,6 +1667,11 @@ bool RISCVAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
     return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 5));
   case Match_InvalidUImm5GE6Plus1:
     return generateImmOutOfRangeError(Operands, ErrorInfo, 6, (1 << 5));
+  case Match_InvalidUImm5Slist: {
+    SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
+    return Error(ErrorLoc,
+                 "immediate must be one of: 0, 1, 2, 4, 8, 15, 16, 31");
+  }
   case Match_InvalidUImm6:
     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 6) - 1);
   case Match_InvalidUImm7:
diff --git a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
index 5abf15a404dfb..93cbf662bfa32 100644
--- a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
+++ b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
@@ -370,6 +370,15 @@ static DecodeStatus decodeUImmPlus1OperandGE(MCInst &Inst, uint32_t Imm,
   return MCDisassembler::Success;
 }
 
+static DecodeStatus decodeUImmSlistOperand(MCInst &Inst, uint32_t Imm,
+                                           int64_t Address,
+                                           const MCDisassembler *Decoder) {
+  assert(isUInt<3>(Imm) && "Invalid Slist immediate");
+  const uint8_t Slist[] = {0, 1, 2, 4, 8, 16, 15, 31};
+  Inst.addOperand(MCOperand::createImm(Slist[Imm]));
+  return MCDisassembler::Success;
+}
+
 static DecodeStatus decodeUImmLog2XLenOperand(MCInst &Inst, uint32_t Imm,
                                               int64_t Address,
                                               const MCDisassembler *Decoder) {
@@ -663,14 +672,15 @@ static constexpr FeatureBitset XRivosFeatureGroup = {
 };
 
 static constexpr FeatureBitset XqciFeatureGroup = {
-    RISCV::FeatureVendorXqcia,   RISCV::FeatureVendorXqciac,
-    RISCV::FeatureVendorXqcibi,  RISCV::FeatureVendorXqcibm,
-    RISCV::FeatureVendorXqcicli, RISCV::FeatureVendorXqcicm,
-    RISCV::FeatureVendorXqcics,  RISCV::FeatureVendorXqcicsr,
-    RISCV::FeatureVendorXqciint, RISCV::FeatureVendorXqcilb,
-    RISCV::FeatureVendorXqcili,  RISCV::FeatureVendorXqcilia,
-    RISCV::FeatureVendorXqcilo,  RISCV::FeatureVendorXqcilsm,
-    RISCV::FeatureVendorXqcisim, RISCV::FeatureVendorXqcisls,
+    RISCV::FeatureVendorXqcia,    RISCV::FeatureVendorXqciac,
+    RISCV::FeatureVendorXqcibi,   RISCV::FeatureVendorXqcibm,
+    RISCV::FeatureVendorXqcicli,  RISCV::FeatureVendorXqcicm,
+    RISCV::FeatureVendorXqcics,   RISCV::FeatureVendorXqcicsr,
+    RISCV::FeatureVendorXqciint,  RISCV::FeatureVendorXqcilb,
+    RISCV::FeatureVendorXqcili,   RISCV::FeatureVendorXqcilia,
+    RISCV::FeatureVendorXqcilo,   RISCV::FeatureVendorXqcilsm,
+    RISCV::FeatureVendorXqcisim,  RISCV::FeatureVendorXqcisls,
+    RISCV::FeatureVendorXqcisync,
 };
 
 static constexpr FeatureBitset XSfVectorGroup = {
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
index 0b08dfb31741d..db305b0083415 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
@@ -299,6 +299,7 @@ enum OperandType : unsigned {
   OPERAND_UIMM5_PLUS1,
   OPERAND_UIMM5_GE6_PLUS1,
   OPERAND_UIMM5_LSB0,
+  OPERAND_UIMM5_SLIST,
   OPERAND_UIMM6,
   OPERAND_UIMM6_LSB0,
   OPERAND_UIMM7,
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
index f045c89a972cb..3ff3368f02461 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
@@ -84,6 +84,10 @@ class RISCVMCCodeEmitter : public MCCodeEmitter {
                                SmallVectorImpl<MCFixup> &Fixups,
                                const MCSubtargetInfo &STI) const;
 
+  uint64_t getImmOpValueSlist(const MCInst &MI, unsigned OpNo,
+                              SmallVectorImpl<MCFixup> &Fixups,
+                              const MCSubtargetInfo &STI) const;
+
   uint64_t getImmOpValueAsr1(const MCInst &MI, unsigned OpNo,
                              SmallVectorImpl<MCFixup> &Fixups,
                              const MCSubtargetInfo &STI) const;
@@ -404,6 +408,36 @@ RISCVMCCodeEmitter::getImmOpValueMinus1(const MCInst &MI, unsigned OpNo,
   return 0;
 }
 
+uint64_t
+RISCVMCCodeEmitter::getImmOpValueSlist(const MCInst &MI, unsigned OpNo,
+                                       SmallVectorImpl<MCFixup> &Fixups,
+                                       const MCSubtargetInfo &STI) const {
+  const MCOperand &MO = MI.getOperand(OpNo);
+  assert(MO.isImm() && "Slist operand must be immediate");
+
+  uint64_t Res = MO.getImm();
+  switch (Res) {
+  case 0:
+    return 0;
+  case 1:
+    return 1;
+  case 2:
+    return 2;
+  case 4:
+    return 3;
+  case 8:
+    return 4;
+  case 16:
+    return 5;
+  case 15:
+    return 6;
+  case 31:
+    return 7;
+  default:
+    llvm_unreachable("Unhandled Slist value!");
+  }
+}
+
 uint64_t
 RISCVMCCodeEmitter::getImmOpValueAsr1(const MCInst &MI, unsigned OpNo,
                                       SmallVectorImpl<MCFixup> &Fixups,
diff --git a/llvm/lib/Target/RISCV/RISCVFeatures.td b/llvm/lib/Target/RISCV/RISCVFeatures.td
index c1223beb304ad..70718113a3b39 100644
--- a/llvm/lib/Target/RISCV/RISCVFeatures.td
+++ b/llvm/lib/Target/RISCV/RISCVFeatures.td
@@ -1448,6 +1448,14 @@ def HasVendorXqcisim
                 AssemblerPredicate<(all_of FeatureVendorXqcisim),
                 "'Xqcisim' (Qualcomm uC Simulation Hint Extension)">;
 
+def FeatureVendorXqcisync
+    : RISCVExperimentalExtension<0, 2, "Qualcomm uC Sync Delay Extension",
+                                 [FeatureStdExtZca]>;
+def HasVendorXqcisync
+    : Predicate<"Subtarget->hasVendorXqcisync()">,
+                AssemblerPredicate<(all_of FeatureVendorXqcisync),
+                "'Xqcisync' (Qualcomm uC Sync Delay Extension)">;
+
 // Rivos Extension(s)
 
 def FeatureVendorXRivosVisni
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
index 86d31937ab7a2..caa66dd8fa739 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
@@ -50,6 +50,21 @@ def uimm5ge6_plus1 : RISCVOp<XLenVT>, ImmLeaf<XLenVT,
   let OperandType = "OPERAND_UIMM5_GE6_PLUS1";
 }
 
+def uimm5slist : RISCVOp<XLenVT>, ImmLeaf<XLenVT,
+  [{return ((Imm == 0)  ||
+            (Imm == 1)  ||
+            (Imm == 2)  ||
+            (Imm == 4)  ||
+            (Imm == 8)  ||
+            (Imm == 16) ||
+            (Imm == 15) ||
+            (Imm == 31));}]> {
+  let ParserMatchClass = UImmAsmOperand<5, "Slist">;
+  let EncoderMethod = "getImmOpValueSlist";
+  let DecoderMethod = "decodeUImmSlistOperand";
+  let OperandType = "OPERAND_UIMM5_SLIST";
+}
+
 def uimm10 : RISCVUImmLeafOp<10>;
 
 def uimm11 : RISCVUImmLeafOp<11>;
@@ -364,6 +379,27 @@ class QCISim_RS1<bits<4> imm11_8, string opcodestr>
   let imm12 = {imm11_8, 0b00000000};
 }
 
+let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
+class QCISync_UIMM5<bits<4> imm11_8, string opcodestr>
+    : RVInstI<0b011, OPC_OP_IMM, (outs), (ins uimm5:$imm5), opcodestr, "$imm5">
+{
+  bits<5> imm5;
+
+  let rs1 = 0;
+  let rd = 0;
+  let imm12 = {imm11_8, 0b000, imm5};
+}
+
+let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
+class QCIRVInst16CBSYNC<bits<3> imm5_func2, string OpcodeStr>
+    : RVInst16CB<0b100, 0b01, (outs), (ins uimm5slist:$slist), OpcodeStr, "$slist"> {
+    bits<3> slist;
+
+    let Inst{6-2} = 0;
+    let Inst{9-7} = slist;
+    let Inst{12-10} = imm5_func2;
+}
+
 class QCIRVInstEIBase<bits<3> funct3, bits<2> funct2, dag outs,
                       dag ins, string opcodestr, string argstr>
     : RVInst48<outs, ins, opcodestr, argstr, [], InstFormatOther> {
@@ -753,6 +789,27 @@ let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in {
 } // hasSideEffects = 0, mayLoad = 0, mayStore = 0
 } // Predicates = [HasVendorXqcilia, IsRV32]
 
+let Predicates = [HasVendorXqcisync, IsRV32] in {
+  def QC_SYNC : QCISync_UIMM5<0b0001, "qc.sync">;
+  def QC_SYNCR : QCISync_UIMM5<0b0010, "qc.syncr">;
+  def QC_SYNCWF : QCISync_UIMM5<0b0100, "qc.syncwf">;
+  def QC_SYNCWL : QCISync_UIMM5<0b1000, "qc.syncwl">;
+
+  def QC_C_SYNC   : QCIRVInst16CBSYNC<0b000, "qc.c.sync">;
+  def QC_C_SYNCR  : QCIRVInst16CBSYNC<0b001, "qc.c.syncr">;
+  def QC_C_SYNCWF : QCIRVInst16CBSYNC<0b100, "qc.c.syncwf">;
+  def QC_C_SYNCWL : QCIRVInst16CBSYNC<0b101, "qc.c.syncwl">;
+
+  let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
+  def QC_C_DELAY : RVInst16CI<0b000, 0b10, (outs),
+                              (ins uimm5nonzero:$imm),
+                              "qc.c.delay", "$imm"> {
+    let Inst{12} = 0;
+    let Inst{11-7} = 0;
+    let Inst{6-2} = imm{4-0};
+  }
+} // Predicates = [HasVendorXqcisync, IsRV32]
+
 let Predicates = [HasVendorXqcisim, IsRV32] in {
 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in {
   def QC_PSYSCALLI : RVInstI<0b010, OPC_OP_IMM, (outs), (ins uimm10:$imm10),
diff --git a/llvm/lib/TargetParser/RISCVISAInfo.cpp b/llvm/lib/TargetParser/RISCVISAInfo.cpp
index 4cb263b028625..cb161b0bfad5f 100644
--- a/llvm/lib/TargetParser/RISCVISAInfo.cpp
+++ b/llvm/lib/TargetParser/RISCVISAInfo.cpp
@@ -744,10 +744,10 @@ Error RISCVISAInfo::checkDependency() {
   bool HasXqccmp = Exts.count("xqccmp") != 0;
 
   static constexpr StringLiteral XqciExts[] = {
-      {"xqcia"},   {"xqciac"},  {"xqcibi"},  {"xqcibm"},
-      {"xqcicli"}, {"xqcicm"},  {"xqcics"},  {"xqcicsr"},
-      {"xqciint"}, {"xqcilb"},  {"xqcili"},  {"xqcilia"},
-      {"xqcilo"},  {"xqcilsm"}, {"xqcisim"}, {"xqcisls"}};
+      {"xqcia"},   {"xqciac"},  {"xqcibi"},  {"xqcibm"},  {"xqcicli"},
+      {"xqcicm"},  {"xqcics"},  {"xqcicsr"}, {"xqciint"}, {"xqcilb"},
+      {"xqcili"},  {"xqcilia"}, {"xqcilo"},  {"xqcilsm"}, {"xqcisim"},
+      {"xqcisls"}, {"xqcisync"}};
   static constexpr StringLiteral ZcdOverlaps[] = {
       {"zcmt"}, {"zcmp"}, {"xqccmp"}, {"xqciac"}, {"xqcicm"}};
 
diff --git a/llvm/test/CodeGen/RISCV/attributes.ll b/llvm/test/CodeGen/RISCV/attributes.ll
index cc2ce1a572d9a..71fe6ce38fd46 100644
--- a/llvm/test/CodeGen/RISCV/attributes.ll
+++ b/llvm/test/CodeGen/RISCV/attributes.ll
@@ -97,6 +97,7 @@
 ; 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
 ; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcisim %s -o - | FileCheck --check-prefix=RV32XQCISIM %s
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcisync %s -o - | FileCheck --check-prefix=RV32XQCISYNC %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
@@ -427,6 +428,7 @@
 ; RV32XQCILO: .attribute 5, "rv32i2p1_zca1p0_xqcilo0p2"
 ; RV32XQCILSM: .attribute 5, "rv32i2p1_xqcilsm0p2"
 ; RV32XQCISIM: attribute 5, "rv32i2p1_zca1p0_xqcisim0p2"
+; RV32XQCISYNC: attribute 5, "rv32i2p1_zca1p0_xqcisync0p2"
 ; RV32XQCISLS: .attribute 5, "rv32i2p1_xqcisls0p2"
 ; RV32ZAAMO: .attribute 5, "rv32i2p1_zaamo1p0"
 ; RV32ZALRSC: .attribute 5, "rv32i2p1_zalrsc1p0"
diff --git a/llvm/test/MC/RISCV/xqcisync-invalid.s b/llvm/test/MC/RISCV/xqcisync-invalid.s
new file mode 100644
index 0000000000000..6c945c9e5cfb0
--- /dev/null
+++ b/llvm/test/MC/RISCV/xqcisync-invalid.s
@@ -0,0 +1,121 @@
+# Xqcisync - Qualcomm uC Sync Delay Extension
+# RUN: not llvm-mc -triple riscv32 -mattr=+experimental-xqcisync < %s 2>&1 \
+# RUN:     | FileCheck -check-prefixes=CHECK,CHECK-PLUS %s
+# RUN: not llvm-mc -triple riscv32 -mattr=-experimental-xqcisync < %s 2>&1 \
+# RUN:     | FileCheck -check-prefixes=CHECK,CHECK-MINUS %s
+
+# CHECK-PLUS: :[[@LINE+1]]:12: error: immediate must be an integer in the range [1, 31]
+qc.c.delay 34
+
+# CHECK: :[[@LINE+1]]:16: error: invalid operand for instruction
+qc.c.delay 11, 12
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.c.delay
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcisync' (Qualcomm uC Sync Delay Extension)
+qc.c.delay   10
+
+
+# CHECK-PLUS: :[[@LINE+1]]:9: error: immediate must be an integer in the range [0, 31]
+qc.sync 45
+
+# CHECK: :[[@LINE+1]]:13: error: invalid operand for instruction
+qc.sync 22, x4
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.sync
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcisync' (Qualcomm uC Sync Delay Extension)
+qc.sync 8
+
+
+# CHECK-PLUS: :[[@LINE+1]]:10: error: immediate must be an integer in the range [0, 31]
+qc.syncr 56
+
+# CHECK: :[[@LINE+1]]:14: error: invalid operand for instruction
+qc.syncr 31, 45
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.syncr
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcisync' (Qualcomm uC Sync Delay Extension)
+qc.syncr   23
+
+
+# CHECK-PLUS: :[[@LINE+1]]:11: error: immediate must be an integer in the range [0, 31]
+qc.syncwf 88
+
+# CHECK: :[[@LINE+1]]:14: error: invalid operand for instruction
+qc.syncwf 5, 44
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.syncwf
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcisync' (Qualcomm uC Sync Delay Extension)
+qc.syncwf  31
+
+
+# CHECK-PLUS: :[[@LINE+1]]:11: error: immediate must be an integer in the range [0, 31]
+qc.syncwl 99
+
+# CHECK: :[[@LINE+1]]:15: error: invalid operand for instruction
+qc.syncwl 11, x10
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.syncwl
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcisync' (Qualcomm uC Sync Delay Extension)
+qc.syncwl  1
+
+
+# CHECK-PLUS: :[[@LINE+1]]:11: error: immediate must be one of: 0, 1, 2, 4, 8, 15, 16, 31
+qc.c.sync 45
+
+# CHECK: :[[@LINE+1]]:15: error: invalid operand for instruction
+qc.c.sync 31, x4
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.c.sync
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcisync' (Qualcomm uC Sync Delay Extension)
+qc.c.sync 8
+
+
+# CHECK-PLUS: :[[@LINE+1]]:12: error: immediate must be one of: 0, 1, 2, 4, 8, 15, 16, 31
+qc.c.syncr 56
+
+# CHECK: :[[@LINE+1]]:16: error: invalid operand for instruction
+qc.c.syncr 31, 45
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.c.syncr
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcisync' (Qualcomm uC Sync Delay Extension)
+qc.c.syncr   8
+
+
+# CHECK-PLUS: :[[@LINE+1]]:13: error: immediate must be one of: 0, 1, 2, 4, 8, 15, 16, 31
+qc.c.syncwf 88
+
+# CHECK: :[[@LINE+1]]:16: error: invalid operand for instruction
+qc.c.syncwf 8, 44
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.c.syncwf
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcisync' (Qualcomm uC Sync Delay Extension)
+qc.c.syncwf  31
+
+
+# CHECK-PLUS: :[[@LINE+1]]:13: error: immediate must be one of: 0, 1, 2, 4, 8, 15, 16, 31
+qc.c.syncwl 99
+
+# CHECK: :[[@LINE+1]]:17: error: invalid operand for instruction
+qc.c.syncwl 15, x10
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.c.syncwl
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcisync' (Qualcomm uC Sync Delay Extension)
+qc.c.syncwl  1
diff --git a/llvm/test/MC/RISCV/xqcisync-valid.s b/llvm/test/MC/RISCV/xqcisync-valid.s
new file mode 100644
index 0000000000000..3eedf99247b22
--- /dev/null
+++ b/llvm/test/MC/RISCV/xqcisync-valid.s
@@ -0,0 +1,47 @@
+# Xqcisync - Qualcomm uC Sync Delay Extension
+# RUN: llvm-mc %s -triple=riscv32 -mattr=+experimental-xqcisync -riscv-no-aliases -show-encoding \
+# RUN:     | FileCheck -check-prefixes=CHECK-ENC,CHECK-INST %s
+# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+experimental-xqcisync < %s \
+# RUN:     | llvm-objdump --mattr=+experimental-xqcisync -M no-aliases --no-print-imm-hex -d - \
+# RUN:     | FileCheck -check-prefix=CHECK-INST %s
+# RUN: llvm-mc %s -triple=riscv32 -mattr=+experimental-xqcisync -show-encoding \
+# RUN:     | FileCheck -check-prefixes=CHECK-ENC,CHECK-INST %s
+# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+experimental-xqcisync < %s \
+# RUN:     | llvm-objdump --mattr=+experimental-xqcisync --no-print-imm-hex -d - \
+# RUN:     | FileCheck -check-prefix=CHECK-INST %s
+
+# CHECK-INST: qc.c.delay     10
+# CHECK-ENC: encoding: [0x2a,0x00]
+qc.c.delay 10
+
+# CHECK-INST: qc.sync      8
+# CHECK-ENC: encoding: [0x13,0x30,0x80,0x10]
+qc.sync 8
+
+...
[truncated]

@llvmbot
Copy link
Member

llvmbot commented Mar 22, 2025

@llvm/pr-subscribers-clang-driver

Author: Sudharsan Veeravalli (svs-quic)

Changes

…on (#132184)""

This reverts commit fe7776e.

With a minor fix for the build failures.


Patch is 21.58 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/132520.diff

14 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/AsmParser/RISCVAsmParser.cpp (+17)
  • (modified) llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp (+18-8)
  • (modified) llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h (+1)
  • (modified) llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp (+34)
  • (modified) llvm/lib/Target/RISCV/RISCVFeatures.td (+8)
  • (modified) llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td (+57)
  • (modified) llvm/lib/TargetParser/RISCVISAInfo.cpp (+4-4)
  • (modified) llvm/test/CodeGen/RISCV/attributes.ll (+2)
  • (added) llvm/test/MC/RISCV/xqcisync-invalid.s (+121)
  • (added) llvm/test/MC/RISCV/xqcisync-valid.s (+47)
  • (modified) llvm/unittests/TargetParser/RISCVISAInfoTest.cpp (+2-1)
diff --git a/clang/test/Driver/print-supported-extensions-riscv.c b/clang/test/Driver/print-supported-extensions-riscv.c
index d6c50da75fe4f..b5533b54347b9 100644
--- a/clang/test/Driver/print-supported-extensions-riscv.c
+++ b/clang/test/Driver/print-supported-extensions-riscv.c
@@ -213,6 +213,7 @@
 // CHECK-NEXT:     xqcilsm              0.2       'Xqcilsm' (Qualcomm uC Load Store Multiple Extension)
 // CHECK-NEXT:     xqcisim              0.2       'Xqcisim' (Qualcomm uC Simulation Hint Extension)
 // CHECK-NEXT:     xqcisls              0.2       'Xqcisls' (Qualcomm uC Scaled Load Store Extension)
+// CHECK-NEXT:     xqcisync             0.2       'Xqcisync' (Qualcomm uC Sync Delay Extension)
 // CHECK-NEXT:     xrivosvisni          0.1       'XRivosVisni' (Rivos Vector Integer Small New)
 // CHECK-NEXT:     xrivosvizip          0.1       'XRivosVizip' (Rivos Vector Register Zips)
 // CHECK-EMPTY:
diff --git a/llvm/docs/RISCVUsage.rst b/llvm/docs/RISCVUsage.rst
index 4f261f06ce633..8735b274a805f 100644
--- a/llvm/docs/RISCVUsage.rst
+++ b/llvm/docs/RISCVUsage.rst
@@ -485,6 +485,9 @@ The current vendor extensions supported are:
 ``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-Xqcisync``
+  LLVM implements `version 0.2 of the Qualcomm uC Sync Delay 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.
+
 ``Xmipscmove``
   LLVM implements conditional move for the `p8700 processor <https://mips.com/products/hardware/p8700/>` by MIPS.
 
diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md
index 157065cb86214..1e39f761ecdad 100644
--- a/llvm/docs/ReleaseNotes.md
+++ b/llvm/docs/ReleaseNotes.md
@@ -140,6 +140,8 @@ 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 experimental assembler support for the Qualcomm uC 'Xqcisync` (Sync Delay)
+  extension.
 * Adds assembler support for the 'Zilsd` (Load/Store Pair Instructions)
   extension.
 * Adds assembler support for the 'Zclsd` (Compressed Load/Store Pair Instructions)
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index 5833ce2270e72..ccaa8ac1c7dbb 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -772,6 +772,18 @@ struct RISCVOperand final : public MCParsedAsmOperand {
            VK == RISCVMCExpr::VK_None;
   }
 
+  bool isUImm5Slist() const {
+    if (!isImm())
+      return false;
+    RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
+    int64_t Imm;
+    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
+    return IsConstantImm &&
+           ((Imm == 0) || (Imm == 1) || (Imm == 2) || (Imm == 4) ||
+            (Imm == 8) || (Imm == 16) || (Imm == 15) || (Imm == 31)) &&
+           VK == RISCVMCExpr::VK_None;
+  }
+
   bool isUImm8GE32() const {
     int64_t Imm;
     RISCVMCExpr::Specifier VK = RISCVMCExpr::VK_None;
@@ -1655,6 +1667,11 @@ bool RISCVAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
     return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 5));
   case Match_InvalidUImm5GE6Plus1:
     return generateImmOutOfRangeError(Operands, ErrorInfo, 6, (1 << 5));
+  case Match_InvalidUImm5Slist: {
+    SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
+    return Error(ErrorLoc,
+                 "immediate must be one of: 0, 1, 2, 4, 8, 15, 16, 31");
+  }
   case Match_InvalidUImm6:
     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 6) - 1);
   case Match_InvalidUImm7:
diff --git a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
index 5abf15a404dfb..93cbf662bfa32 100644
--- a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
+++ b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
@@ -370,6 +370,15 @@ static DecodeStatus decodeUImmPlus1OperandGE(MCInst &Inst, uint32_t Imm,
   return MCDisassembler::Success;
 }
 
+static DecodeStatus decodeUImmSlistOperand(MCInst &Inst, uint32_t Imm,
+                                           int64_t Address,
+                                           const MCDisassembler *Decoder) {
+  assert(isUInt<3>(Imm) && "Invalid Slist immediate");
+  const uint8_t Slist[] = {0, 1, 2, 4, 8, 16, 15, 31};
+  Inst.addOperand(MCOperand::createImm(Slist[Imm]));
+  return MCDisassembler::Success;
+}
+
 static DecodeStatus decodeUImmLog2XLenOperand(MCInst &Inst, uint32_t Imm,
                                               int64_t Address,
                                               const MCDisassembler *Decoder) {
@@ -663,14 +672,15 @@ static constexpr FeatureBitset XRivosFeatureGroup = {
 };
 
 static constexpr FeatureBitset XqciFeatureGroup = {
-    RISCV::FeatureVendorXqcia,   RISCV::FeatureVendorXqciac,
-    RISCV::FeatureVendorXqcibi,  RISCV::FeatureVendorXqcibm,
-    RISCV::FeatureVendorXqcicli, RISCV::FeatureVendorXqcicm,
-    RISCV::FeatureVendorXqcics,  RISCV::FeatureVendorXqcicsr,
-    RISCV::FeatureVendorXqciint, RISCV::FeatureVendorXqcilb,
-    RISCV::FeatureVendorXqcili,  RISCV::FeatureVendorXqcilia,
-    RISCV::FeatureVendorXqcilo,  RISCV::FeatureVendorXqcilsm,
-    RISCV::FeatureVendorXqcisim, RISCV::FeatureVendorXqcisls,
+    RISCV::FeatureVendorXqcia,    RISCV::FeatureVendorXqciac,
+    RISCV::FeatureVendorXqcibi,   RISCV::FeatureVendorXqcibm,
+    RISCV::FeatureVendorXqcicli,  RISCV::FeatureVendorXqcicm,
+    RISCV::FeatureVendorXqcics,   RISCV::FeatureVendorXqcicsr,
+    RISCV::FeatureVendorXqciint,  RISCV::FeatureVendorXqcilb,
+    RISCV::FeatureVendorXqcili,   RISCV::FeatureVendorXqcilia,
+    RISCV::FeatureVendorXqcilo,   RISCV::FeatureVendorXqcilsm,
+    RISCV::FeatureVendorXqcisim,  RISCV::FeatureVendorXqcisls,
+    RISCV::FeatureVendorXqcisync,
 };
 
 static constexpr FeatureBitset XSfVectorGroup = {
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
index 0b08dfb31741d..db305b0083415 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
@@ -299,6 +299,7 @@ enum OperandType : unsigned {
   OPERAND_UIMM5_PLUS1,
   OPERAND_UIMM5_GE6_PLUS1,
   OPERAND_UIMM5_LSB0,
+  OPERAND_UIMM5_SLIST,
   OPERAND_UIMM6,
   OPERAND_UIMM6_LSB0,
   OPERAND_UIMM7,
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
index f045c89a972cb..3ff3368f02461 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
@@ -84,6 +84,10 @@ class RISCVMCCodeEmitter : public MCCodeEmitter {
                                SmallVectorImpl<MCFixup> &Fixups,
                                const MCSubtargetInfo &STI) const;
 
+  uint64_t getImmOpValueSlist(const MCInst &MI, unsigned OpNo,
+                              SmallVectorImpl<MCFixup> &Fixups,
+                              const MCSubtargetInfo &STI) const;
+
   uint64_t getImmOpValueAsr1(const MCInst &MI, unsigned OpNo,
                              SmallVectorImpl<MCFixup> &Fixups,
                              const MCSubtargetInfo &STI) const;
@@ -404,6 +408,36 @@ RISCVMCCodeEmitter::getImmOpValueMinus1(const MCInst &MI, unsigned OpNo,
   return 0;
 }
 
+uint64_t
+RISCVMCCodeEmitter::getImmOpValueSlist(const MCInst &MI, unsigned OpNo,
+                                       SmallVectorImpl<MCFixup> &Fixups,
+                                       const MCSubtargetInfo &STI) const {
+  const MCOperand &MO = MI.getOperand(OpNo);
+  assert(MO.isImm() && "Slist operand must be immediate");
+
+  uint64_t Res = MO.getImm();
+  switch (Res) {
+  case 0:
+    return 0;
+  case 1:
+    return 1;
+  case 2:
+    return 2;
+  case 4:
+    return 3;
+  case 8:
+    return 4;
+  case 16:
+    return 5;
+  case 15:
+    return 6;
+  case 31:
+    return 7;
+  default:
+    llvm_unreachable("Unhandled Slist value!");
+  }
+}
+
 uint64_t
 RISCVMCCodeEmitter::getImmOpValueAsr1(const MCInst &MI, unsigned OpNo,
                                       SmallVectorImpl<MCFixup> &Fixups,
diff --git a/llvm/lib/Target/RISCV/RISCVFeatures.td b/llvm/lib/Target/RISCV/RISCVFeatures.td
index c1223beb304ad..70718113a3b39 100644
--- a/llvm/lib/Target/RISCV/RISCVFeatures.td
+++ b/llvm/lib/Target/RISCV/RISCVFeatures.td
@@ -1448,6 +1448,14 @@ def HasVendorXqcisim
                 AssemblerPredicate<(all_of FeatureVendorXqcisim),
                 "'Xqcisim' (Qualcomm uC Simulation Hint Extension)">;
 
+def FeatureVendorXqcisync
+    : RISCVExperimentalExtension<0, 2, "Qualcomm uC Sync Delay Extension",
+                                 [FeatureStdExtZca]>;
+def HasVendorXqcisync
+    : Predicate<"Subtarget->hasVendorXqcisync()">,
+                AssemblerPredicate<(all_of FeatureVendorXqcisync),
+                "'Xqcisync' (Qualcomm uC Sync Delay Extension)">;
+
 // Rivos Extension(s)
 
 def FeatureVendorXRivosVisni
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
index 86d31937ab7a2..caa66dd8fa739 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
@@ -50,6 +50,21 @@ def uimm5ge6_plus1 : RISCVOp<XLenVT>, ImmLeaf<XLenVT,
   let OperandType = "OPERAND_UIMM5_GE6_PLUS1";
 }
 
+def uimm5slist : RISCVOp<XLenVT>, ImmLeaf<XLenVT,
+  [{return ((Imm == 0)  ||
+            (Imm == 1)  ||
+            (Imm == 2)  ||
+            (Imm == 4)  ||
+            (Imm == 8)  ||
+            (Imm == 16) ||
+            (Imm == 15) ||
+            (Imm == 31));}]> {
+  let ParserMatchClass = UImmAsmOperand<5, "Slist">;
+  let EncoderMethod = "getImmOpValueSlist";
+  let DecoderMethod = "decodeUImmSlistOperand";
+  let OperandType = "OPERAND_UIMM5_SLIST";
+}
+
 def uimm10 : RISCVUImmLeafOp<10>;
 
 def uimm11 : RISCVUImmLeafOp<11>;
@@ -364,6 +379,27 @@ class QCISim_RS1<bits<4> imm11_8, string opcodestr>
   let imm12 = {imm11_8, 0b00000000};
 }
 
+let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
+class QCISync_UIMM5<bits<4> imm11_8, string opcodestr>
+    : RVInstI<0b011, OPC_OP_IMM, (outs), (ins uimm5:$imm5), opcodestr, "$imm5">
+{
+  bits<5> imm5;
+
+  let rs1 = 0;
+  let rd = 0;
+  let imm12 = {imm11_8, 0b000, imm5};
+}
+
+let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
+class QCIRVInst16CBSYNC<bits<3> imm5_func2, string OpcodeStr>
+    : RVInst16CB<0b100, 0b01, (outs), (ins uimm5slist:$slist), OpcodeStr, "$slist"> {
+    bits<3> slist;
+
+    let Inst{6-2} = 0;
+    let Inst{9-7} = slist;
+    let Inst{12-10} = imm5_func2;
+}
+
 class QCIRVInstEIBase<bits<3> funct3, bits<2> funct2, dag outs,
                       dag ins, string opcodestr, string argstr>
     : RVInst48<outs, ins, opcodestr, argstr, [], InstFormatOther> {
@@ -753,6 +789,27 @@ let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in {
 } // hasSideEffects = 0, mayLoad = 0, mayStore = 0
 } // Predicates = [HasVendorXqcilia, IsRV32]
 
+let Predicates = [HasVendorXqcisync, IsRV32] in {
+  def QC_SYNC : QCISync_UIMM5<0b0001, "qc.sync">;
+  def QC_SYNCR : QCISync_UIMM5<0b0010, "qc.syncr">;
+  def QC_SYNCWF : QCISync_UIMM5<0b0100, "qc.syncwf">;
+  def QC_SYNCWL : QCISync_UIMM5<0b1000, "qc.syncwl">;
+
+  def QC_C_SYNC   : QCIRVInst16CBSYNC<0b000, "qc.c.sync">;
+  def QC_C_SYNCR  : QCIRVInst16CBSYNC<0b001, "qc.c.syncr">;
+  def QC_C_SYNCWF : QCIRVInst16CBSYNC<0b100, "qc.c.syncwf">;
+  def QC_C_SYNCWL : QCIRVInst16CBSYNC<0b101, "qc.c.syncwl">;
+
+  let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
+  def QC_C_DELAY : RVInst16CI<0b000, 0b10, (outs),
+                              (ins uimm5nonzero:$imm),
+                              "qc.c.delay", "$imm"> {
+    let Inst{12} = 0;
+    let Inst{11-7} = 0;
+    let Inst{6-2} = imm{4-0};
+  }
+} // Predicates = [HasVendorXqcisync, IsRV32]
+
 let Predicates = [HasVendorXqcisim, IsRV32] in {
 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in {
   def QC_PSYSCALLI : RVInstI<0b010, OPC_OP_IMM, (outs), (ins uimm10:$imm10),
diff --git a/llvm/lib/TargetParser/RISCVISAInfo.cpp b/llvm/lib/TargetParser/RISCVISAInfo.cpp
index 4cb263b028625..cb161b0bfad5f 100644
--- a/llvm/lib/TargetParser/RISCVISAInfo.cpp
+++ b/llvm/lib/TargetParser/RISCVISAInfo.cpp
@@ -744,10 +744,10 @@ Error RISCVISAInfo::checkDependency() {
   bool HasXqccmp = Exts.count("xqccmp") != 0;
 
   static constexpr StringLiteral XqciExts[] = {
-      {"xqcia"},   {"xqciac"},  {"xqcibi"},  {"xqcibm"},
-      {"xqcicli"}, {"xqcicm"},  {"xqcics"},  {"xqcicsr"},
-      {"xqciint"}, {"xqcilb"},  {"xqcili"},  {"xqcilia"},
-      {"xqcilo"},  {"xqcilsm"}, {"xqcisim"}, {"xqcisls"}};
+      {"xqcia"},   {"xqciac"},  {"xqcibi"},  {"xqcibm"},  {"xqcicli"},
+      {"xqcicm"},  {"xqcics"},  {"xqcicsr"}, {"xqciint"}, {"xqcilb"},
+      {"xqcili"},  {"xqcilia"}, {"xqcilo"},  {"xqcilsm"}, {"xqcisim"},
+      {"xqcisls"}, {"xqcisync"}};
   static constexpr StringLiteral ZcdOverlaps[] = {
       {"zcmt"}, {"zcmp"}, {"xqccmp"}, {"xqciac"}, {"xqcicm"}};
 
diff --git a/llvm/test/CodeGen/RISCV/attributes.ll b/llvm/test/CodeGen/RISCV/attributes.ll
index cc2ce1a572d9a..71fe6ce38fd46 100644
--- a/llvm/test/CodeGen/RISCV/attributes.ll
+++ b/llvm/test/CodeGen/RISCV/attributes.ll
@@ -97,6 +97,7 @@
 ; 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
 ; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcisim %s -o - | FileCheck --check-prefix=RV32XQCISIM %s
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcisync %s -o - | FileCheck --check-prefix=RV32XQCISYNC %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
@@ -427,6 +428,7 @@
 ; RV32XQCILO: .attribute 5, "rv32i2p1_zca1p0_xqcilo0p2"
 ; RV32XQCILSM: .attribute 5, "rv32i2p1_xqcilsm0p2"
 ; RV32XQCISIM: attribute 5, "rv32i2p1_zca1p0_xqcisim0p2"
+; RV32XQCISYNC: attribute 5, "rv32i2p1_zca1p0_xqcisync0p2"
 ; RV32XQCISLS: .attribute 5, "rv32i2p1_xqcisls0p2"
 ; RV32ZAAMO: .attribute 5, "rv32i2p1_zaamo1p0"
 ; RV32ZALRSC: .attribute 5, "rv32i2p1_zalrsc1p0"
diff --git a/llvm/test/MC/RISCV/xqcisync-invalid.s b/llvm/test/MC/RISCV/xqcisync-invalid.s
new file mode 100644
index 0000000000000..6c945c9e5cfb0
--- /dev/null
+++ b/llvm/test/MC/RISCV/xqcisync-invalid.s
@@ -0,0 +1,121 @@
+# Xqcisync - Qualcomm uC Sync Delay Extension
+# RUN: not llvm-mc -triple riscv32 -mattr=+experimental-xqcisync < %s 2>&1 \
+# RUN:     | FileCheck -check-prefixes=CHECK,CHECK-PLUS %s
+# RUN: not llvm-mc -triple riscv32 -mattr=-experimental-xqcisync < %s 2>&1 \
+# RUN:     | FileCheck -check-prefixes=CHECK,CHECK-MINUS %s
+
+# CHECK-PLUS: :[[@LINE+1]]:12: error: immediate must be an integer in the range [1, 31]
+qc.c.delay 34
+
+# CHECK: :[[@LINE+1]]:16: error: invalid operand for instruction
+qc.c.delay 11, 12
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.c.delay
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcisync' (Qualcomm uC Sync Delay Extension)
+qc.c.delay   10
+
+
+# CHECK-PLUS: :[[@LINE+1]]:9: error: immediate must be an integer in the range [0, 31]
+qc.sync 45
+
+# CHECK: :[[@LINE+1]]:13: error: invalid operand for instruction
+qc.sync 22, x4
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.sync
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcisync' (Qualcomm uC Sync Delay Extension)
+qc.sync 8
+
+
+# CHECK-PLUS: :[[@LINE+1]]:10: error: immediate must be an integer in the range [0, 31]
+qc.syncr 56
+
+# CHECK: :[[@LINE+1]]:14: error: invalid operand for instruction
+qc.syncr 31, 45
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.syncr
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcisync' (Qualcomm uC Sync Delay Extension)
+qc.syncr   23
+
+
+# CHECK-PLUS: :[[@LINE+1]]:11: error: immediate must be an integer in the range [0, 31]
+qc.syncwf 88
+
+# CHECK: :[[@LINE+1]]:14: error: invalid operand for instruction
+qc.syncwf 5, 44
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.syncwf
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcisync' (Qualcomm uC Sync Delay Extension)
+qc.syncwf  31
+
+
+# CHECK-PLUS: :[[@LINE+1]]:11: error: immediate must be an integer in the range [0, 31]
+qc.syncwl 99
+
+# CHECK: :[[@LINE+1]]:15: error: invalid operand for instruction
+qc.syncwl 11, x10
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.syncwl
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcisync' (Qualcomm uC Sync Delay Extension)
+qc.syncwl  1
+
+
+# CHECK-PLUS: :[[@LINE+1]]:11: error: immediate must be one of: 0, 1, 2, 4, 8, 15, 16, 31
+qc.c.sync 45
+
+# CHECK: :[[@LINE+1]]:15: error: invalid operand for instruction
+qc.c.sync 31, x4
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.c.sync
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcisync' (Qualcomm uC Sync Delay Extension)
+qc.c.sync 8
+
+
+# CHECK-PLUS: :[[@LINE+1]]:12: error: immediate must be one of: 0, 1, 2, 4, 8, 15, 16, 31
+qc.c.syncr 56
+
+# CHECK: :[[@LINE+1]]:16: error: invalid operand for instruction
+qc.c.syncr 31, 45
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.c.syncr
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcisync' (Qualcomm uC Sync Delay Extension)
+qc.c.syncr   8
+
+
+# CHECK-PLUS: :[[@LINE+1]]:13: error: immediate must be one of: 0, 1, 2, 4, 8, 15, 16, 31
+qc.c.syncwf 88
+
+# CHECK: :[[@LINE+1]]:16: error: invalid operand for instruction
+qc.c.syncwf 8, 44
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.c.syncwf
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcisync' (Qualcomm uC Sync Delay Extension)
+qc.c.syncwf  31
+
+
+# CHECK-PLUS: :[[@LINE+1]]:13: error: immediate must be one of: 0, 1, 2, 4, 8, 15, 16, 31
+qc.c.syncwl 99
+
+# CHECK: :[[@LINE+1]]:17: error: invalid operand for instruction
+qc.c.syncwl 15, x10
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.c.syncwl
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcisync' (Qualcomm uC Sync Delay Extension)
+qc.c.syncwl  1
diff --git a/llvm/test/MC/RISCV/xqcisync-valid.s b/llvm/test/MC/RISCV/xqcisync-valid.s
new file mode 100644
index 0000000000000..3eedf99247b22
--- /dev/null
+++ b/llvm/test/MC/RISCV/xqcisync-valid.s
@@ -0,0 +1,47 @@
+# Xqcisync - Qualcomm uC Sync Delay Extension
+# RUN: llvm-mc %s -triple=riscv32 -mattr=+experimental-xqcisync -riscv-no-aliases -show-encoding \
+# RUN:     | FileCheck -check-prefixes=CHECK-ENC,CHECK-INST %s
+# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+experimental-xqcisync < %s \
+# RUN:     | llvm-objdump --mattr=+experimental-xqcisync -M no-aliases --no-print-imm-hex -d - \
+# RUN:     | FileCheck -check-prefix=CHECK-INST %s
+# RUN: llvm-mc %s -triple=riscv32 -mattr=+experimental-xqcisync -show-encoding \
+# RUN:     | FileCheck -check-prefixes=CHECK-ENC,CHECK-INST %s
+# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+experimental-xqcisync < %s \
+# RUN:     | llvm-objdump --mattr=+experimental-xqcisync --no-print-imm-hex -d - \
+# RUN:     | FileCheck -check-prefix=CHECK-INST %s
+
+# CHECK-INST: qc.c.delay     10
+# CHECK-ENC: encoding: [0x2a,0x00]
+qc.c.delay 10
+
+# CHECK-INST: qc.sync      8
+# CHECK-ENC: encoding: [0x13,0x30,0x80,0x10]
+qc.sync 8
+
+...
[truncated]

@topperc
Copy link
Collaborator

topperc commented Mar 22, 2025

Please avoid "Revert 'Revert" in commit names. Use "Recommit".

@svs-quic svs-quic merged commit e710797 into llvm:main Mar 22, 2025
17 checks passed
@svs-quic
Copy link
Contributor Author

Please avoid "Revert 'Revert" in commit names. Use "Recommit".

Thanks I've made the change while committing.

@svs-quic svs-quic deleted the xqcisync branch March 25, 2025 06:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend:RISC-V clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' clang Clang issues not falling into any other category mc Machine (object) code
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants