[llvm] [llvm][RISCV] Use zilsd for callee-saved register spill/restore on RV32 (PR #184794)
Sam Elliott via llvm-commits
llvm-commits at lists.llvm.org
Thu Mar 5 09:48:14 PST 2026
================
@@ -1255,6 +1263,407 @@ define void @callee() {
; RV64IZCMP-WITH-FP-NEXT: addi sp, sp, 160
; RV64IZCMP-WITH-FP-NEXT: .cfi_def_cfa_offset 0
; RV64IZCMP-WITH-FP-NEXT: ret
+;
+; RV32I-ZILSD-LABEL: callee:
+; RV32I-ZILSD: # %bb.0:
+; RV32I-ZILSD-NEXT: addi sp, sp, -80
+; RV32I-ZILSD-NEXT: .cfi_def_cfa_offset 80
+; RV32I-ZILSD-NEXT: sw ra, 76(sp) # 4-byte Folded Spill
+; RV32I-ZILSD-NEXT: sd s0, 64(sp) # 8-byte Folded Spill
+; RV32I-ZILSD-NEXT: sd s2, 56(sp) # 8-byte Folded Spill
+; RV32I-ZILSD-NEXT: sd s4, 48(sp) # 8-byte Folded Spill
+; RV32I-ZILSD-NEXT: sd s6, 40(sp) # 8-byte Folded Spill
+; RV32I-ZILSD-NEXT: sd s8, 32(sp) # 8-byte Folded Spill
+; RV32I-ZILSD-NEXT: sd s10, 24(sp) # 8-byte Folded Spill
+; RV32I-ZILSD-NEXT: .cfi_offset ra, -4
+; RV32I-ZILSD-NEXT: .cfi_offset s0, -16
+; RV32I-ZILSD-NEXT: .cfi_offset s1, -12
+; RV32I-ZILSD-NEXT: .cfi_offset s2, -24
+; RV32I-ZILSD-NEXT: .cfi_offset s3, -20
+; RV32I-ZILSD-NEXT: .cfi_offset s4, -32
+; RV32I-ZILSD-NEXT: .cfi_offset s5, -28
+; RV32I-ZILSD-NEXT: .cfi_offset s6, -40
+; RV32I-ZILSD-NEXT: .cfi_offset s7, -36
+; RV32I-ZILSD-NEXT: .cfi_offset s8, -48
+; RV32I-ZILSD-NEXT: .cfi_offset s9, -44
+; RV32I-ZILSD-NEXT: .cfi_offset s10, -56
+; RV32I-ZILSD-NEXT: .cfi_offset s11, -52
+; RV32I-ZILSD-NEXT: lui a0, %hi(var)
+; RV32I-ZILSD-NEXT: addi a0, a0, %lo(var)
+; RV32I-ZILSD-NEXT: lw a1, 0(a0)
+; RV32I-ZILSD-NEXT: lw a2, 4(a0)
+; RV32I-ZILSD-NEXT: sw a2, 16(sp) # 4-byte Folded Spill
+; RV32I-ZILSD-NEXT: sw a1, 20(sp) # 4-byte Folded Spill
+; RV32I-ZILSD-NEXT: lw a1, 8(a0)
+; RV32I-ZILSD-NEXT: lw a2, 12(a0)
+; RV32I-ZILSD-NEXT: sw a2, 8(sp) # 4-byte Folded Spill
+; RV32I-ZILSD-NEXT: sw a1, 12(sp) # 4-byte Folded Spill
+; RV32I-ZILSD-NEXT: lw a1, 16(a0)
+; RV32I-ZILSD-NEXT: lw a6, 20(a0)
+; RV32I-ZILSD-NEXT: sw a1, 4(sp) # 4-byte Folded Spill
+; RV32I-ZILSD-NEXT: ld t1, 24(a0)
+; RV32I-ZILSD-NEXT: ld t3, 32(a0)
+; RV32I-ZILSD-NEXT: ld t5, 40(a0)
+; RV32I-ZILSD-NEXT: ld s0, 48(a0)
+; RV32I-ZILSD-NEXT: ld s2, 56(a0)
+; RV32I-ZILSD-NEXT: ld s4, 64(a0)
+; RV32I-ZILSD-NEXT: ld s6, 72(a0)
+; RV32I-ZILSD-NEXT: ld s8, 80(a0)
+; RV32I-ZILSD-NEXT: ld s10, 88(a0)
+; RV32I-ZILSD-NEXT: lw a1, 120(a0)
+; RV32I-ZILSD-NEXT: lw t0, 124(a0)
+; RV32I-ZILSD-NEXT: lw ra, 96(a0)
+; RV32I-ZILSD-NEXT: lw a7, 100(a0)
+; RV32I-ZILSD-NEXT: ld a2, 112(a0)
+; RV32I-ZILSD-NEXT: ld a4, 104(a0)
+; RV32I-ZILSD-NEXT: sw t0, 124(a0)
+; RV32I-ZILSD-NEXT: sw a1, 120(a0)
+; RV32I-ZILSD-NEXT: sw a3, 116(a0)
+; RV32I-ZILSD-NEXT: sw a2, 112(a0)
+; RV32I-ZILSD-NEXT: sw a5, 108(a0)
+; RV32I-ZILSD-NEXT: sw a4, 104(a0)
+; RV32I-ZILSD-NEXT: sw a7, 100(a0)
+; RV32I-ZILSD-NEXT: sw ra, 96(a0)
+; RV32I-ZILSD-NEXT: sw s11, 92(a0)
+; RV32I-ZILSD-NEXT: sw s10, 88(a0)
+; RV32I-ZILSD-NEXT: sw s9, 84(a0)
+; RV32I-ZILSD-NEXT: sw s8, 80(a0)
+; RV32I-ZILSD-NEXT: sw s7, 76(a0)
+; RV32I-ZILSD-NEXT: sw s6, 72(a0)
+; RV32I-ZILSD-NEXT: sw s5, 68(a0)
+; RV32I-ZILSD-NEXT: sw s4, 64(a0)
+; RV32I-ZILSD-NEXT: sw s3, 60(a0)
+; RV32I-ZILSD-NEXT: sw s2, 56(a0)
+; RV32I-ZILSD-NEXT: sw s1, 52(a0)
+; RV32I-ZILSD-NEXT: sw s0, 48(a0)
+; RV32I-ZILSD-NEXT: sw t6, 44(a0)
+; RV32I-ZILSD-NEXT: sw t5, 40(a0)
+; RV32I-ZILSD-NEXT: sw t4, 36(a0)
+; RV32I-ZILSD-NEXT: sw t3, 32(a0)
+; RV32I-ZILSD-NEXT: sw t2, 28(a0)
+; RV32I-ZILSD-NEXT: sw t1, 24(a0)
+; RV32I-ZILSD-NEXT: sw a6, 20(a0)
+; RV32I-ZILSD-NEXT: lw a1, 4(sp) # 4-byte Folded Reload
+; RV32I-ZILSD-NEXT: sw a1, 16(a0)
+; RV32I-ZILSD-NEXT: lw a1, 8(sp) # 4-byte Folded Reload
+; RV32I-ZILSD-NEXT: sw a1, 12(a0)
+; RV32I-ZILSD-NEXT: lw a1, 12(sp) # 4-byte Folded Reload
+; RV32I-ZILSD-NEXT: sw a1, 8(a0)
+; RV32I-ZILSD-NEXT: lw a1, 16(sp) # 4-byte Folded Reload
+; RV32I-ZILSD-NEXT: sw a1, 4(a0)
+; RV32I-ZILSD-NEXT: lw a1, 20(sp) # 4-byte Folded Reload
+; RV32I-ZILSD-NEXT: sw a1, 0(a0)
+; RV32I-ZILSD-NEXT: lw ra, 76(sp) # 4-byte Folded Reload
+; RV32I-ZILSD-NEXT: ld s0, 64(sp) # 8-byte Folded Reload
+; RV32I-ZILSD-NEXT: ld s2, 56(sp) # 8-byte Folded Reload
+; RV32I-ZILSD-NEXT: ld s4, 48(sp) # 8-byte Folded Reload
+; RV32I-ZILSD-NEXT: ld s6, 40(sp) # 8-byte Folded Reload
+; RV32I-ZILSD-NEXT: ld s8, 32(sp) # 8-byte Folded Reload
+; RV32I-ZILSD-NEXT: ld s10, 24(sp) # 8-byte Folded Reload
+; RV32I-ZILSD-NEXT: .cfi_restore ra
+; RV32I-ZILSD-NEXT: .cfi_restore s0
+; RV32I-ZILSD-NEXT: .cfi_restore s1
+; RV32I-ZILSD-NEXT: .cfi_restore s2
+; RV32I-ZILSD-NEXT: .cfi_restore s3
+; RV32I-ZILSD-NEXT: .cfi_restore s4
+; RV32I-ZILSD-NEXT: .cfi_restore s5
+; RV32I-ZILSD-NEXT: .cfi_restore s6
+; RV32I-ZILSD-NEXT: .cfi_restore s7
+; RV32I-ZILSD-NEXT: .cfi_restore s8
+; RV32I-ZILSD-NEXT: .cfi_restore s9
+; RV32I-ZILSD-NEXT: .cfi_restore s10
+; RV32I-ZILSD-NEXT: .cfi_restore s11
+; RV32I-ZILSD-NEXT: addi sp, sp, 80
+; RV32I-ZILSD-NEXT: .cfi_def_cfa_offset 0
+; RV32I-ZILSD-NEXT: ret
+;
+; RV32I-ZILSD-WITH-FP-LABEL: callee:
+; RV32I-ZILSD-WITH-FP: # %bb.0:
+; RV32I-ZILSD-WITH-FP-NEXT: addi sp, sp, -80
+; RV32I-ZILSD-WITH-FP-NEXT: .cfi_def_cfa_offset 80
+; RV32I-ZILSD-WITH-FP-NEXT: sw ra, 76(sp) # 4-byte Folded Spill
+; RV32I-ZILSD-WITH-FP-NEXT: sw s0, 72(sp) # 4-byte Folded Spill
+; RV32I-ZILSD-WITH-FP-NEXT: sw s1, 68(sp) # 4-byte Folded Spill
+; RV32I-ZILSD-WITH-FP-NEXT: sd s2, 56(sp) # 8-byte Folded Spill
+; RV32I-ZILSD-WITH-FP-NEXT: sd s4, 48(sp) # 8-byte Folded Spill
+; RV32I-ZILSD-WITH-FP-NEXT: sd s6, 40(sp) # 8-byte Folded Spill
+; RV32I-ZILSD-WITH-FP-NEXT: sd s8, 32(sp) # 8-byte Folded Spill
+; RV32I-ZILSD-WITH-FP-NEXT: sd s10, 24(sp) # 8-byte Folded Spill
+; RV32I-ZILSD-WITH-FP-NEXT: .cfi_offset ra, -4
+; RV32I-ZILSD-WITH-FP-NEXT: .cfi_offset s0, -8
+; RV32I-ZILSD-WITH-FP-NEXT: .cfi_offset s1, -12
+; RV32I-ZILSD-WITH-FP-NEXT: .cfi_offset s2, -24
+; RV32I-ZILSD-WITH-FP-NEXT: .cfi_offset s3, -20
+; RV32I-ZILSD-WITH-FP-NEXT: .cfi_offset s4, -32
+; RV32I-ZILSD-WITH-FP-NEXT: .cfi_offset s5, -28
+; RV32I-ZILSD-WITH-FP-NEXT: .cfi_offset s6, -40
+; RV32I-ZILSD-WITH-FP-NEXT: .cfi_offset s7, -36
+; RV32I-ZILSD-WITH-FP-NEXT: .cfi_offset s8, -48
+; RV32I-ZILSD-WITH-FP-NEXT: .cfi_offset s9, -44
+; RV32I-ZILSD-WITH-FP-NEXT: .cfi_offset s10, -56
+; RV32I-ZILSD-WITH-FP-NEXT: .cfi_offset s11, -52
+; RV32I-ZILSD-WITH-FP-NEXT: addi s0, sp, 80
+; RV32I-ZILSD-WITH-FP-NEXT: .cfi_def_cfa s0, 0
+; RV32I-ZILSD-WITH-FP-NEXT: lui a0, %hi(var)
+; RV32I-ZILSD-WITH-FP-NEXT: addi a0, a0, %lo(var)
+; RV32I-ZILSD-WITH-FP-NEXT: lw a1, 0(a0)
+; RV32I-ZILSD-WITH-FP-NEXT: lw a2, 4(a0)
+; RV32I-ZILSD-WITH-FP-NEXT: sw a2, -64(s0) # 4-byte Folded Spill
+; RV32I-ZILSD-WITH-FP-NEXT: sw a1, -60(s0) # 4-byte Folded Spill
+; RV32I-ZILSD-WITH-FP-NEXT: lw a1, 8(a0)
+; RV32I-ZILSD-WITH-FP-NEXT: lw a2, 12(a0)
+; RV32I-ZILSD-WITH-FP-NEXT: sw a2, -72(s0) # 4-byte Folded Spill
+; RV32I-ZILSD-WITH-FP-NEXT: sw a1, -68(s0) # 4-byte Folded Spill
+; RV32I-ZILSD-WITH-FP-NEXT: lw a1, 16(a0)
+; RV32I-ZILSD-WITH-FP-NEXT: lw a2, 20(a0)
+; RV32I-ZILSD-WITH-FP-NEXT: sw a2, -80(s0) # 4-byte Folded Spill
+; RV32I-ZILSD-WITH-FP-NEXT: sw a1, -76(s0) # 4-byte Folded Spill
+; RV32I-ZILSD-WITH-FP-NEXT: ld t1, 24(a0)
+; RV32I-ZILSD-WITH-FP-NEXT: ld t3, 32(a0)
+; RV32I-ZILSD-WITH-FP-NEXT: ld t5, 40(a0)
+; RV32I-ZILSD-WITH-FP-NEXT: ld s2, 48(a0)
+; RV32I-ZILSD-WITH-FP-NEXT: ld s4, 56(a0)
+; RV32I-ZILSD-WITH-FP-NEXT: ld s6, 64(a0)
+; RV32I-ZILSD-WITH-FP-NEXT: ld s8, 72(a0)
+; RV32I-ZILSD-WITH-FP-NEXT: ld s10, 80(a0)
+; RV32I-ZILSD-WITH-FP-NEXT: lw a1, 88(a0)
+; RV32I-ZILSD-WITH-FP-NEXT: lw t0, 92(a0)
+; RV32I-ZILSD-WITH-FP-NEXT: lw s1, 120(a0)
+; RV32I-ZILSD-WITH-FP-NEXT: lw ra, 124(a0)
+; RV32I-ZILSD-WITH-FP-NEXT: ld a6, 96(a0)
+; RV32I-ZILSD-WITH-FP-NEXT: ld a2, 112(a0)
+; RV32I-ZILSD-WITH-FP-NEXT: ld a4, 104(a0)
+; RV32I-ZILSD-WITH-FP-NEXT: sw ra, 124(a0)
+; RV32I-ZILSD-WITH-FP-NEXT: sw s1, 120(a0)
+; RV32I-ZILSD-WITH-FP-NEXT: sw a3, 116(a0)
+; RV32I-ZILSD-WITH-FP-NEXT: sw a2, 112(a0)
+; RV32I-ZILSD-WITH-FP-NEXT: sw a5, 108(a0)
+; RV32I-ZILSD-WITH-FP-NEXT: sw a4, 104(a0)
+; RV32I-ZILSD-WITH-FP-NEXT: sw a7, 100(a0)
+; RV32I-ZILSD-WITH-FP-NEXT: sw a6, 96(a0)
+; RV32I-ZILSD-WITH-FP-NEXT: sw t0, 92(a0)
+; RV32I-ZILSD-WITH-FP-NEXT: sw a1, 88(a0)
+; RV32I-ZILSD-WITH-FP-NEXT: sw s11, 84(a0)
+; RV32I-ZILSD-WITH-FP-NEXT: sw s10, 80(a0)
+; RV32I-ZILSD-WITH-FP-NEXT: sw s9, 76(a0)
+; RV32I-ZILSD-WITH-FP-NEXT: sw s8, 72(a0)
+; RV32I-ZILSD-WITH-FP-NEXT: sw s7, 68(a0)
+; RV32I-ZILSD-WITH-FP-NEXT: sw s6, 64(a0)
+; RV32I-ZILSD-WITH-FP-NEXT: sw s5, 60(a0)
+; RV32I-ZILSD-WITH-FP-NEXT: sw s4, 56(a0)
+; RV32I-ZILSD-WITH-FP-NEXT: sw s3, 52(a0)
+; RV32I-ZILSD-WITH-FP-NEXT: sw s2, 48(a0)
+; RV32I-ZILSD-WITH-FP-NEXT: sw t6, 44(a0)
+; RV32I-ZILSD-WITH-FP-NEXT: sw t5, 40(a0)
+; RV32I-ZILSD-WITH-FP-NEXT: sw t4, 36(a0)
+; RV32I-ZILSD-WITH-FP-NEXT: sw t3, 32(a0)
+; RV32I-ZILSD-WITH-FP-NEXT: sw t2, 28(a0)
+; RV32I-ZILSD-WITH-FP-NEXT: sw t1, 24(a0)
+; RV32I-ZILSD-WITH-FP-NEXT: lw a1, -80(s0) # 4-byte Folded Reload
+; RV32I-ZILSD-WITH-FP-NEXT: sw a1, 20(a0)
+; RV32I-ZILSD-WITH-FP-NEXT: lw a1, -76(s0) # 4-byte Folded Reload
+; RV32I-ZILSD-WITH-FP-NEXT: sw a1, 16(a0)
+; RV32I-ZILSD-WITH-FP-NEXT: lw a1, -72(s0) # 4-byte Folded Reload
+; RV32I-ZILSD-WITH-FP-NEXT: sw a1, 12(a0)
+; RV32I-ZILSD-WITH-FP-NEXT: lw a1, -68(s0) # 4-byte Folded Reload
+; RV32I-ZILSD-WITH-FP-NEXT: sw a1, 8(a0)
+; RV32I-ZILSD-WITH-FP-NEXT: lw a1, -64(s0) # 4-byte Folded Reload
+; RV32I-ZILSD-WITH-FP-NEXT: sw a1, 4(a0)
+; RV32I-ZILSD-WITH-FP-NEXT: lw a1, -60(s0) # 4-byte Folded Reload
+; RV32I-ZILSD-WITH-FP-NEXT: sw a1, 0(a0)
+; RV32I-ZILSD-WITH-FP-NEXT: .cfi_def_cfa sp, 80
+; RV32I-ZILSD-WITH-FP-NEXT: lw ra, 76(sp) # 4-byte Folded Reload
+; RV32I-ZILSD-WITH-FP-NEXT: lw s0, 72(sp) # 4-byte Folded Reload
+; RV32I-ZILSD-WITH-FP-NEXT: lw s1, 68(sp) # 4-byte Folded Reload
+; RV32I-ZILSD-WITH-FP-NEXT: ld s2, 56(sp) # 8-byte Folded Reload
+; RV32I-ZILSD-WITH-FP-NEXT: ld s4, 48(sp) # 8-byte Folded Reload
+; RV32I-ZILSD-WITH-FP-NEXT: ld s6, 40(sp) # 8-byte Folded Reload
+; RV32I-ZILSD-WITH-FP-NEXT: ld s8, 32(sp) # 8-byte Folded Reload
+; RV32I-ZILSD-WITH-FP-NEXT: ld s10, 24(sp) # 8-byte Folded Reload
+; RV32I-ZILSD-WITH-FP-NEXT: .cfi_restore ra
+; RV32I-ZILSD-WITH-FP-NEXT: .cfi_restore s0
+; RV32I-ZILSD-WITH-FP-NEXT: .cfi_restore s1
+; RV32I-ZILSD-WITH-FP-NEXT: .cfi_restore s2
+; RV32I-ZILSD-WITH-FP-NEXT: .cfi_restore s3
+; RV32I-ZILSD-WITH-FP-NEXT: .cfi_restore s4
+; RV32I-ZILSD-WITH-FP-NEXT: .cfi_restore s5
+; RV32I-ZILSD-WITH-FP-NEXT: .cfi_restore s6
+; RV32I-ZILSD-WITH-FP-NEXT: .cfi_restore s7
+; RV32I-ZILSD-WITH-FP-NEXT: .cfi_restore s8
+; RV32I-ZILSD-WITH-FP-NEXT: .cfi_restore s9
+; RV32I-ZILSD-WITH-FP-NEXT: .cfi_restore s10
+; RV32I-ZILSD-WITH-FP-NEXT: .cfi_restore s11
+; RV32I-ZILSD-WITH-FP-NEXT: addi sp, sp, 80
+; RV32I-ZILSD-WITH-FP-NEXT: .cfi_def_cfa_offset 0
+; RV32I-ZILSD-WITH-FP-NEXT: ret
+;
+; RV32I-ZILSD-ILP32E-LABEL: callee:
+; RV32I-ZILSD-ILP32E: # %bb.0:
+; RV32I-ZILSD-ILP32E-NEXT: addi sp, sp, -32
+; RV32I-ZILSD-ILP32E-NEXT: .cfi_def_cfa_offset 32
+; RV32I-ZILSD-ILP32E-NEXT: sw ra, 28(sp) # 4-byte Folded Spill
+; RV32I-ZILSD-ILP32E-NEXT: sw s0, 24(sp) # 4-byte Folded Spill
+; RV32I-ZILSD-ILP32E-NEXT: sw s1, 20(sp) # 4-byte Folded Spill
----------------
lenary wrote:
This looks a little weird, I'm not sure what's going on here.
Evidently, you're not using zilsd to save s0, which suggests there's a frame pointer, but then there's no `addi s0, sp, 32` to actually create a frame pointer?
I think the situation with ilp32e is that it's really really difficult to introduce late 8-byte aligned spills correctly (which is why we have issues with ilp32e + the D extension), so we probably need to bail out of using zilsd on ilp32e if we have strict zilsd alignment.
On ilp32e, you only have s0 and s1 as CSRs anyway, so the zilsd saving is not enough to really help, so maybe we should avoid trying to do the merging at all if we have zilsd alignment of 8 and ilp32e.
https://github.com/llvm/llvm-project/pull/184794
More information about the llvm-commits
mailing list