We cannot call LRM::unassign() if LRM::assign() was never called before, these are symmetrical calls. There are two ways of assigning a physical register to virtual, via LRM::assign() and via VRM::assignVirt2Phys(). LRM::assign() will call the VRM to assign the register and then update LiveIntervalUnion. Inline spiller calls VRM directly and thus LiveIntervalUnion never gets updated. A call to LRM::unassign() then asserts about inconsistent liveness. We have to note that not all callers of the InlineSpiller even have LRM to pass, RegAllocPBQP does not have it, so we cannot always pass LRM into the spiller. The only way to get into that spiller LRE_DidCloneVirtReg() call is from LiveRangeEdit::eliminateDeadDefs if we split an LI. This patch refuses to reassign a LiveInterval created by a split to workaround the problem. In fact we cannot reassign a spill anyway as all registers of the needed class are occupied and we are spilling. Fixes: SWDEV-267996 Differential Revision: https://reviews.llvm.org/D95489
39 lines
1.9 KiB
YAML
39 lines
1.9 KiB
YAML
# RUN: llc -march=amdgcn -mcpu=gfx1010 -verify-machineinstrs -run-pass greedy,amdgpu-regbanks-reassign,virtregrewriter -o - %s | FileCheck -check-prefix=GCN %s
|
|
|
|
--- |
|
|
define amdgpu_kernel void @do_not_reassign_spill() #0 { ret void }
|
|
|
|
attributes #0 = { "amdgpu-num-vgpr"="8" }
|
|
...
|
|
|
|
# GCN-LABEL: do_not_reassign_spill{{$}}
|
|
# GCN: V_AND_B32_e32 killed $vgpr1, killed $vgpr5,
|
|
---
|
|
name: do_not_reassign_spill
|
|
tracksRegLiveness: true
|
|
machineFunctionInfo:
|
|
stackPtrOffsetReg: $sgpr32
|
|
stack:
|
|
- { id: 0, type: default, offset: 0, size: 4, alignment: 4 }
|
|
registers:
|
|
- { id: 0, class: vgpr_32, preferred-register: '$vgpr0' }
|
|
- { id: 1, class: vgpr_32, preferred-register: '$vgpr1' }
|
|
- { id: 2, class: vgpr_32, preferred-register: '$vgpr2' }
|
|
- { id: 3, class: vgpr_32, preferred-register: '$vgpr3' }
|
|
- { id: 4, class: vgpr_32, preferred-register: '$vgpr4' }
|
|
- { id: 5, class: vgpr_32, preferred-register: '$vgpr5' }
|
|
- { id: 6, class: vgpr_32 }
|
|
body: |
|
|
bb.0:
|
|
%0 = SI_SPILL_V32_RESTORE %stack.0, $sgpr32, 0, implicit $exec :: (load 4 from %stack.0, align 4, addrspace 5)
|
|
%1 = SI_SPILL_V32_RESTORE %stack.0, $sgpr32, 0, implicit $exec :: (load 4 from %stack.0, align 4, addrspace 5)
|
|
%2 = SI_SPILL_V32_RESTORE %stack.0, $sgpr32, 0, implicit $exec :: (load 4 from %stack.0, align 4, addrspace 5)
|
|
%3 = SI_SPILL_V32_RESTORE %stack.0, $sgpr32, 0, implicit $exec :: (load 4 from %stack.0, align 4, addrspace 5)
|
|
%4 = SI_SPILL_V32_RESTORE %stack.0, $sgpr32, 0, implicit $exec :: (load 4 from %stack.0, align 4, addrspace 5)
|
|
%5 = SI_SPILL_V32_RESTORE %stack.0, $sgpr32, 0, implicit $exec :: (load 4 from %stack.0, align 4, addrspace 5)
|
|
S_NOP 0, implicit-def dead $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7
|
|
S_NOP 0, implicit %0, implicit %1, implicit %2, implicit %3, implicit %4, implicit %5
|
|
%6 = V_AND_B32_e32 %1, %5, implicit $exec
|
|
S_ENDPGM 0, implicit %6
|
|
...
|