Skip to content

[RISCV] Update to Xqciint v0.4 #130219

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 2 commits into from
Mar 11, 2025
Merged

[RISCV] Update to Xqciint v0.4 #130219

merged 2 commits into from
Mar 11, 2025

Conversation

lenary
Copy link
Member

@lenary lenary commented Mar 7, 2025

The Xqci 0.7.0 spec just came out, with some updates to Xqciint, bringing it to v0.4. The main update of any relevance is that qc.c.mienter and qc.c.mienter.nest now update both the stack pointer and the frame pointer (before, they only updated the stack pointer). They both remain compatible with the frame pointer convention.

This change bumps the Xqciint version, and ensures that we don't emit the unneeded frame pointer adjustment instruction after qc.c.mienter(.nest).

The Xqci 0.7.0 spec just came out, with some updates to Xqciint,
bringing it to v0.4. The main update of any relevance is that
`qc.c.mienter` and `qc.c.mienter.nest` now update both the stack pointer
and the frame pointer (before, they only updated the stack pointer).
They both remain compatible with the frame pointer convention.

This change bumps the Xqciint version, and ensures that we don't emit
the unneeded frame pointer adjustment instruction after
`qc.c.mienter(.nest)`.
@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' clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Mar 7, 2025
@lenary lenary requested review from topperc, svs-quic and hchandel March 7, 2025 01:33
@llvmbot
Copy link
Member

llvmbot commented Mar 7, 2025

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

@llvm/pr-subscribers-clang

Author: Sam Elliott (lenary)

Changes

The Xqci 0.7.0 spec just came out, with some updates to Xqciint, bringing it to v0.4. The main update of any relevance is that qc.c.mienter and qc.c.mienter.nest now update both the stack pointer and the frame pointer (before, they only updated the stack pointer). They both remain compatible with the frame pointer convention.

This change bumps the Xqciint version, and ensures that we don't emit the unneeded frame pointer adjustment instruction after qc.c.mienter(.nest).


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

11 Files Affected:

  • (modified) clang/include/clang/Basic/AttrDocs.td (+1-1)
  • (modified) clang/test/Driver/print-supported-extensions-riscv.c (+1-1)
  • (modified) llvm/docs/RISCVUsage.rst (+1-1)
  • (modified) llvm/lib/Target/RISCV/RISCVFeatures.td (+1-1)
  • (modified) llvm/lib/Target/RISCV/RISCVFrameLowering.cpp (+3-4)
  • (modified) llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td (+1-1)
  • (modified) llvm/lib/Target/RISCV/RISCVMachineFunctionInfo.cpp (+24)
  • (modified) llvm/lib/Target/RISCV/RISCVMachineFunctionInfo.h (+6)
  • (modified) llvm/test/CodeGen/RISCV/attributes.ll (+1-1)
  • (modified) llvm/test/CodeGen/RISCV/qci-interrupt-attr.ll (-12)
  • (modified) llvm/unittests/TargetParser/RISCVISAInfoTest.cpp (+2-2)
diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td
index fdc58d1c92c0d..02bab407d08fe 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -2848,7 +2848,7 @@ https://gcc.gnu.org/onlinedocs/gcc/RISC-V-Function-Attributes.html
 https://riscv.org/specifications/privileged-isa/
 The RISC-V Instruction Set Manual Volume II: Privileged Architecture
 Version 1.10.
-https://github.com/quic/riscv-unified-db/releases/tag/Xqci-0.6
+https://github.com/quic/riscv-unified-db/releases/tag/Xqci-0.7
   }];
 }
 
diff --git a/clang/test/Driver/print-supported-extensions-riscv.c b/clang/test/Driver/print-supported-extensions-riscv.c
index 69b76f0c4c4cd..d9335fe502bb6 100644
--- a/clang/test/Driver/print-supported-extensions-riscv.c
+++ b/clang/test/Driver/print-supported-extensions-riscv.c
@@ -201,7 +201,7 @@
 // CHECK-NEXT:     xqcicm               0.2       'Xqcicm' (Qualcomm uC Conditional Move Extension)
 // CHECK-NEXT:     xqcics               0.2       'Xqcics' (Qualcomm uC Conditional Select Extension)
 // CHECK-NEXT:     xqcicsr              0.2       'Xqcicsr' (Qualcomm uC CSR Extension)
-// CHECK-NEXT:     xqciint              0.2       'Xqciint' (Qualcomm uC Interrupts Extension)
+// CHECK-NEXT:     xqciint              0.4       'Xqciint' (Qualcomm uC Interrupts Extension)
 // CHECK-NEXT:     xqcilia              0.2       'Xqcilia' (Qualcomm uC Large Immediate Arithmetic Extension)
 // CHECK-NEXT:     xqcilo               0.2       'Xqcilo' (Qualcomm uC Large Offset Load Store Extension)
 // CHECK-NEXT:     xqcilsm              0.2       'Xqcilsm' (Qualcomm uC Load Store Multiple Extension)
diff --git a/llvm/docs/RISCVUsage.rst b/llvm/docs/RISCVUsage.rst
index 62c6a4fd80fd4..831e8fd5d186b 100644
--- a/llvm/docs/RISCVUsage.rst
+++ b/llvm/docs/RISCVUsage.rst
@@ -454,7 +454,7 @@ The current vendor extensions supported are:
   LLVM implements `version 0.2 of the Qualcomm uC CSR extension specification <https://github.com/quic/riscv-unified-db/releases/latest>`__ by Qualcomm.  All instructions are prefixed with `qc.` as described in the specification. These instructions are only available for riscv32.
 
 ``experimental-Xqciint``
