Mikhail R. Gadelha 8149cbfecd
[RISCV] Implement getIPRACSRegs hook (#125586)
Fixes #124932.

This patch implements the getIPRACSRegs hook for RISC-V, similar to its introduction for x86 in commit 14b567d. This hook is necessary for correct code generation when Interprocedural Register Allocation (IPRA) is enabled, ensuring that the return address register (ra / x1) is correctly saved and restored when needed.

Unlike the x86 implementation, this patch only saves ra and does not yet include the frame pointer (fp). Further investigation is required to determine whether fp should also be preserved in all cases.

The test case is representative of a miscompile observed in the GCC torture suite (20090113-3.c), though similar failures occur in SPEC’s xz benchmark.
2025-02-04 10:02:42 -03:00

128 lines
4.6 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
; RUN: llc -mtriple=riscv64 -verify-machineinstrs -enable-ipra < %s | FileCheck %s -check-prefix=RV64
; RUN: llc -mtriple=riscv32 -verify-machineinstrs -enable-ipra < %s | FileCheck %s -check-prefix=RV32
; RUN: llc -mtriple=riscv64 -verify-machineinstrs -frame-pointer=all -enable-ipra < %s \
; RUN: | FileCheck %s -check-prefix=RV64-WITHFP
; RUN: llc -mtriple=riscv32 -verify-machineinstrs -frame-pointer=all -enable-ipra < %s \
; RUN: | FileCheck %s -check-prefix=RV32-WITHFP
%struct.bitmap_iterator = type { ptr, ptr, i32, i64 }
define i32 @main() nounwind {
; RV64-LABEL: main:
; RV64: # %bb.0: # %entry
; RV64-NEXT: addi sp, sp, -16
; RV64-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
; RV64-NEXT: li a0, 0
; RV64-NEXT: call foobar
; RV64-NEXT: li a0, 0
; RV64-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
; RV64-NEXT: addi sp, sp, 16
; RV64-NEXT: ret
;
; RV32-LABEL: main:
; RV32: # %bb.0: # %entry
; RV32-NEXT: addi sp, sp, -16
; RV32-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
; RV32-NEXT: li a0, 0
; RV32-NEXT: call foobar
; RV32-NEXT: li a0, 0
; RV32-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
; RV32-NEXT: addi sp, sp, 16
; RV32-NEXT: ret
;
; RV64-WITHFP-LABEL: main:
; RV64-WITHFP: # %bb.0: # %entry
; RV64-WITHFP-NEXT: addi sp, sp, -16
; RV64-WITHFP-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
; RV64-WITHFP-NEXT: sd s0, 0(sp) # 8-byte Folded Spill
; RV64-WITHFP-NEXT: addi s0, sp, 16
; RV64-WITHFP-NEXT: li a0, 0
; RV64-WITHFP-NEXT: call foobar
; RV64-WITHFP-NEXT: li a0, 0
; RV64-WITHFP-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
; RV64-WITHFP-NEXT: ld s0, 0(sp) # 8-byte Folded Reload
; RV64-WITHFP-NEXT: addi sp, sp, 16
; RV64-WITHFP-NEXT: ret
;
; RV32-WITHFP-LABEL: main:
; RV32-WITHFP: # %bb.0: # %entry
; RV32-WITHFP-NEXT: addi sp, sp, -16
; RV32-WITHFP-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
; RV32-WITHFP-NEXT: sw s0, 8(sp) # 4-byte Folded Spill
; RV32-WITHFP-NEXT: addi s0, sp, 16
; RV32-WITHFP-NEXT: li a0, 0
; RV32-WITHFP-NEXT: call foobar
; RV32-WITHFP-NEXT: li a0, 0
; RV32-WITHFP-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
; RV32-WITHFP-NEXT: lw s0, 8(sp) # 4-byte Folded Reload
; RV32-WITHFP-NEXT: addi sp, sp, 16
; RV32-WITHFP-NEXT: ret
entry:
call void @foobar(ptr null)
ret i32 0
}
define internal void @foobar(ptr %live_throughout.0.val) norecurse nounwind {
; RV64-LABEL: foobar:
; RV64: # %bb.0: # %entry
; RV64-NEXT: addi sp, sp, -48
; RV64-NEXT: sd ra, 40(sp) # 8-byte Folded Spill
; RV64-NEXT: mv a1, a0
; RV64-NEXT: addi a0, sp, 8
; RV64-NEXT: addi a2, sp, 4
; RV64-NEXT: call bmp_iter_set_init
; RV64-NEXT: ld ra, 40(sp) # 8-byte Folded Reload
; RV64-NEXT: addi sp, sp, 48
; RV64-NEXT: ret
;
; RV32-LABEL: foobar:
; RV32: # %bb.0: # %entry
; RV32-NEXT: addi sp, sp, -48
; RV32-NEXT: sw ra, 44(sp) # 4-byte Folded Spill
; RV32-NEXT: mv a1, a0
; RV32-NEXT: addi a0, sp, 16
; RV32-NEXT: addi a2, sp, 12
; RV32-NEXT: call bmp_iter_set_init
; RV32-NEXT: lw ra, 44(sp) # 4-byte Folded Reload
; RV32-NEXT: addi sp, sp, 48
; RV32-NEXT: ret
;
; RV64-WITHFP-LABEL: foobar:
; RV64-WITHFP: # %bb.0: # %entry
; RV64-WITHFP-NEXT: addi sp, sp, -64
; RV64-WITHFP-NEXT: sd ra, 56(sp) # 8-byte Folded Spill
; RV64-WITHFP-NEXT: sd s0, 48(sp) # 8-byte Folded Spill
; RV64-WITHFP-NEXT: addi s0, sp, 64
; RV64-WITHFP-NEXT: mv a1, a0
; RV64-WITHFP-NEXT: addi a0, s0, -48
; RV64-WITHFP-NEXT: addi a2, s0, -52
; RV64-WITHFP-NEXT: call bmp_iter_set_init
; RV64-WITHFP-NEXT: ld ra, 56(sp) # 8-byte Folded Reload
; RV64-WITHFP-NEXT: ld s0, 48(sp) # 8-byte Folded Reload
; RV64-WITHFP-NEXT: addi sp, sp, 64
; RV64-WITHFP-NEXT: ret
;
; RV32-WITHFP-LABEL: foobar:
; RV32-WITHFP: # %bb.0: # %entry
; RV32-WITHFP-NEXT: addi sp, sp, -48
; RV32-WITHFP-NEXT: sw ra, 44(sp) # 4-byte Folded Spill
; RV32-WITHFP-NEXT: sw s0, 40(sp) # 4-byte Folded Spill
; RV32-WITHFP-NEXT: addi s0, sp, 48
; RV32-WITHFP-NEXT: mv a1, a0
; RV32-WITHFP-NEXT: addi a0, s0, -32
; RV32-WITHFP-NEXT: addi a2, s0, -36
; RV32-WITHFP-NEXT: call bmp_iter_set_init
; RV32-WITHFP-NEXT: lw ra, 44(sp) # 4-byte Folded Reload
; RV32-WITHFP-NEXT: lw s0, 40(sp) # 4-byte Folded Reload
; RV32-WITHFP-NEXT: addi sp, sp, 48
; RV32-WITHFP-NEXT: ret
entry:
%rsi = alloca %struct.bitmap_iterator, align 8
%regno = alloca i32, i32 0, align 4
call void @bmp_iter_set_init(ptr %rsi, ptr %live_throughout.0.val, ptr %regno)
ret void
}
declare void @bmp_iter_set_init(ptr, ptr, ptr)