Index: llvm/include/llvm/CodeGen/TargetRegisterInfo.h =================================================================== --- llvm/include/llvm/CodeGen/TargetRegisterInfo.h +++ llvm/include/llvm/CodeGen/TargetRegisterInfo.h @@ -578,6 +578,14 @@ return false; } + // Return true if the register is needed for returning from the + // function and so must be preserved in the callee even if preserved + // by the caller + virtual bool isNeededForReturn(MCRegister PhysReg, + const MachineFunction &MF) const { + return false; + } + /// Prior to adding the live-out mask to a stackmap or patchpoint /// instruction, provide the target the opportunity to adjust it (mainly to /// remove pseudo-registers that should be ignored). Index: llvm/lib/CodeGen/TargetFrameLoweringImpl.cpp =================================================================== --- llvm/lib/CodeGen/TargetFrameLoweringImpl.cpp +++ llvm/lib/CodeGen/TargetFrameLoweringImpl.cpp @@ -92,10 +92,9 @@ // When interprocedural register allocation is enabled caller saved registers // are preferred over callee saved registers. - if (MF.getTarget().Options.EnableIPRA && - isSafeForNoCSROpt(MF.getFunction()) && - isProfitableForNoCSROpt(MF.getFunction())) - return; + bool NoCSR = (MF.getTarget().Options.EnableIPRA && + isSafeForNoCSROpt(MF.getFunction()) && + isProfitableForNoCSROpt(MF.getFunction())); // Get the callee saved register list... const MCPhysReg *CSRegs = MF.getRegInfo().getCalleeSavedRegs(); @@ -124,10 +123,12 @@ // Functions which call __builtin_unwind_init get all their registers saved. bool CallsUnwindInit = MF.callsUnwindInit(); const MachineRegisterInfo &MRI = MF.getRegInfo(); + const TargetRegisterInfo *RI = MF.getSubtarget().getRegisterInfo(); for (unsigned i = 0; CSRegs[i]; ++i) { unsigned Reg = CSRegs[i]; if (CallsUnwindInit || MRI.isPhysRegModified(Reg)) - SavedRegs.set(Reg); + if (!NoCSR || !MRI.isAllocatable(Reg) || RI->isNeededForReturn(Reg, MF)) + SavedRegs.set(Reg); } } Index: llvm/lib/Target/Mips/MipsRegisterInfo.h =================================================================== --- llvm/lib/Target/Mips/MipsRegisterInfo.h +++ llvm/lib/Target/Mips/MipsRegisterInfo.h @@ -72,6 +72,9 @@ /// Return GPR register class. virtual const TargetRegisterClass *intRegClass(unsigned Size) const = 0; + virtual bool isNeededForReturn(MCRegister PhysReg, + const MachineFunction &MF) const override; + private: virtual void eliminateFI(MachineBasicBlock::iterator II, unsigned OpNo, int FrameIndex, uint64_t StackSize, Index: llvm/lib/Target/Mips/MipsRegisterInfo.cpp =================================================================== --- llvm/lib/Target/Mips/MipsRegisterInfo.cpp +++ llvm/lib/Target/Mips/MipsRegisterInfo.cpp @@ -244,6 +244,11 @@ return true; } +bool MipsRegisterInfo::isNeededForReturn(MCRegister PhysReg, + const MachineFunction &MF) const { + return PhysReg == Mips::RA || PhysReg == Mips::RA_64; +} + // FrameIndex represent objects inside a abstract stack. // We must replace FrameIndex with an stack/frame pointer // direct reference.