-  LLVM implements `version 0.2 of the Qualcomm uC Interrupts extension specification <https://github.com/quic/riscv-unified-db/releases/latest>`__ by Qualcomm.  All instructions are prefixed with `qc.` as described in the specification. These instructions are only available for riscv32.
+  LLVM implements `version 0.4 of the Qualcomm uC Interrupts extension specification <https://github.com/quic/riscv-unified-db/releases/latest>`__ by Qualcomm.  All instructions are prefixed with `qc.` as described in the specification. These instructions are only available for riscv32.
 
 ``experimental-Xqcilia``
   LLVM implements `version 0.2 of the Qualcomm uC Large Immediate Arithmetic extension specification <https://github.com/quic/riscv-unified-db/releases/latest>`__ by Qualcomm.  All instructions are prefixed with `qc.` as described in the specification. These instructions are only available for riscv32.
diff --git a/llvm/lib/Target/RISCV/RISCVFeatures.td b/llvm/lib/Target/RISCV/RISCVFeatures.td
index 35db027509d94..544ad14266183 100644
--- a/llvm/lib/Target/RISCV/RISCVFeatures.td
+++ b/llvm/lib/Target/RISCV/RISCVFeatures.td
@@ -1351,7 +1351,7 @@ def HasVendorXqcicm
                          "'Xqcicm' (Qualcomm uC Conditional Move Extension)">;
 
 def FeatureVendorXqciint
-    : RISCVExperimentalExtension<0, 2, "Qualcomm uC Interrupts Extension",
+    : RISCVExperimentalExtension<0, 4, "Qualcomm uC Interrupts Extension",
                                  [FeatureStdExtZca]>;
 def HasVendorXqciint
     : Predicate<"Subtarget->hasVendorXqciint()">,
diff --git a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
index 6b61a236cf570..e1314d4fee8a0 100644
--- a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
@@ -1008,10 +1008,9 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF,
     // The frame pointer does need to be reserved from register allocation.
     assert(MF.getRegInfo().isReserved(FPReg) && "FP not reserved");
 
