Skip to content

Commit 8149cbf

Browse files
[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.
1 parent daefb1b commit 8149cbf

File tree

4 files changed

+19
-7
lines changed

4 files changed

+19
-7
lines changed

llvm/lib/Target/RISCV/RISCVCallingConv.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ def CSR_ILP32D_LP64D_V
4242
// Needed for implementation of RISCVRegisterInfo::getNoPreservedMask()
4343
def CSR_NoRegs : CalleeSavedRegs<(add)>;
4444

45+
def CSR_IPRA : CalleeSavedRegs<(add X1)>;
46+
4547
// Interrupt handler needs to save/restore all registers that are used,
4648
// both Caller and Callee saved registers.
4749
def CSR_Interrupt : CalleeSavedRegs<(add X1, (sequence "X%u", 5, 31))>;

llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,11 @@ RISCVRegisterInfo::RISCVRegisterInfo(unsigned HwMode)
5555
: RISCVGenRegisterInfo(RISCV::X1, /*DwarfFlavour*/0, /*EHFlavor*/0,
5656
/*PC*/0, HwMode) {}
5757

58+
const MCPhysReg *
59+
RISCVRegisterInfo::getIPRACSRegs(const MachineFunction *MF) const {
60+
return CSR_IPRA_SaveList;
61+
}
62+
5863
const MCPhysReg *
5964
RISCVRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
6065
auto &Subtarget = MF->getSubtarget<RISCVSubtarget>();

llvm/lib/Target/RISCV/RISCVRegisterInfo.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ struct RISCVRegisterInfo : public RISCVGenRegisterInfo {
6262

6363
const MCPhysReg *getCalleeSavedRegs(const MachineFunction *MF) const override;
6464

65+
const MCPhysReg *getIPRACSRegs(const MachineFunction *MF) const override;
66+
6567
BitVector getReservedRegs(const MachineFunction &MF) const override;
6668
bool isAsmClobberable(const MachineFunction &MF,
6769
MCRegister PhysReg) const override;

llvm/test/CodeGen/RISCV/ipra.ll

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -63,26 +63,29 @@ entry:
6363
ret i32 0
6464
}
6565

66-
; FIXME: this function calls another function but doesn't save/restore ra
6766
define internal void @foobar(ptr %live_throughout.0.val) norecurse nounwind {
6867
; RV64-LABEL: foobar:
6968
; RV64: # %bb.0: # %entry
7069
; RV64-NEXT: addi sp, sp, -48
70+
; RV64-NEXT: sd ra, 40(sp) # 8-byte Folded Spill
7171
; RV64-NEXT: mv a1, a0
72-
; RV64-NEXT: addi a0, sp, 16
73-
; RV64-NEXT: addi a2, sp, 12
72+
; RV64-NEXT: addi a0, sp, 8
73+
; RV64-NEXT: addi a2, sp, 4
7474
; RV64-NEXT: call bmp_iter_set_init
75+
; RV64-NEXT: ld ra, 40(sp) # 8-byte Folded Reload
7576
; RV64-NEXT: addi sp, sp, 48
7677
; RV64-NEXT: ret
7778
;
7879
; RV32-LABEL: foobar:
7980
; RV32: # %bb.0: # %entry
80-
; RV32-NEXT: addi sp, sp, -32
81+
; RV32-NEXT: addi sp, sp, -48
82+
; RV32-NEXT: sw ra, 44(sp) # 4-byte Folded Spill
8183
; RV32-NEXT: mv a1, a0
82-
; RV32-NEXT: addi a0, sp, 8
83-
; RV32-NEXT: addi a2, sp, 4
84+
; RV32-NEXT: addi a0, sp, 16
85+
; RV32-NEXT: addi a2, sp, 12
8486
; RV32-NEXT: call bmp_iter_set_init
85-
; RV32-NEXT: addi sp, sp, 32
87+
; RV32-NEXT: lw ra, 44(sp) # 4-byte Folded Reload
88+
; RV32-NEXT: addi sp, sp, 48
8689
; RV32-NEXT: ret
8790
;
8891
; RV64-WITHFP-LABEL: foobar:

0 commit comments

Comments
 (0)