Index: llvm/lib/Target/AMDGPU/SIInstrInfo.cpp =================================================================== --- llvm/lib/Target/AMDGPU/SIInstrInfo.cpp +++ llvm/lib/Target/AMDGPU/SIInstrInfo.cpp @@ -1343,8 +1343,23 @@ auto MIB = BuildMI(MBB, MI, DL, get(Opcode)); if (RI.hasAGPRs(RC)) { - MachineRegisterInfo &MRI = MF->getRegInfo(); - Register Tmp = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass); + Register Tmp; + + // RegAllocFast only does a single pass through the function, and cannot + // deal with newly added virtual registers. + if (MF->getTarget().getOptLevel() == CodeGenOpt::None) { + std::unique_ptr RS(new RegScavenger()); + RS->enterBasicBlockEnd(MBB); + Tmp = RS->scavengeRegisterBackwards(AMDGPU::VGPR_32RegClass, MI, + false, 0); + if (!Tmp) + report_fatal_error("Cannot scavenge VGPR to spill AGPR"); + RS->setRegUsed(Tmp); + } else { + MachineRegisterInfo &MRI = MF->getRegInfo(); + Tmp = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass); + } + MIB.addReg(Tmp, RegState::Define); } MIB.addReg(SrcReg, getKillRegState(isKill)) // data @@ -1468,8 +1483,23 @@ : getVGPRSpillRestoreOpcode(SpillSize); auto MIB = BuildMI(MBB, MI, DL, get(Opcode), DestReg); if (RI.hasAGPRs(RC)) { - MachineRegisterInfo &MRI = MF->getRegInfo(); - Register Tmp = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass); + Register Tmp; + + // RegAllocFast only does a single pass through the function, and cannot + // deal with newly added virtual registers. + if (MF->getTarget().getOptLevel() == CodeGenOpt::None) { + std::unique_ptr RS(new RegScavenger()); + RS->enterBasicBlockEnd(MBB); + Tmp = RS->scavengeRegisterBackwards(AMDGPU::VGPR_32RegClass, MI, + false, 0); + if (!Tmp) + report_fatal_error("Cannot scavenge VGPR to spill AGPR"); + RS->setRegUsed(Tmp); + } else { + MachineRegisterInfo &MRI = MF->getRegInfo(); + Tmp = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass); + } + MIB.addReg(Tmp, RegState::Define); } MIB.addFrameIndex(FrameIndex) // vaddr Index: llvm/test/CodeGen/AMDGPU/spill-agpr.mir =================================================================== --- /dev/null +++ llvm/test/CodeGen/AMDGPU/spill-agpr.mir @@ -0,0 +1,102 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -march=amdgcn -mcpu=gfx908 -O0 -run-pass=regallocfast -o - %s | FileCheck -check-prefix=SPILLED %s +# RUN: llc -march=amdgcn -mcpu=gfx908 -O0 -run-pass=regallocfast,si-lower-sgpr-spills -o - %s | FileCheck -check-prefix=EXPANDED %s + +--- +name: spill_restore_agpr32 +tracksRegLiveness: true +machineFunctionInfo: + scratchRSrcReg: $sgpr0_sgpr1_sgpr2_sgpr3 + stackPtrOffsetReg: $sgpr32 +body: | + ; SPILLED-LABEL: name: spill_restore_agpr32 + ; SPILLED: bb.0: + ; SPILLED: successors: %bb.1(0x80000000) + ; SPILLED: S_NOP 0, implicit-def renamable $agpr0 + ; SPILLED: S_NOP 0, implicit-def renamable $agpr1 + ; SPILLED: early-clobber $vgpr0 = SI_SPILL_A32_SAVE killed $agpr0, %stack.0, $sgpr0_sgpr1_sgpr2_sgpr3, $sgpr32, 0, implicit $exec :: (store 4 into %stack.0, addrspace 5) + ; SPILLED: early-clobber $vgpr0 = SI_SPILL_A32_SAVE killed $agpr1, %stack.1, $sgpr0_sgpr1_sgpr2_sgpr3, $sgpr32, 0, implicit $exec :: (store 4 into %stack.1, addrspace 5) + ; SPILLED: S_CBRANCH_SCC1 %bb.1, implicit undef $scc + ; SPILLED: bb.1: + ; SPILLED: successors: %bb.2(0x80000000) + ; SPILLED: S_NOP 1 + ; SPILLED: bb.2: + ; SPILLED: $agpr0, early-clobber $vgpr0 = SI_SPILL_A32_RESTORE %stack.0, $sgpr0_sgpr1_sgpr2_sgpr3, $sgpr32, 0, implicit $exec :: (load 4 from %stack.0, addrspace 5) + ; SPILLED: $agpr1, early-clobber $vgpr0 = SI_SPILL_A32_RESTORE %stack.1, $sgpr0_sgpr1_sgpr2_sgpr3, $sgpr32, 0, implicit $exec :: (load 4 from %stack.1, addrspace 5) + ; SPILLED: S_NOP 0, implicit renamable $agpr0, implicit renamable $agpr1 + ; EXPANDED-LABEL: name: spill_restore_agpr32 + ; EXPANDED: bb.0: + ; EXPANDED: successors: %bb.1(0x80000000) + ; EXPANDED: liveins: $vgpr1, $vgpr2 + ; EXPANDED: S_NOP 0, implicit-def renamable $agpr0 + ; EXPANDED: S_NOP 0, implicit-def renamable $agpr1 + ; EXPANDED: $vgpr1 = V_ACCVGPR_READ_B32 killed $agpr0, implicit $exec + ; EXPANDED: $vgpr2 = V_ACCVGPR_READ_B32 killed $agpr1, implicit $exec + ; EXPANDED: S_CBRANCH_SCC1 %bb.1, implicit undef $scc + ; EXPANDED: bb.1: + ; EXPANDED: successors: %bb.2(0x80000000) + ; EXPANDED: liveins: $vgpr1, $vgpr2 + ; EXPANDED: S_NOP 1 + ; EXPANDED: bb.2: + ; EXPANDED: liveins: $vgpr1, $vgpr2 + ; EXPANDED: $agpr0 = V_ACCVGPR_WRITE_B32 $vgpr1, implicit $exec + ; EXPANDED: $agpr1 = V_ACCVGPR_WRITE_B32 $vgpr2, implicit $exec + ; EXPANDED: S_NOP 0, implicit renamable $agpr0, implicit renamable $agpr1 + bb.0: + S_NOP 0, implicit-def %0:agpr_32 + S_NOP 0, implicit-def %1:agpr_32 + S_CBRANCH_SCC1 implicit undef $scc, %bb.1 + + bb.1: + S_NOP 1 + + bb.2: + S_NOP 0, implicit %0, implicit %1 +... + +--- +name: spill_restore_agpr64 +tracksRegLiveness: true +machineFunctionInfo: + scratchRSrcReg: $sgpr0_sgpr1_sgpr2_sgpr3 + stackPtrOffsetReg: $sgpr32 +body: | + ; SPILLED-LABEL: name: spill_restore_agpr64 + ; SPILLED: bb.0: + ; SPILLED: successors: %bb.1(0x80000000) + ; SPILLED: S_NOP 0, implicit-def renamable $agpr0_agpr1 + ; SPILLED: early-clobber $vgpr0 = SI_SPILL_A64_SAVE killed $agpr0_agpr1, %stack.0, $sgpr0_sgpr1_sgpr2_sgpr3, $sgpr32, 0, implicit $exec :: (store 8 into %stack.0, align 4, addrspace 5) + ; SPILLED: S_CBRANCH_SCC1 %bb.1, implicit undef $scc + ; SPILLED: bb.1: + ; SPILLED: successors: %bb.2(0x80000000) + ; SPILLED: S_NOP 1 + ; SPILLED: bb.2: + ; SPILLED: $agpr0_agpr1, early-clobber $vgpr0 = SI_SPILL_A64_RESTORE %stack.0, $sgpr0_sgpr1_sgpr2_sgpr3, $sgpr32, 0, implicit $exec :: (load 8 from %stack.0, align 4, addrspace 5) + ; SPILLED: S_NOP 0, implicit renamable $agpr0_agpr1 + ; EXPANDED-LABEL: name: spill_restore_agpr64 + ; EXPANDED: bb.0: + ; EXPANDED: successors: %bb.1(0x80000000) + ; EXPANDED: liveins: $vgpr1, $vgpr2 + ; EXPANDED: S_NOP 0, implicit-def renamable $agpr0_agpr1 + ; EXPANDED: $vgpr1 = V_ACCVGPR_READ_B32 killed $agpr0, implicit $exec, implicit $agpr0_agpr1 + ; EXPANDED: $vgpr2 = V_ACCVGPR_READ_B32 killed $agpr1, implicit $exec, implicit killed $agpr0_agpr1 + ; EXPANDED: S_CBRANCH_SCC1 %bb.1, implicit undef $scc + ; EXPANDED: bb.1: + ; EXPANDED: successors: %bb.2(0x80000000) + ; EXPANDED: liveins: $vgpr1, $vgpr2 + ; EXPANDED: S_NOP 1 + ; EXPANDED: bb.2: + ; EXPANDED: liveins: $vgpr1, $vgpr2 + ; EXPANDED: $agpr0 = V_ACCVGPR_WRITE_B32 $vgpr1, implicit $exec, implicit-def $agpr0_agpr1 + ; EXPANDED: $agpr1 = V_ACCVGPR_WRITE_B32 $vgpr2, implicit $exec, implicit-def $agpr0_agpr1 + ; EXPANDED: S_NOP 0, implicit renamable $agpr0_agpr1 + bb.0: + S_NOP 0, implicit-def %0:areg_64 + S_CBRANCH_SCC1 implicit undef $scc, %bb.1 + + bb.1: + S_NOP 1 + + bb.2: + S_NOP 0, implicit %0 +...