Index: lib/Target/SystemZ/SystemZRegisterInfo.h =================================================================== --- lib/Target/SystemZ/SystemZRegisterInfo.h +++ lib/Target/SystemZ/SystemZRegisterInfo.h @@ -59,6 +59,14 @@ void eliminateFrameIndex(MachineBasicBlock::iterator MI, int SPAdj, unsigned FIOperandNum, RegScavenger *RS) const override; + bool shouldCoalesce(MachineInstr *MI, + const TargetRegisterClass *SrcRC, + unsigned SubReg, + const TargetRegisterClass *DstRC, + unsigned DstSubReg, + const TargetRegisterClass *NewRC) const override; + + /// \brief SrcRC and DstRC will be morphed into NewRC if this returns true. unsigned getFrameRegister(const MachineFunction &MF) const override; }; Index: lib/Target/SystemZ/SystemZRegisterInfo.cpp =================================================================== --- lib/Target/SystemZ/SystemZRegisterInfo.cpp +++ lib/Target/SystemZ/SystemZRegisterInfo.cpp @@ -152,6 +152,22 @@ MI->getOperand(FIOperandNum + 1).ChangeToImmediate(Offset); } +bool SystemZRegisterInfo::shouldCoalesce(MachineInstr *MI, + const TargetRegisterClass *SrcRC, + unsigned SubReg, + const TargetRegisterClass *DstRC, + unsigned DstSubReg, + const TargetRegisterClass *NewRC) const { + // Avoid coalescing COPYs of subregs of a GR128 register to prevent + // regalloc running out of registers. That may happen as long as subreg + // liveness is turned off per default due to being compile time expensive. + if (SrcRC->hasSubClassEq(&SystemZ::GR128BitRegClass) && + getRegSizeInBits(*DstRC) <= 64) + return false; + + return true; +} + unsigned SystemZRegisterInfo::getFrameRegister(const MachineFunction &MF) const { const SystemZFrameLowering *TFI = getFrameLowering(MF); Index: test/CodeGen/SystemZ/regalloc-GR128.ll =================================================================== --- /dev/null +++ test/CodeGen/SystemZ/regalloc-GR128.ll @@ -0,0 +1,11 @@ +; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z13 -O3 |& FileCheck %s +; +; Test that regalloc does not run out of registers + +define i64 @test(i64 %dividend, i64 %divisor) { +; CHECK-NOT: LLVM ERROR: ran out of registers during register allocation +init: + %rem = urem i64 %dividend, %divisor + call void asm sideeffect "", "{r1},{r3},{r5},{r7},{r9},{r11},{r12},{r13}"(i64 0, i64 0, i64 0, i64 0, i64 0, i64 0, i64 0, i64 %rem) + ret i64 %rem +}