Skip to content

Commit 8c0483b

Browse files
authored
RegisterCoalescer: Fix assert on remat to copy-to-physreg with subregs (#121734)
Do not try to rematerialize a super-register def used by a subregister extract copy into a copy to a physical register if the other pieces of the full physreg are live at the rematerialization point. It would insert the super-register def at the rematerialization point, and assert since the other half of the register was already live. This is analagous to the undef subregister def handling above, which handled the virtual register case. Fixes #120970
1 parent 93e6346 commit 8c0483b

File tree

2 files changed

+111
-5
lines changed

2 files changed

+111
-5
lines changed

llvm/lib/CodeGen/RegisterCoalescer.cpp

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1325,11 +1325,6 @@ bool RegisterCoalescer::reMaterializeTrivialDef(const CoalescerPair &CP,
13251325
const MCInstrDesc &MCID = DefMI->getDesc();
13261326
if (MCID.getNumDefs() != 1)
13271327
return false;
1328-
// Only support subregister destinations when the def is read-undef.
1329-
MachineOperand &DstOperand = CopyMI->getOperand(0);
1330-
Register CopyDstReg = DstOperand.getReg();
1331-
if (DstOperand.getSubReg() && !DstOperand.isUndef())
1332-
return false;
13331328

13341329
// If both SrcIdx and DstIdx are set, correct rematerialization would widen
13351330
// the register substantially (beyond both source and dest size). This is bad
@@ -1339,6 +1334,32 @@ bool RegisterCoalescer::reMaterializeTrivialDef(const CoalescerPair &CP,
13391334
if (SrcIdx && DstIdx)
13401335
return false;
13411336

1337+
// Only support subregister destinations when the def is read-undef.
1338+
MachineOperand &DstOperand = CopyMI->getOperand(0);
1339+
Register CopyDstReg = DstOperand.getReg();
1340+
if (DstOperand.getSubReg() && !DstOperand.isUndef())
1341+
return false;
1342+
1343+
// In the physical register case, checking that the def is read-undef is not
1344+
// enough. We're widening the def and need to avoid clobbering other live
1345+
// values in the unused register pieces.
1346+
//
1347+
// TODO: Targets may support rewriting the rematerialized instruction to only
1348+
// touch relevant lanes, in which case we don't need any liveness check.
1349+
if (CopyDstReg.isPhysical() && CP.isPartial()) {
1350+
for (MCRegUnit Unit : TRI->regunits(DstReg)) {
1351+
// Ignore the register units we are writing anyway.
1352+
if (is_contained(TRI->regunits(CopyDstReg), Unit))
1353+
continue;
1354+
1355+
// Check if the other lanes we are defining are live at the
1356+
// rematerialization point.
1357+
LiveRange &LR = LIS->getRegUnit(Unit);
1358+
if (LR.liveAt(CopyIdx))
1359+
return false;
1360+
}
1361+
}
1362+
13421363
const unsigned DefSubIdx = DefMI->getOperand(0).getSubReg();
13431364
const TargetRegisterClass *DefRC = TII->getRegClass(MCID, 0, TRI, *MF);
13441365
if (!DefMI->isImplicitDef()) {
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5
2+
# RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 -run-pass=register-coalescer -o - %s | FileCheck %s
3+
4+
# This used to assert due to trying to rematerialize V_MOV_B64_PSEUDO
5+
# at copy to $vgpr1. This would assert since this would clobber the
6+
# live value in $vgpr0.
7+
8+
---
9+
name: rematerialize_physreg_sub_def_already_live_at_def_assert
10+
tracksRegLiveness: true
11+
body: |
12+
bb.0:
13+
liveins: $vgpr0
14+
15+
; CHECK-LABEL: name: rematerialize_physreg_sub_def_already_live_at_def_assert
16+
; CHECK: liveins: $vgpr0
17+
; CHECK-NEXT: {{ $}}
18+
; CHECK-NEXT: [[V_MOV_B:%[0-9]+]]:vreg_64 = V_MOV_B64_PSEUDO 1, implicit $exec
19+
; CHECK-NEXT: $vgpr0 = V_MOV_B32_e32 0, implicit $exec
20+
; CHECK-NEXT: $vgpr1 = COPY [[V_MOV_B]].sub1
21+
; CHECK-NEXT: SI_RETURN implicit $vgpr0, implicit killed $vgpr1
22+
%0:vreg_64 = V_MOV_B64_PSEUDO 1, implicit $exec
23+
%1:vgpr_32 = COPY %0.sub1
24+
$vgpr0 = V_MOV_B32_e32 0, implicit $exec
25+
$vgpr1 = COPY %1
26+
SI_RETURN implicit $vgpr0, implicit killed $vgpr1
27+
...
28+
29+
# Same as previous, except with an IMPLICIT_DEF
30+
---
31+
name: rematerialize_physreg_sub_def_already_live_at_def_assert_implicit_def
32+
tracksRegLiveness: true
33+
body: |
34+
bb.0:
35+
liveins: $vgpr0
36+
37+
; CHECK-LABEL: name: rematerialize_physreg_sub_def_already_live_at_def_assert_implicit_def
38+
; CHECK: liveins: $vgpr0
39+
; CHECK-NEXT: {{ $}}
40+
; CHECK-NEXT: [[DEF:%[0-9]+]]:vreg_64 = IMPLICIT_DEF
41+
; CHECK-NEXT: $vgpr0 = V_MOV_B32_e32 0, implicit $exec
42+
; CHECK-NEXT: $vgpr1 = COPY [[DEF]].sub1
43+
; CHECK-NEXT: SI_RETURN implicit $vgpr0, implicit killed $vgpr1
44+
%0:vreg_64 = IMPLICIT_DEF
45+
%1:vgpr_32 = COPY %0.sub1
46+
$vgpr0 = V_MOV_B32_e32 0, implicit $exec
47+
$vgpr1 = COPY %1
48+
SI_RETURN implicit $vgpr0, implicit killed $vgpr1
49+
...
50+
51+
---
52+
name: rematerialize_physreg_sub_def_no_live_sub_def_0
53+
tracksRegLiveness: true
54+
body: |
55+
bb.0:
56+
liveins: $vgpr0
57+
58+
; CHECK-LABEL: name: rematerialize_physreg_sub_def_no_live_sub_def_0
59+
; CHECK: liveins: $vgpr0
60+
; CHECK-NEXT: {{ $}}
61+
; CHECK-NEXT: dead $vgpr0_vgpr1 = V_MOV_B64_PSEUDO 1, implicit $exec, implicit-def $vgpr1
62+
; CHECK-NEXT: SI_RETURN implicit killed $vgpr1
63+
%0:vreg_64 = V_MOV_B64_PSEUDO 1, implicit $exec
64+
%1:vgpr_32 = COPY %0.sub1
65+
$vgpr1 = COPY %1
66+
SI_RETURN implicit killed $vgpr1
67+
...
68+
69+
---
70+
name: rematerialize_physreg_sub_def_no_live_sub_def_1
71+
tracksRegLiveness: true
72+
body: |
73+
bb.0:
74+
liveins: $vgpr0
75+
76+
; CHECK-LABEL: name: rematerialize_physreg_sub_def_no_live_sub_def_1
77+
; CHECK: liveins: $vgpr0
78+
; CHECK-NEXT: {{ $}}
79+
; CHECK-NEXT: dead $vgpr1_vgpr2 = V_MOV_B64_PSEUDO 1, implicit $exec, implicit-def $vgpr1
80+
; CHECK-NEXT: SI_RETURN implicit killed $vgpr1
81+
%0:vreg_64 = V_MOV_B64_PSEUDO 1, implicit $exec
82+
%1:vgpr_32 = COPY %0.sub0
83+
$vgpr1 = COPY %1
84+
SI_RETURN implicit killed $vgpr1
85+
...

0 commit comments

Comments
 (0)