[llvm] [RISCV] Disable Zilsd CSR-pair generation when push/pop or save-restore is enabled (PR #200623)

Sudharsan Veeravalli via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 1 08:48:10 PDT 2026


https://github.com/svs-quic updated https://github.com/llvm/llvm-project/pull/200623

>From 930b400a13b75c8d13c16ea1d0603b46dfdcfe30 Mon Sep 17 00:00:00 2001
From: Sudharsan Veeravalli <svs at qti.qualcomm.com>
Date: Sun, 31 May 2026 07:51:13 +0530
Subject: [PATCH 1/3] Precommit tests

---
 llvm/test/CodeGen/RISCV/cmp-zilsd-csr.ll      | 88 +++++++++++++++++++
 .../RISCV/saverestore-zilsd-fixed-location.ll | 28 ++++++
 2 files changed, 116 insertions(+)
 create mode 100644 llvm/test/CodeGen/RISCV/cmp-zilsd-csr.ll
 create mode 100644 llvm/test/CodeGen/RISCV/saverestore-zilsd-fixed-location.ll

diff --git a/llvm/test/CodeGen/RISCV/cmp-zilsd-csr.ll b/llvm/test/CodeGen/RISCV/cmp-zilsd-csr.ll
new file mode 100644
index 0000000000000..9fc07b43e7316
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/cmp-zilsd-csr.ll
@@ -0,0 +1,88 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc -mtriple=riscv32 -mattr=+zcmp -verify-machineinstrs < %s \
+; RUN:   | FileCheck %s --check-prefix=ZCMP
+; RUN: llc -mtriple=riscv32 -mattr=+zcmp,+zilsd -verify-machineinstrs < %s \
+; RUN:   | FileCheck %s --check-prefix=ZCMP-ZILSD
+; RUN: llc -mtriple=riscv32 -mattr=+xqccmp -verify-machineinstrs < %s \
+; RUN:   | FileCheck %s --check-prefix=XQCCMP
+; RUN: llc -mtriple=riscv32 -mattr=+xqccmp,+zilsd < %s \
+; RUN:   | FileCheck %s --check-prefix=XQCCMP-ZILSD
+
+
+declare i32 @foo()
+declare void @bar()
+
+define void @c_expand_asm_operands(ptr %p, i32 %a) optsize nounwind{
+; ZCMP-LABEL: c_expand_asm_operands:
+; ZCMP:       # %bb.0: # %entry
+; ZCMP-NEXT:    cm.push {ra, s0-s2}, -16
+; ZCMP-NEXT:    addi s0, sp, 16
+; ZCMP-NEXT:    cm.mvsa01 s2, s1
+; ZCMP-NEXT:    call foo
+; ZCMP-NEXT:    addi s1, s1, 15
+; ZCMP-NEXT:    andi s1, s1, -16
+; ZCMP-NEXT:    sub a0, sp, s1
+; ZCMP-NEXT:    mv sp, a0
+; ZCMP-NEXT:    sw a0, 0(s2)
+; ZCMP-NEXT:    addi sp, s0, -16
+; ZCMP-NEXT:    cm.pop {ra, s0-s2}, 16
+; ZCMP-NEXT:    tail bar
+;
+; ZCMP-ZILSD-LABEL: c_expand_asm_operands:
+; ZCMP-ZILSD:       # %bb.0: # %entry
+; ZCMP-ZILSD-NEXT:    cm.push {ra}, -32
+; ZCMP-ZILSD-NEXT:    sd s0, 8(sp) # 8-byte Folded Spill
+; ZCMP-ZILSD-NEXT:    sd s2, 0(sp) # 8-byte Folded Spill
+; ZCMP-ZILSD-NEXT:    addi s0, sp, 32
+; ZCMP-ZILSD-NEXT:    cm.mvsa01 s2, s1
+; ZCMP-ZILSD-NEXT:    call foo
+; ZCMP-ZILSD-NEXT:    addi s1, s1, 15
+; ZCMP-ZILSD-NEXT:    andi s1, s1, -16
+; ZCMP-ZILSD-NEXT:    sub a0, sp, s1
+; ZCMP-ZILSD-NEXT:    mv sp, a0
+; ZCMP-ZILSD-NEXT:    sw a0, 0(s2)
+; ZCMP-ZILSD-NEXT:    addi sp, s0, -32
+; ZCMP-ZILSD-NEXT:    ld s0, 8(sp) # 8-byte Folded Reload
+; ZCMP-ZILSD-NEXT:    ld s2, 0(sp) # 8-byte Folded Reload
+; ZCMP-ZILSD-NEXT:    cm.pop {ra}, 32
+; ZCMP-ZILSD-NEXT:    tail bar
+;
+; XQCCMP-LABEL: c_expand_asm_operands:
+; XQCCMP:       # %bb.0: # %entry
+; XQCCMP-NEXT:    qc.cm.pushfp {ra, s0-s2}, -16
+; XQCCMP-NEXT:    qc.cm.mvsa01 s2, s1
+; XQCCMP-NEXT:    call foo
+; XQCCMP-NEXT:    addi s1, s1, 15
+; XQCCMP-NEXT:    andi s1, s1, -16
+; XQCCMP-NEXT:    sub a0, sp, s1
+; XQCCMP-NEXT:    mv sp, a0
+; XQCCMP-NEXT:    sw a0, 0(s2)
+; XQCCMP-NEXT:    addi sp, s0, -16
+; XQCCMP-NEXT:    qc.cm.pop {ra, s0-s2}, 16
+; XQCCMP-NEXT:    tail bar
+;
+; XQCCMP-ZILSD-LABEL: c_expand_asm_operands:
+; XQCCMP-ZILSD:       # %bb.0: # %entry
+; XQCCMP-ZILSD-NEXT:    qc.cm.pushfp {ra}, -32
+; XQCCMP-ZILSD-NEXT:    sd s0, 8(sp) # 8-byte Folded Spill
+; XQCCMP-ZILSD-NEXT:    sd s2, 0(sp) # 8-byte Folded Spill
+; XQCCMP-ZILSD-NEXT:    qc.cm.mvsa01 s2, s1
+; XQCCMP-ZILSD-NEXT:    call foo
+; XQCCMP-ZILSD-NEXT:    addi s1, s1, 15
+; XQCCMP-ZILSD-NEXT:    andi s1, s1, -16
+; XQCCMP-ZILSD-NEXT:    sub a0, sp, s1
+; XQCCMP-ZILSD-NEXT:    mv sp, a0
+; XQCCMP-ZILSD-NEXT:    sw a0, 0(s2)
+; XQCCMP-ZILSD-NEXT:    addi sp, s0, -32
+; XQCCMP-ZILSD-NEXT:    ld s0, 8(sp) # 8-byte Folded Reload
+; XQCCMP-ZILSD-NEXT:    ld s2, 0(sp) # 8-byte Folded Reload
+; XQCCMP-ZILSD-NEXT:    qc.cm.pop {ra}, 32
+; XQCCMP-ZILSD-NEXT:    tail bar
+entry:
+  %call1 = call i32 @foo()
+  %0 = alloca i8, i32 %a, align 8
+  store ptr %0, ptr %p, align 8
+  tail call void @bar()
+  ret void
+}
+
diff --git a/llvm/test/CodeGen/RISCV/saverestore-zilsd-fixed-location.ll b/llvm/test/CodeGen/RISCV/saverestore-zilsd-fixed-location.ll
new file mode 100644
index 0000000000000..a62de62c746d7
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/saverestore-zilsd-fixed-location.ll
@@ -0,0 +1,28 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc -mtriple=riscv32 -mattr=+save-restore -verify-machineinstrs < %s \
+; RUN:   | FileCheck %s --check-prefix=SR
+; RUN: llc -mtriple=riscv32 -mattr=+save-restore,+zilsd -verify-machineinstrs < %s \
+; RUN:   | FileCheck %s --check-prefix=SR-ZILSD
+
+define void @fixed_location_sr() nounwind {
+; SR-LABEL: fixed_location_sr:
+; SR:       # %bb.0: # %entry
+; SR-NEXT:    call t0, __riscv_save_5
+; SR-NEXT:    #APP
+; SR-NEXT:    #NO_APP
+; SR-NEXT:    tail __riscv_restore_5
+;
+; SR-ZILSD-LABEL: fixed_location_sr:
+; SR-ZILSD:       # %bb.0: # %entry
+; SR-ZILSD-NEXT:    call t0, __riscv_save_5
+; SR-ZILSD-NEXT:    addi sp, sp, -16
+; SR-ZILSD-NEXT:    sd s2, 8(sp) # 8-byte Folded Spill
+; SR-ZILSD-NEXT:    #APP
+; SR-ZILSD-NEXT:    #NO_APP
+; SR-ZILSD-NEXT:    ld s2, 8(sp) # 8-byte Folded Reload
+; SR-ZILSD-NEXT:    addi sp, sp, 16
+; SR-ZILSD-NEXT:    tail __riscv_restore_5
+entry:
+  call void asm sideeffect "", "~{x9},~{x18},~{x19},~{x20}"()
+  ret void
+}

>From 68644085fa0277bdec4656be1cbac27e0917a9cb Mon Sep 17 00:00:00 2001
From: Sudharsan Veeravalli <svs at qti.qualcomm.com>
Date: Sun, 31 May 2026 08:07:34 +0530
Subject: [PATCH 2/3] Disable Zilsd CSR-pair generation when push/pop or
 save-restore is enabled

---
 llvm/lib/Target/RISCV/RISCVFrameLowering.cpp  |  8 +++++--
 llvm/test/CodeGen/RISCV/cmp-zilsd-csr.ll      | 24 +++++++------------
 .../RISCV/saverestore-zilsd-fixed-location.ll |  4 ----
 3 files changed, 14 insertions(+), 22 deletions(-)

diff --git a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
index 9306fe69ef427..5c623821f80d1 100644
--- a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
@@ -1690,9 +1690,13 @@ void RISCVFrameLowering::determineCalleeSaves(MachineFunction &MF,
   // For Zilsd on RV32, append GPRPair registers to the CSR list. This prevents
   // the need to create register sets for each abi which is a lot more complex.
   // Don't use Zilsd for callee-saved coalescing if the required alignment
-  // exceeds the stack alignment.
+  // exceeds the stack alignment or when Zcmp/Xqccmp or save/restore libcalls
+  // are enabled.
+  bool HasPushPopCompression = STI.hasStdExtZcmp() || STI.hasVendorXqccmp();
   bool UseZilsd = !STI.is64Bit() && STI.hasStdExtZilsd() &&
-                  STI.getZilsdAlign() <= getStackAlign();
+                  STI.getZilsdAlign() <= getStackAlign() &&
+                  !RVFI->isPushable(MF) && !RVFI->useSaveRestoreLibCalls(MF) &&
+                  !HasPushPopCompression;
   if (UseZilsd) {
     SmallVector<MCPhysReg, 32> NewCSRs;
     SmallSet<MCPhysReg, 16> CSRSet;
diff --git a/llvm/test/CodeGen/RISCV/cmp-zilsd-csr.ll b/llvm/test/CodeGen/RISCV/cmp-zilsd-csr.ll
index 9fc07b43e7316..69b801fddbf3b 100644
--- a/llvm/test/CodeGen/RISCV/cmp-zilsd-csr.ll
+++ b/llvm/test/CodeGen/RISCV/cmp-zilsd-csr.ll
@@ -5,7 +5,7 @@
 ; RUN:   | FileCheck %s --check-prefix=ZCMP-ZILSD
 ; RUN: llc -mtriple=riscv32 -mattr=+xqccmp -verify-machineinstrs < %s \
 ; RUN:   | FileCheck %s --check-prefix=XQCCMP
-; RUN: llc -mtriple=riscv32 -mattr=+xqccmp,+zilsd < %s \
+; RUN: llc -mtriple=riscv32 -mattr=+xqccmp,+zilsd -verify-machineinstrs < %s \
 ; RUN:   | FileCheck %s --check-prefix=XQCCMP-ZILSD
 
 
@@ -30,10 +30,8 @@ define void @c_expand_asm_operands(ptr %p, i32 %a) optsize nounwind{
 ;
 ; ZCMP-ZILSD-LABEL: c_expand_asm_operands:
 ; ZCMP-ZILSD:       # %bb.0: # %entry
-; ZCMP-ZILSD-NEXT:    cm.push {ra}, -32
-; ZCMP-ZILSD-NEXT:    sd s0, 8(sp) # 8-byte Folded Spill
-; ZCMP-ZILSD-NEXT:    sd s2, 0(sp) # 8-byte Folded Spill
-; ZCMP-ZILSD-NEXT:    addi s0, sp, 32
+; ZCMP-ZILSD-NEXT:    cm.push {ra, s0-s2}, -16
+; ZCMP-ZILSD-NEXT:    addi s0, sp, 16
 ; ZCMP-ZILSD-NEXT:    cm.mvsa01 s2, s1
 ; ZCMP-ZILSD-NEXT:    call foo
 ; ZCMP-ZILSD-NEXT:    addi s1, s1, 15
@@ -41,10 +39,8 @@ define void @c_expand_asm_operands(ptr %p, i32 %a) optsize nounwind{
 ; ZCMP-ZILSD-NEXT:    sub a0, sp, s1
 ; ZCMP-ZILSD-NEXT:    mv sp, a0
 ; ZCMP-ZILSD-NEXT:    sw a0, 0(s2)
-; ZCMP-ZILSD-NEXT:    addi sp, s0, -32
-; ZCMP-ZILSD-NEXT:    ld s0, 8(sp) # 8-byte Folded Reload
-; ZCMP-ZILSD-NEXT:    ld s2, 0(sp) # 8-byte Folded Reload
-; ZCMP-ZILSD-NEXT:    cm.pop {ra}, 32
+; ZCMP-ZILSD-NEXT:    addi sp, s0, -16
+; ZCMP-ZILSD-NEXT:    cm.pop {ra, s0-s2}, 16
 ; ZCMP-ZILSD-NEXT:    tail bar
 ;
 ; XQCCMP-LABEL: c_expand_asm_operands:
@@ -63,9 +59,7 @@ define void @c_expand_asm_operands(ptr %p, i32 %a) optsize nounwind{
 ;
 ; XQCCMP-ZILSD-LABEL: c_expand_asm_operands:
 ; XQCCMP-ZILSD:       # %bb.0: # %entry
-; XQCCMP-ZILSD-NEXT:    qc.cm.pushfp {ra}, -32
-; XQCCMP-ZILSD-NEXT:    sd s0, 8(sp) # 8-byte Folded Spill
-; XQCCMP-ZILSD-NEXT:    sd s2, 0(sp) # 8-byte Folded Spill
+; XQCCMP-ZILSD-NEXT:    qc.cm.pushfp {ra, s0-s2}, -16
 ; XQCCMP-ZILSD-NEXT:    qc.cm.mvsa01 s2, s1
 ; XQCCMP-ZILSD-NEXT:    call foo
 ; XQCCMP-ZILSD-NEXT:    addi s1, s1, 15
@@ -73,10 +67,8 @@ define void @c_expand_asm_operands(ptr %p, i32 %a) optsize nounwind{
 ; XQCCMP-ZILSD-NEXT:    sub a0, sp, s1
 ; XQCCMP-ZILSD-NEXT:    mv sp, a0
 ; XQCCMP-ZILSD-NEXT:    sw a0, 0(s2)
-; XQCCMP-ZILSD-NEXT:    addi sp, s0, -32
-; XQCCMP-ZILSD-NEXT:    ld s0, 8(sp) # 8-byte Folded Reload
-; XQCCMP-ZILSD-NEXT:    ld s2, 0(sp) # 8-byte Folded Reload
-; XQCCMP-ZILSD-NEXT:    qc.cm.pop {ra}, 32
+; XQCCMP-ZILSD-NEXT:    addi sp, s0, -16
+; XQCCMP-ZILSD-NEXT:    qc.cm.pop {ra, s0-s2}, 16
 ; XQCCMP-ZILSD-NEXT:    tail bar
 entry:
   %call1 = call i32 @foo()
diff --git a/llvm/test/CodeGen/RISCV/saverestore-zilsd-fixed-location.ll b/llvm/test/CodeGen/RISCV/saverestore-zilsd-fixed-location.ll
index a62de62c746d7..ec46ccf478d58 100644
--- a/llvm/test/CodeGen/RISCV/saverestore-zilsd-fixed-location.ll
+++ b/llvm/test/CodeGen/RISCV/saverestore-zilsd-fixed-location.ll
@@ -15,12 +15,8 @@ define void @fixed_location_sr() nounwind {
 ; SR-ZILSD-LABEL: fixed_location_sr:
 ; SR-ZILSD:       # %bb.0: # %entry
 ; SR-ZILSD-NEXT:    call t0, __riscv_save_5
-; SR-ZILSD-NEXT:    addi sp, sp, -16
-; SR-ZILSD-NEXT:    sd s2, 8(sp) # 8-byte Folded Spill
 ; SR-ZILSD-NEXT:    #APP
 ; SR-ZILSD-NEXT:    #NO_APP
-; SR-ZILSD-NEXT:    ld s2, 8(sp) # 8-byte Folded Reload
-; SR-ZILSD-NEXT:    addi sp, sp, 16
 ; SR-ZILSD-NEXT:    tail __riscv_restore_5
 entry:
   call void asm sideeffect "", "~{x9},~{x18},~{x19},~{x20}"()

>From 25e1123adc720e2b7fe9e8ffc00d0eace78e608e Mon Sep 17 00:00:00 2001
From: Sudharsan Veeravalli <svs at qti.qualcomm.com>
Date: Mon, 1 Jun 2026 21:17:24 +0530
Subject: [PATCH 3/3] Remove HasPushPopCompression

---
 llvm/lib/Target/RISCV/RISCVFrameLowering.cpp | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
index 5c623821f80d1..a971b1ea1ccef 100644
--- a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
@@ -1692,11 +1692,9 @@ void RISCVFrameLowering::determineCalleeSaves(MachineFunction &MF,
   // Don't use Zilsd for callee-saved coalescing if the required alignment
   // exceeds the stack alignment or when Zcmp/Xqccmp or save/restore libcalls
   // are enabled.
-  bool HasPushPopCompression = STI.hasStdExtZcmp() || STI.hasVendorXqccmp();
   bool UseZilsd = !STI.is64Bit() && STI.hasStdExtZilsd() &&
                   STI.getZilsdAlign() <= getStackAlign() &&
-                  !RVFI->isPushable(MF) && !RVFI->useSaveRestoreLibCalls(MF) &&
-                  !HasPushPopCompression;
+                  !RVFI->isPushable(MF) && !RVFI->useSaveRestoreLibCalls(MF);
   if (UseZilsd) {
     SmallVector<MCPhysReg, 32> NewCSRs;
     SmallSet<MCPhysReg, 16> CSRSet;



More information about the llvm-commits mailing list