[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