Index: lib/CodeGen/RegUsageInfoCollector.cpp =================================================================== --- lib/CodeGen/RegUsageInfoCollector.cpp +++ lib/CodeGen/RegUsageInfoCollector.cpp @@ -81,6 +81,7 @@ bool RegUsageInfoCollector::runOnMachineFunction(MachineFunction &MF) { MachineRegisterInfo *MRI = &MF.getRegInfo(); const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); + const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering(); const TargetMachine &TM = MF.getTarget(); DEBUG(dbgs() << " -------------------- " << getPassName() @@ -103,6 +104,18 @@ DEBUG(dbgs() << "Clobbered Registers: "); + // Build the set of registers the target has decided to save and restore + // that includes also the subregs. + BitVector SavedRegs; + TFI->determineCalleeSaves(MF, SavedRegs); + const MCPhysReg *CSRegs = TRI->getCalleeSavedRegs(&MF); + for (unsigned i = 0; CSRegs[i]; ++i) { + unsigned Reg = CSRegs[i]; + if (SavedRegs.test(Reg)) + for (MCSubRegIterator SR(Reg, TRI, true); SR.isValid(); ++SR) + SavedRegs.set(*SR); + } + const BitVector &UsedPhysRegsMask = MRI->getUsedPhysRegsMask(); auto SetRegAsDefined = [&RegMask] (unsigned Reg) { RegMask[Reg / 32] &= ~(1u << Reg % 32); @@ -110,6 +123,10 @@ // Scan all the physical registers. When a register is defined in the current // function set it and all the aliasing registers as defined in the regmask. for (unsigned PReg = 1, PRegE = TRI->getNumRegs(); PReg < PRegE; ++PReg) { + // Don't count registers that are saved and restored. + if (SavedRegs.test(PReg)) + continue; + // If a register is in the UsedPhysRegsMask set then mark it as defined. // All it's aliases will also be in the set, so we can skip setting // as defined all the aliases here. @@ -125,18 +142,10 @@ } } - if (!TargetFrameLowering::isSafeForNoCSROpt(F)) { - const uint32_t *CallPreservedMask = - TRI->getCallPreservedMask(MF, F.getCallingConv()); - if (CallPreservedMask) { - // Set callee saved register as preserved. - for (unsigned i = 0; i < RegMaskSize; ++i) - RegMask[i] = RegMask[i] | CallPreservedMask[i]; - } - } else { + if (TargetFrameLowering::isSafeForNoCSROpt(F)) { ++NumCSROpt; DEBUG(dbgs() << MF.getName() - << " function optimized for not having CSR.\n"); + << " function optimized for not having CSR.\n"); } for (unsigned PReg = 1, PRegE = TRI->getNumRegs(); PReg < PRegE; ++PReg) Index: test/CodeGen/SystemZ/ipra-04.ll =================================================================== --- /dev/null +++ test/CodeGen/SystemZ/ipra-04.ll @@ -0,0 +1,37 @@ +; Test that the updated regmask on the call to @fun1 perserves %r14 and +; %15. @fun1 will save and restore these registers since it contains a call. +; +; RUN: llc -mtriple=s390x-linux-gnu -mcpu=z13 -enable-ipra -print-regmask-num-regs=-1 \ +; RUN: -debug-only=ip-regalloc 2>&1 < %s | FileCheck --check-prefix=DBG %s +; +; DBG: fun1 function optimized for not having CSR +; DBG: Call Instruction After Register Usage Info Propagation : CallBRASL @fun1{{.*}} $r14d $r15d + +%0 = type { [3 x i64] } + +; Function Attrs: norecurse nounwind +declare dso_local fastcc signext i32 @foo(i16*, i32 signext) unnamed_addr + +; Function Attrs: norecurse nounwind +define internal fastcc void @fun1(i16*, i16* nocapture) unnamed_addr #0 { + %3 = load i16, i16* undef, align 2 + %4 = shl i16 %3, 4 + %5 = tail call fastcc signext i32 @foo(i16* nonnull %0, i32 signext 5) + %6 = or i16 0, %4 + %7 = or i16 %6, 0 + store i16 %7, i16* undef, align 2 + %8 = getelementptr inbounds i16, i16* %0, i64 5 + %9 = load i16, i16* %8, align 2 + store i16 %9, i16* %1, align 2 + ret void +} + +; Function Attrs: nounwind +define fastcc void @fun0(i8* nocapture readonly, i16* nocapture, i32 signext) unnamed_addr { + %a = alloca i8, i64 undef + call fastcc void @fun1(i16* nonnull undef, i16* %1) + ret void +} + +attributes #0 = { norecurse nounwind "no-frame-pointer-elim"="false" } +