-    // Xqccmp with hasFP will update FP using `qc.cm.pushfp`, so we don't need
-    // to update it again, but we do need to emit the `.cfi_def_cfa` below.
-    if (RVFI->getPushPopKind(MF) !=
-        RISCVMachineFunctionInfo::PushPopKind::VendorXqccmp) {
+    // Some stack management variants automatically keep FP updated, so we don't
+    // need an instruction to do so.
+    if (!RVFI->hasImplicitFPUpdates(MF)) {
       RI->adjustReg(
           MBB, MBBI, DL, FPReg, SPReg,
           StackOffset::getFixed(RealStackSize - RVFI->getVarArgsSaveSize()),
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
index 8e84a01821f56..32cfade8697b9 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
@@ -568,7 +568,7 @@ let Predicates = [HasVendorXqciint, IsRV32], hasSideEffects = 1 in {
 
   let mayLoad = 0, mayStore = 1,
     Uses = [X1, X2, X5, X6, X7, X8, X10, X11, X12, X13, X14, X15, X16, X17, X28, X29, X30, X31],
-    Defs = [X2] in {
+    Defs = [X2, X8] in {
   def QC_C_MIENTER      : QCIRVInst16CI_NONE<0b10000, "qc.c.mienter">;
   def QC_C_MIENTER_NEST : QCIRVInst16CI_NONE<0b10001, "qc.c.mienter.nest">;
   } // mayLoad = 1, mayStore = 1, Uses = [...], Defs = [...]
diff --git a/llvm/lib/Target/RISCV/RISCVMachineFunctionInfo.cpp b/llvm/lib/Target/RISCV/RISCVMachineFunctionInfo.cpp
index a2fdbcc7f4d28..0a3ea9f6e0d6c 100644
--- a/llvm/lib/Target/RISCV/RISCVMachineFunctionInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVMachineFunctionInfo.cpp
@@ -100,6 +100,29 @@ RISCVMachineFunctionInfo::getPushPopKind(const MachineFunction &MF) const {
   return PushPopKind::None;
 }
 
+bool RISCVMachineFunctionInfo::hasImplicitFPUpdates(const MachineFunction &MF) const {
+  switch (getInterruptStackKind(MF)) {
+  case InterruptStackKind::QCINest:
+  case InterruptStackKind::QCINoNest:
+    // QC.C.MIENTER and QC.C.MIENTER.NEST both update FP on function entry.
+    return true;
+  default:
+    break;
+  }
+
+  switch (getPushPopKind(MF)) {
+  case PushPopKind::VendorXqccmp:
+    // When using Xqccmp, we will use `QC.CM.PUSHFP` when Frame Pointers are
+    // enabled, which will update FP.
+    return true;
+  default:
+    break;
+  }
+
+  return false;
+}
+
+
 void RISCVMachineFunctionInfo::initializeBaseYamlFields(
     const yaml::RISCVMachineFunctionInfo &YamlMFI) {
   VarArgsFrameIndex = YamlMFI.VarArgsFrameIndex;
@@ -113,3 +136,4 @@ void RISCVMachineFunctionInfo::addSExt32Register(Register Reg) {
 bool RISCVMachineFunctionInfo::isSExt32Register(Register Reg) const {
   return is_contained(SExt32Registers, Reg);
 }
+
diff --git a/llvm/lib/Target/RISCV/RISCVMachineFunctionInfo.h b/llvm/lib/Target/RISCV/RISCVMachineFunctionInfo.h
index f24355650ab22..4d06dea7414f1 100644
--- a/llvm/lib/Target/RISCV/RISCVMachineFunctionInfo.h
+++ b/llvm/lib/Target/RISCV/RISCVMachineFunctionInfo.h
@@ -166,6 +166,12 @@ class RISCVMachineFunctionInfo : public MachineFunctionInfo {
   unsigned getQCIInterruptStackSize() const { return QCIInterruptStackSize; }
   void setQCIInterruptStackSize(unsigned Size) { QCIInterruptStackSize = Size; }
 
+  // Some Stack Management Variants automatically update FP in a frame-pointer
+  // convention compatible way - which means we don't need to manually update
+  // the FP, but we still need to emit the correct CFI information for
+  // calculating the CFA based on FP.
+  bool hasImplicitFPUpdates(const MachineFunction &MF) const;
+
   void initializeBaseYamlFields(const yaml::RISCVMachineFunctionInfo &YamlMFI);
 
   void addSExt32Register(Register Reg);
diff --git a/llvm/test/CodeGen/RISCV/attributes.ll b/llvm/test/CodeGen/RISCV/attributes.ll
index 85e5a71fc7b62..eaf54f879df17 100644
--- a/llvm/test/CodeGen/RISCV/attributes.ll
+++ b/llvm/test/CodeGen/RISCV/attributes.ll
@@ -411,7 +411,7 @@
 ; RV32XQCICM: .attribute 5, "rv32i2p1_zca1p0_xqcicm0p2"
 ; RV32XQCICS: .attribute 5, "rv32i2p1_xqcics0p2"
 ; RV32XQCICSR: .attribute 5, "rv32i2p1_xqcicsr0p2"
-; RV32XQCIINT: .attribute 5, "rv32i2p1_zca1p0_xqciint0p2"
+; RV32XQCIINT: .attribute 5, "rv32i2p1_zca1p0_xqciint0p4"
 ; RV32XQCILIA: .attribute 5, "rv32i2p1_zca1p0_xqcilia0p2"
 ; RV32XQCILO: .attribute 5, "rv32i2p1_zca1p0_xqcilo0p2"
 ; RV32XQCILSM: .attribute 5, "rv32i2p1_xqcilsm0p2"
diff --git a/llvm/test/CodeGen/RISCV/qci-interrupt-attr.ll b/llvm/test/CodeGen/RISCV/qci-interrupt-attr.ll
index a6c90ae9e69c3..76d61eee07eef 100644
--- a/llvm/test/CodeGen/RISCV/qci-interrupt-attr.ll
+++ b/llvm/test/CodeGen/RISCV/qci-interrupt-attr.ll
@@ -65,7 +65,6 @@ define void @test_nest_empty() "interrupt"="qci-nest" {
 ; QCI-FP-NEXT:    .cfi_offset t4, -72
 ; QCI-FP-NEXT:    .cfi_offset t5, -76
 ; QCI-FP-NEXT:    .cfi_offset t6, -80
-; QCI-FP-NEXT:    addi s0, sp, 96
 ; QCI-FP-NEXT:    .cfi_def_cfa s0, 0
 ; QCI-FP-NEXT:    .cfi_def_cfa sp, 96
 ; QCI-FP-NEXT:    qc.c.mileaveret
@@ -140,7 +139,6 @@ define void @test_nonest_empty() "interrupt"="qci-nonest" {
 ; QCI-FP-NEXT:    .cfi_offset t4, -72
 ; QCI-FP-NEXT:    .cfi_offset t5, -76
 ; QCI-FP-NEXT:    .cfi_offset t6, -80
-; QCI-FP-NEXT:    addi s0, sp, 96
 ; QCI-FP-NEXT:    .cfi_def_cfa s0, 0
 ; QCI-FP-NEXT:    .cfi_def_cfa sp, 96
 ; QCI-FP-NEXT:    qc.c.mileaveret
@@ -223,7 +221,6 @@ define void @test_nest_asm() "interrupt"="qci-nest" {
 ; QCI-FP-NEXT:    .cfi_offset t4, -72
 ; QCI-FP-NEXT:    .cfi_offset t5, -76
 ; QCI-FP-NEXT:    .cfi_offset t6, -80
-; QCI-FP-NEXT:    addi s0, sp, 96
 ; QCI-FP-NEXT:    .cfi_def_cfa s0, 0
 ; QCI-FP-NEXT:    li a0, 1
 ; QCI-FP-NEXT:    #APP
@@ -315,7 +312,6 @@ define void @test_nonest_asm() "interrupt"="qci-nonest" {
 ; QCI-FP-NEXT:    .cfi_offset t4, -72
 ; QCI-FP-NEXT:    .cfi_offset t5, -76
 ; QCI-FP-NEXT:    .cfi_offset t6, -80
-; QCI-FP-NEXT:    addi s0, sp, 96
 ; QCI-FP-NEXT:    .cfi_def_cfa s0, 0
 ; QCI-FP-NEXT:    li a0, 1
 ; QCI-FP-NEXT:    #APP
@@ -423,7 +419,6 @@ define void @test_nest_call() "interrupt"="qci-nest" {
 ; QCI-FP-NEXT:    .cfi_offset t6, -80
 ; QCI-FP-NEXT:    addi sp, sp, -16
 ; QCI-FP-NEXT:    .cfi_def_cfa_offset 112
-; QCI-FP-NEXT:    addi s0, sp, 112
 ; QCI-FP-NEXT:    .cfi_def_cfa s0, 0
 ; QCI-FP-NEXT:    li a0, 4
 ; QCI-FP-NEXT:    li a2, 1
@@ -548,7 +543,6 @@ define void @test_nonest_call() "interrupt"="qci-nonest" {
 ; QCI-FP-NEXT:    .cfi_offset t6, -80
 ; QCI-FP-NEXT:    addi sp, sp, -16
 ; QCI-FP-NEXT:    .cfi_def_cfa_offset 112
-; QCI-FP-NEXT:    addi s0, sp, 112
 ; QCI-FP-NEXT:    .cfi_def_cfa s0, 0
 ; QCI-FP-NEXT:    li a0, 4
 ; QCI-FP-NEXT:    li a2, 1
@@ -807,7 +801,6 @@ define void @test_spill_nest() "interrupt"="qci-nest" {
 ; QCI-FP-NEXT:    .cfi_offset s9, -132
 ; QCI-FP-NEXT:    .cfi_offset s10, -136
 ; QCI-FP-NEXT:    .cfi_offset s11, -140
-; QCI-FP-NEXT:    addi s0, sp, 176
 ; QCI-FP-NEXT:    .cfi_def_cfa s0, 0
 ; QCI-FP-NEXT:    lui t1, %hi(var)
 ; QCI-FP-NEXT:    lw a0, %lo(var)(t1)
@@ -1264,7 +1257,6 @@ define void @test_spill_nonest() "interrupt"="qci-nonest" {
 ; QCI-FP-NEXT:    .cfi_offset s9, -132
 ; QCI-FP-NEXT:    .cfi_offset s10, -136
 ; QCI-FP-NEXT:    .cfi_offset s11, -140
-; QCI-FP-NEXT:    addi s0, sp, 176
 ; QCI-FP-NEXT:    .cfi_def_cfa s0, 0
 ; QCI-FP-NEXT:    lui t1, %hi(var)
 ; QCI-FP-NEXT:    lw a0, %lo(var)(t1)
@@ -1765,7 +1757,6 @@ define void @test_spill_call_nest() "interrupt"="qci-nest" {
 ; QCI-FP-NEXT:    .cfi_offset s9, -132
 ; QCI-FP-NEXT:    .cfi_offset s10, -136
 ; QCI-FP-NEXT:    .cfi_offset s11, -140
-; QCI-FP-NEXT:    addi s0, sp, 240
 ; QCI-FP-NEXT:    .cfi_def_cfa s0, 0
 ; QCI-FP-NEXT:    lui s6, %hi(var)
 ; QCI-FP-NEXT:    lw a0, %lo(var)(s6)
@@ -2356,7 +2347,6 @@ define void @test_spill_call_nonest() "interrupt"="qci-nonest" {
 ; QCI-FP-NEXT:    .cfi_offset s9, -132
 ; QCI-FP-NEXT:    .cfi_offset s10, -136
 ; QCI-FP-NEXT:    .cfi_offset s11, -140
-; QCI-FP-NEXT:    addi s0, sp, 240
 ; QCI-FP-NEXT:    .cfi_def_cfa s0, 0
 ; QCI-FP-NEXT:    lui s6, %hi(var)
 ; QCI-FP-NEXT:    lw a0, %lo(var)(s6)
@@ -2768,7 +2758,6 @@ define void @test_nest_explicit_s11() "interrupt"="qci-nest" {
 ; QCI-FP-NEXT:    .cfi_def_cfa_offset 112
 ; QCI-FP-NEXT:    sw s11, 12(sp) # 4-byte Folded Spill
 ; QCI-FP-NEXT:    .cfi_offset s11, -100
-; QCI-FP-NEXT:    addi s0, sp, 112
 ; QCI-FP-NEXT:    .cfi_def_cfa s0, 0
 ; QCI-FP-NEXT:    #APP
 ; QCI-FP-NEXT:    li s4, 0
@@ -2877,7 +2866,6 @@ define void @test_nonest_explicit_s11() "interrupt"="qci-nonest" {
 ; QCI-FP-NEXT:    .cfi_def_cfa_offset 112
 ; QCI-FP-NEXT:    sw s11, 12(sp) # 4-byte Folded Spill
 ; QCI-FP-NEXT:    .cfi_offset s11, -100
-; QCI-FP-NEXT:    addi s0, sp, 112
 ; QCI-FP-NEXT:    .cfi_def_cfa s0, 0
 ; QCI-FP-NEXT:    #APP
 ; QCI-FP-NEXT:    li s11, 0
diff --git a/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp b/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp
index 00dc160c39a36..e24b2d47f6bc4 100644
--- a/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp
+++ b/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp
@@ -656,7 +656,7 @@ TEST(ParseArchString, RejectsConflictingExtensions) {
   for (StringRef Input :
        {"rv64i_xqcisls0p2", "rv64i_xqcia0p4", "rv64i_xqciac0p3",
         "rv64i_xqcicsr0p2", "rv64i_xqcilsm0p2", "rv64i_xqcicm0p2",
-        "rv64i_xqcics0p2", "rv64i_xqcicli0p2", "rv64i_xqciint0p2",
+        "rv64i_xqcics0p2", "rv64i_xqcicli0p2", "rv64i_xqciint0p4",
         "rv64i_xqcilo0p2", "rv64i_xqcilia0p2", "rv64i_xqcibm0p4"}) {
     EXPECT_THAT(
         toString(RISCVISAInfo::parseArchString(Input, true).takeError()),
@@ -1132,7 +1132,7 @@ Experimental extensions
     xqcicm               0.2
     xqcics               0.2
     xqcicsr              0.2
-    xqciint              0.2
+    xqciint              0.4
     xqcilia              0.2
     xqcilo               0.2
     xqcilsm              0.2

@llvmbot
Copy link
Member

llvmbot commented Mar 7, 2025

@llvm/pr-subscribers-clang-driver

Author: Sam Elliott (lenary)

Changes

The Xqci 0.7.0 spec just came out, with some updates to Xqciint, bringing it to v0.4. The main update of any relevance is that qc.c.mienter and qc.c.mienter.nest now update both the stack pointer and the frame pointer (before, they only updated the stack pointer). They both remain compatible with the frame pointer convention.

This change bumps the Xqciint version, and ensures that we don't emit the unneeded frame pointer adjustment instruction after qc.c.mienter(.nest).


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

11 Files Affected:

  • (modified) clang/include/clang/Basic/AttrDocs.td (+1-1)
  • (modified) clang/test/Driver/print-supported-extensions-riscv.c (+1-1)
  • (modified) llvm/docs/RISCVUsage.rst (+1-1)
  • (modified) llvm/lib/Target/RISCV/RISCVFeatures.td (+1-1)
  • (modified) llvm/lib/Target/RISCV/RISCVFrameLowering.cpp (+3-4)
  • (modified) llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td (+1-1)
  • (modified) llvm/lib/Target/RISCV/RISCVMachineFunctionInfo.cpp (+24)
  • (modified) llvm/lib/Target/RISCV/RISCVMachineFunctionInfo.h (+6)
  • (modified) llvm/test/CodeGen/RISCV/attributes.ll (+1-1)
  • (modified) llvm/test/CodeGen/RISCV/qci-interrupt-attr.ll (-12)
  • (modified) llvm/unittests/TargetParser/RISCVISAInfoTest.cpp (+2-2)
diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td
index fdc58d1c92c0d..02bab407d08fe 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -2848,7 +2848,7 @@ https://gcc.gnu.org/onlinedocs/gcc/RISC-V-Function-Attributes.html
 https://riscv.org/specifications/privileged-isa/
 The RISC-V Instruction Set Manual Volume II: Privileged Architecture
 Version 1.10.
-https://github.com/quic/riscv-unified-db/releases/tag/Xqci-0.6
+https://github.com/quic/riscv-unified-db/releases/tag/Xqci-0.7
   }];
 }
 
diff --git a/clang/test/Driver/print-supported-extensions-riscv.c b/clang/test/Driver/print-supported-extensions-riscv.c
index 69b76f0c4c4cd..d9335fe502bb6 100644
--- a/clang/test/Driver/print-supported-extensions-riscv.c
+++ b/clang/test/Driver/print-supported-extensions-riscv.c
@@ -201,7 +201,7 @@
 // CHECK-NEXT:     xqcicm               0.2       'Xqcicm' (Qualcomm uC Conditional Move Extension)
 // CHECK-NEXT:     xqcics               0.2       'Xqcics' (Qualcomm uC Conditional Select Extension)
 // CHECK-NEXT:     xqcicsr              0.2       'Xqcicsr' (Qualcomm uC CSR Extension)
-// CHECK-NEXT:     xqciint              0.2       'Xqciint' (Qualcomm uC Interrupts Extension)
+// CHECK-NEXT:     xqciint              0.4       'Xqciint' (Qualcomm uC Interrupts Extension)
 // CHECK-NEXT:     xqcilia              0.2       'Xqcilia' (Qualcomm uC Large Immediate Arithmetic Extension)
 // CHECK-NEXT:     xqcilo               0.2       'Xqcilo' (Qualcomm uC Large Offset Load Store Extension)
 // CHECK-NEXT:     xqcilsm              0.2       'Xqcilsm' (Qualcomm uC Load Store Multiple Extension)
diff --git a/llvm/docs/RISCVUsage.rst b/llvm/docs/RISCVUsage.rst
index 62c6a4fd80fd4..831e8fd5d186b 100644
--- a/llvm/docs/RISCVUsage.rst
+++ b/llvm/docs/RISCVUsage.rst
@@ -454,7 +454,7 @@ The current vendor extensions supported are:
   LLVM implements `version 0.2 of the Qualcomm uC CSR extension specification <https://github.com/quic/riscv-unified-db/releases/latest>`__ by Qualcomm.  All instructions are prefixed with `qc.` as described in the specification. These instructions are only available for riscv32.
 
 ``experimental-Xqciint``
-  LLVM implements `version 0.2 of the Qualcomm uC Interrupts extension specification <https://github.com/quic/riscv-unified-db/releases/latest>`__ by Qualcomm.  All instructions are prefixed with `qc.` as described in the specification. These instructions are only available for riscv32.
+  LLVM implements `version 0.4 of the Qualcomm uC Interrupts extension specification <https://github.com/quic/riscv-unified-db/releases/latest>`__ by Qualcomm.  All instructions are prefixed with `qc.` as described in the specification. These instructions are only available for riscv32.
 
 ``experimental-Xqcilia``
   LLVM implements `version 0.2 of the Qualcomm uC Large Immediate Arithmetic extension specification <https://github.com/quic/riscv-unified-db/releases/latest>`__ by Qualcomm.  All instructions are prefixed with `qc.` as described in the specification. These instructions are only available for riscv32.
diff --git a/llvm/lib/Target/RISCV/RISCVFeatures.td b/llvm/lib/Target/RISCV/RISCVFeatures.td
index 35db027509d94..544ad14266183 100644
--- a/llvm/lib/Target/RISCV/RISCVFeatures.td
+++ b/llvm/lib/Target/RISCV/RISCVFeatures.td
@@ -1351,7 +1351,7 @@ def HasVendorXqcicm
                          "'Xqcicm' (Qualcomm uC Conditional Move Extension)">;
 
 def FeatureVendorXqciint
-    : RISCVExperimentalExtension<0, 2, "Qualcomm uC Interrupts Extension",
+    : RISCVExperimentalExtension<0, 4, "Qualcomm uC Interrupts Extension",
                                  [FeatureStdExtZca]>;
 def HasVendorXqciint
     : Predicate<"Subtarget->hasVendorXqciint()">,
diff --git a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
index 6b61a236cf570..e1314d4fee8a0 100644
--- a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
@@ -1008,10 +1008,9 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF,
     // The frame pointer does need to be reserved from register allocation.
     assert(MF.getRegInfo().isReserved(FPReg) && "FP not reserved");
 
-    // Xqccmp with hasFP will update FP using `qc.cm.pushfp`, so we don't need
-    // to update it again, but we do need to emit the `.cfi_def_cfa` below.
-    if (RVFI->getPushPopKind(MF) !=
-        RISCVMachineFunctionInfo::PushPopKind::VendorXqccmp) {
+    // Some stack management variants automatically keep FP updated, so we don't
+    // need an instruction to do so.
+    if (!RVFI->hasImplicitFPUpdates(MF)) {
       RI->adjustReg(
           MBB, MBBI, DL, FPReg, SPReg,
           StackOffset::getFixed(RealStackSize - RVFI->getVarArgsSaveSize()),
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
index 8e84a01821f56..32cfade8697b9 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
@@ -568,7 +568,7 @@ let Predicates = [HasVendorXqciint, IsRV32], hasSideEffects = 1 in {
 
   let mayLoad = 0, mayStore = 1,
     Uses = [X1, X2, X5, X6, X7, X8, X10, X11, X12, X13, X14, X15, X16, X17, X28, X29, X30, X31],
-    Defs = [X2] in {
+    Defs = [X2, X8] in {
   def QC_C_MIENTER      : QCIRVInst16CI_NONE<0b10000, "qc.c.mienter">;
   def QC_C_MIENTER_NEST : QCIRVInst16CI_NONE<0b10001, "qc.c.mienter.nest">;
   } // mayLoad = 1, mayStore = 1, Uses = [...], Defs = [...]
diff --git a/llvm/lib/Target/RISCV/RISCVMachineFunctionInfo.cpp b/llvm/lib/Target/RISCV/RISCVMachineFunctionInfo.cpp
index a2fdbcc7f4d28..0a3ea9f6e0d6c 100644
--- a/llvm/lib/Target/RISCV/RISCVMachineFunctionInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVMachineFunctionInfo.cpp
@@ -100,6 +100,29 @@ RISCVMachineFunctionInfo::getPushPopKind(const MachineFunction &MF) const {
   return PushPopKind::None;
 }
 
+bool RISCVMachineFunctionInfo::hasImplicitFPUpdates(const MachineFunction &MF) const {
+  switch (getInterruptStackKind(MF)) {
+  case InterruptStackKind::QCINest:
+  case InterruptStackKind::QCINoNest:
+    // QC.C.MIENTER and QC.C.MIENTER.NEST both update FP on function entry.
+    return true;
+  default:
+    break;
+  }
+
+  switch (getPushPopKind(MF)) {
+  case PushPopKind::VendorXqccmp:
+    // When using Xqccmp, we will use `QC.CM.PUSHFP` when Frame Pointers are
+    // enabled, which will update FP.
+    return true;
+  default:
+    break;
+  }
+
+  return false;
+}
+
+
 void RISCVMachineFunctionInfo::initializeBaseYamlFields(
     const yaml::RISCVMachineFunctionInfo &YamlMFI) {
   VarArgsFrameIndex = YamlMFI.VarArgsFrameIndex;
@@ -113,3 +136,4 @@ void RISCVMachineFunctionInfo::addSExt32Register(Register Reg) {
 bool RISCVMachineFunctionInfo::isSExt32Register(Register Reg) const {
   return is_contained(SExt32Registers, Reg);
 }
+
diff --git a/llvm/lib/Target/RISCV/RISCVMachineFunctionInfo.h b/llvm/lib/Target/RISCV/RISCVMachineFunctionInfo.h
index f24355650ab22..4d06dea7414f1 100644
--- a/llvm/lib/Target/RISCV/RISCVMachineFunctionInfo.h
+++ b/llvm/lib/Target/RISCV/RISCVMachineFunctionInfo.h
@@ -166,6 +166,12 @@ class RISCVMachineFunctionInfo : public MachineFunctionInfo {
   unsigned getQCIInterruptStackSize() const { return QCIInterruptStackSize; }
   void setQCIInterruptStackSize(unsigned Size) { QCIInterruptStackSize = Size; }
 
+  // Some Stack Management Variants automatically update FP in a frame-pointer
+  // convention compatible way - which means we don't need to manually update
+  // the FP, but we still need to emit the correct CFI information for
+  // calculating the CFA based on FP.
+  bool hasImplicitFPUpdates(const MachineFunction &MF) const;
+
   void initializeBaseYamlFields(const yaml::RISCVMachineFunctionInfo &YamlMFI);
 
   void addSExt32Register(Register Reg);
diff --git a/llvm/test/CodeGen/RISCV/attributes.ll b/llvm/test/CodeGen/RISCV/attributes.ll
index 85e5a71fc7b62..eaf54f879df17 100644
--- a/llvm/test/CodeGen/RISCV/attributes.ll
+++ b/llvm/test/CodeGen/RISCV/attributes.ll
@@ -411,7 +411,7 @@
 ; RV32XQCICM: .attribute 5, "rv32i2p1_zca1p0_xqcicm0p2"
 ; RV32XQCICS: .attribute 5, "rv32i2p1_xqcics0p2"
 ; RV32XQCICSR: .attribute 5, "rv32i2p1_xqcicsr0p2"
-; RV32XQCIINT: .attribute 5, "rv32i2p1_zca1p0_xqciint0p2"
+; RV32XQCIINT: .attribute 5, "rv32i2p1_zca1p0_xqciint0p4"
 ; RV32XQCILIA: .attribute 5, "rv32i2p1_zca1p0_xqcilia0p2"
 ; RV32XQCILO: .attribute 5, "rv32i2p1_zca1p0_xqcilo0p2"
 ; RV32XQCILSM: .attribute 5, "rv32i2p1_xqcilsm0p2"
diff --git a/llvm/test/CodeGen/RISCV/qci-interrupt-attr.ll b/llvm/test/CodeGen/RISCV/qci-interrupt-attr.ll
index a6c90ae9e69c3..76d61eee07eef 100644
--- a/llvm/test/CodeGen/RISCV/qci-interrupt-attr.ll
+++ b/llvm/test/CodeGen/RISCV/qci-interrupt-attr.ll
@@ -65,7 +65,6 @@ define void @test_nest_empty() "interrupt"="qci-nest" {
 ; QCI-FP-NEXT:    .cfi_offset t4, -72
 ; QCI-FP-NEXT:    .cfi_offset t5, -76
 ; QCI-FP-NEXT:    .cfi_offset t6, -80
-; QCI-FP-NEXT:    addi s0, sp, 96
 ; QCI-FP-NEXT:    .cfi_def_cfa s0, 0
 ; QCI-FP-NEXT:    .cfi_def_cfa sp, 96
 ; QCI-FP-NEXT:    qc.c.mileaveret
@@ -140,7 +139,6 @@ define void @test_nonest_empty() "interrupt"="qci-nonest" {
 ; QCI-FP-NEXT:    .cfi_offset t4, -72
 ; QCI-FP-NEXT:    .cfi_offset t5, -76
 ; QCI-FP-NEXT:    .cfi_offset t6, -80
-; QCI-FP-NEXT:    addi s0, sp, 96
 ; QCI-FP-NEXT:    .cfi_def_cfa s0, 0
 ; QCI-FP-NEXT:    .cfi_def_cfa sp, 96
 ; QCI-FP-NEXT:    qc.c.mileaveret
@@ -223,7 +221,6 @@ define void @test_nest_asm() "interrupt"="qci-nest" {
 ; QCI-FP-NEXT:    .cfi_offset t4, -72
 ; QCI-FP-NEXT:    .cfi_offset t5, -76
 ; QCI-FP-NEXT:    .cfi_offset t6, -80
-; QCI-FP-NEXT:    addi s0, sp, 96
 ; QCI-FP-NEXT:    .cfi_def_cfa s0, 0
 ; QCI-FP-NEXT:    li a0, 1
 ; QCI-FP-NEXT:    #APP
@@ -315,7 +312,6 @@ define void @test_nonest_asm() "interrupt"="qci-nonest" {
 ; QCI-FP-NEXT:    .cfi_offset t4, -72
 ; QCI-FP-NEXT:    .cfi_offset t5, -76
 ; QCI-FP-NEXT:    .cfi_offset t6, -80
-; QCI-FP-NEXT:    addi s0, sp, 96
 ; QCI-FP-NEXT:    .cfi_def_cfa s0, 0
 ; QCI-FP-NEXT:    li a0, 1
 ; QCI-FP-NEXT:    #APP
@@ -423,7 +419,6 @@ define void @test_nest_call() "interrupt"="qci-nest" {
 ; QCI-FP-NEXT:    .cfi_offset t6, -80
 ; QCI-FP-NEXT:    addi sp, sp, -16
 ; QCI-FP-NEXT:    .cfi_def_cfa_offset 112
-; QCI-FP-NEXT:    addi s0, sp, 112
 ; QCI-FP-NEXT:    .cfi_def_cfa s0, 0
 ; QCI-FP-NEXT:    li a0, 4
 ; QCI-FP-NEXT:    li a2, 1
@@ -548,7 +543,6 @@ define void @test_nonest_call() "interrupt"="qci-nonest" {
 ; QCI-FP-NEXT:    .cfi_offset t6, -80
 ; QCI-FP-NEXT:    addi sp, sp, -16
 ; QCI-FP-NEXT:    .cfi_def_cfa_offset 112
-; QCI-FP-NEXT:    addi s0, sp, 112
 ; QCI-FP-NEXT:    .cfi_def_cfa s0, 0
 ; QCI-FP-NEXT:    li a0, 4
 ; QCI-FP-NEXT:    li a2, 1
@@ -807,7 +801,6 @@ define void @test_spill_nest() "interrupt"="qci-nest" {
 ; QCI-FP-NEXT:    .cfi_offset s9, -132
 ; QCI-FP-NEXT:    .cfi_offset s10, -136
 ; QCI-FP-NEXT:    .cfi_offset s11, -140
-; QCI-FP-NEXT:    addi s0, sp, 176
 ; QCI-FP-NEXT:    .cfi_def_cfa s0, 0
 ; QCI-FP-NEXT:    lui t1, %hi(var)
 ; QCI-FP-NEXT:    lw a0, %lo(var)(t1)
@@ -1264,7 +1257,6 @@ define void @test_spill_nonest() "interrupt"="qci-nonest" {
 ; QCI-FP-NEXT:    .cfi_offset s9, -132
 ; QCI-FP-NEXT:    .cfi_offset s10, -136
 ; QCI-FP-NEXT:    .cfi_offset s11, -140
-; QCI-FP-NEXT:    addi s0, sp, 176
 ; QCI-FP-NEXT:    .cfi_def_cfa s0, 0
 ; QCI-FP-NEXT:    lui t1, %hi(var)
 ; QCI-FP-NEXT:    lw a0, %lo(var)(t1)
@@ -1765,7 +1757,6 @@ define void @test_spill_call_nest() "interrupt"="qci-nest" {
 ; QCI-FP-NEXT:    .cfi_offset s9, -132
 ; QCI-FP-NEXT:    .cfi_offset s10, -136
 ; QCI-FP-NEXT:    .cfi_offset s11, -140
-; QCI-FP-NEXT:    addi s0, sp, 240
 ; QCI-FP-NEXT:    .cfi_def_cfa s0, 0
 ; QCI-FP-NEXT:    lui s6, %hi(var)
 ; QCI-FP-NEXT:    lw a0, %lo(var)(s6)
@@ -2356,7 +2347,6 @@ define void @test_spill_call_nonest() "interrupt"="qci-nonest" {
 ; QCI-FP-NEXT:    .cfi_offset s9, -132
 ; QCI-FP-NEXT:    .cfi_offset s10, -136
 ; QCI-FP-NEXT:    .cfi_offset s11, -140
-; QCI-FP-NEXT:    addi s0, sp, 240
 ; QCI-FP-NEXT:    .cfi_def_cfa s0, 0
 ; QCI-FP-NEXT:    lui s6, %hi(var)
 ; QCI-FP-NEXT:    lw a0, %lo(var)(s6)
@@ -2768,7 +2758,6 @@ define void @test_nest_explicit_s11() "interrupt"="qci-nest" {
 ; QCI-FP-NEXT:    .cfi_def_cfa_offset 112
 ; QCI-FP-NEXT:    sw s11, 12(sp) # 4-byte Folded Spill
 ; QCI-FP-NEXT:    .cfi_offset s11, -100
-; QCI-FP-NEXT:    addi s0, sp, 112
 ; QCI-FP-NEXT:    .cfi_def_cfa s0, 0
 ; QCI-FP-NEXT:    #APP
 ; QCI-FP-NEXT:    li s4, 0
@@ -2877,7 +2866,6 @@ define void @test_nonest_explicit_s11() "interrupt"="qci-nonest" {
 ; QCI-FP-NEXT:    .cfi_def_cfa_offset 112
 ; QCI-FP-NEXT:    sw s11, 12(sp) # 4-byte Folded Spill
 ; QCI-FP-NEXT:    .cfi_offset s11, -100
-; QCI-FP-NEXT:    addi s0, sp, 112
 ; QCI-FP-NEXT:    .cfi_def_cfa s0, 0
 ; QCI-FP-NEXT:    #APP
 ; QCI-FP-NEXT:    li s11, 0
diff --git a/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp b/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp
index 00dc160c39a36..e24b2d47f6bc4 100644
--- a/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp
+++ b/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp
@@ -656,7 +656,7 @@ TEST(ParseArchString, RejectsConflictingExtensions) {
   for (StringRef Input :
        {"rv64i_xqcisls0p2", "rv64i_xqcia0p4", "rv64i_xqciac0p3",
         "rv64i_xqcicsr0p2", "rv64i_xqcilsm0p2", "rv64i_xqcicm0p2",
-        "rv64i_xqcics0p2", "rv64i_xqcicli0p2", "rv64i_xqciint0p2",
+        "rv64i_xqcics0p2", "rv64i_xqcicli0p2", "rv64i_xqciint0p4",
         "rv64i_xqcilo0p2", "rv64i_xqcilia0p2", "rv64i_xqcibm0p4"}) {
     EXPECT_THAT(
         toString(RISCVISAInfo::parseArchString(Input, true).takeError()),
@@ -1132,7 +1132,7 @@ Experimental extensions
     xqcicm               0.2
     xqcics               0.2
     xqcicsr              0.2
-    xqciint              0.2
+    xqciint              0.4
     xqcilia              0.2
     xqcilo               0.2
     xqcilsm              0.2

@lenary
Copy link
Member Author

lenary commented Mar 10, 2025

ping?

Copy link
Collaborator

@topperc topperc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link
Contributor

@hchandel hchandel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@lenary lenary merged commit ae98526 into llvm:main Mar 11, 2025
12 checks passed
@lenary lenary deleted the pr/riscv-xqciint-0.4 branch March 11, 2025 15:54
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:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants