Skip to content

Commit ad9eed1

Browse files
committed
[MachineVerifier] Verify LiveIntervals for PHIs
Implement basic support for verifying LiveIntervals for PHIs. Reviewed By: arsenm Differential Revision: https://reviews.llvm.org/D156872
1 parent efa8374 commit ad9eed1

File tree

2 files changed

+93
-3
lines changed

2 files changed

+93
-3
lines changed

llvm/lib/CodeGen/MachineVerifier.cpp

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2375,10 +2375,12 @@ void MachineVerifier::checkLivenessAtUse(const MachineOperand *MO,
23752375
const LiveRange &LR,
23762376
Register VRegOrUnit,
23772377
LaneBitmask LaneMask) {
2378+
const MachineInstr *MI = MO->getParent();
23782379
LiveQueryResult LRQ = LR.Query(UseIdx);
2380+
bool HasValue = LRQ.valueIn() || (MI->isPHI() && LRQ.valueOut());
23792381
// Check if we have a segment at the use, note however that we only need one
23802382
// live subregister range, the others may be dead.
2381-
if (!LRQ.valueIn() && LaneMask.none()) {
2383+
if (!HasValue && LaneMask.none()) {
23822384
report("No live segment at use", MO, MONum);
23832385
report_context_liverange(LR);
23842386
report_context_vreg_regunit(VRegOrUnit);
@@ -2484,7 +2486,14 @@ void MachineVerifier::checkLiveness(const MachineOperand *MO, unsigned MONum) {
24842486

24852487
// Check LiveInts liveness and kill.
24862488
if (LiveInts && !LiveInts->isNotInMIMap(*MI)) {
2487-
SlotIndex UseIdx = LiveInts->getInstructionIndex(*MI);
2489+
SlotIndex UseIdx;
2490+
if (MI->isPHI()) {
2491+
// PHI use occurs on the edge, so check for live out here instead.
2492+
UseIdx = LiveInts->getMBBEndIdx(
2493+
MI->getOperand(MONum + 1).getMBB()).getPrevSlot();
2494+
} else {
2495+
UseIdx = LiveInts->getInstructionIndex(*MI);
2496+
}
24882497
// Check the cached regunit intervals.
24892498
if (Reg.isPhysical() && !isReserved(Reg)) {
24902499
for (MCRegUnit Unit : TRI->regunits(Reg.asMCReg())) {
@@ -2509,7 +2518,7 @@ void MachineVerifier::checkLiveness(const MachineOperand *MO, unsigned MONum) {
25092518
continue;
25102519
checkLivenessAtUse(MO, MONum, UseIdx, SR, Reg, SR.LaneMask);
25112520
LiveQueryResult LRQ = SR.Query(UseIdx);
2512-
if (LRQ.valueIn())
2521+
if (LRQ.valueIn() || (MI->isPHI() && LRQ.valueOut()))
25132522
LiveInMask |= SR.LaneMask;
25142523
}
25152524
// At least parts of the register has to be live at the use.
@@ -2518,6 +2527,12 @@ void MachineVerifier::checkLiveness(const MachineOperand *MO, unsigned MONum) {
25182527
report_context(*LI);
25192528
report_context(UseIdx);
25202529
}
2530+
// For PHIs all lanes should be live
2531+
if (MI->isPHI() && LiveInMask != MOMask) {
2532+
report("Not all lanes of PHI source live at use", MO, MONum);
2533+
report_context(*LI);
2534+
report_context(UseIdx);
2535+
}
25212536
}
25222537
}
25232538
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 2
2+
# RUN: llc -march=amdgcn -mcpu=gfx1100 -verify-machineinstrs -run-pass liveintervals -o - %s | FileCheck -check-prefixes=GCN %s
3+
4+
# This test simply checks that liveintervals pass verification.
5+
6+
---
7+
name: split_critical_edge_subranges
8+
tracksRegLiveness: true
9+
body: |
10+
; GCN-LABEL: name: split_critical_edge_subranges
11+
; GCN: bb.0:
12+
; GCN-NEXT: successors: %bb.3(0x40000000), %bb.1(0x40000000)
13+
; GCN-NEXT: {{ $}}
14+
; GCN-NEXT: %coord:vreg_64 = IMPLICIT_DEF
15+
; GCN-NEXT: %desc:sgpr_256 = IMPLICIT_DEF
16+
; GCN-NEXT: %c0:sreg_32 = IMPLICIT_DEF
17+
; GCN-NEXT: %c1:sreg_32 = IMPLICIT_DEF
18+
; GCN-NEXT: %const:vgpr_32 = IMPLICIT_DEF
19+
; GCN-NEXT: %load:vreg_64 = IMAGE_LOAD_V2_V2_gfx11 %coord, %desc, 3, 1, -1, 0, 0, 0, 0, 0, 0, implicit $exec :: (dereferenceable load (s64), align 16, addrspace 4)
20+
; GCN-NEXT: %s0a:vgpr_32 = COPY %load.sub0
21+
; GCN-NEXT: %s0b:vgpr_32 = COPY %load.sub1
22+
; GCN-NEXT: S_CMP_EQ_U32 %c0, %c1, implicit-def $scc
23+
; GCN-NEXT: S_CBRANCH_SCC1 %bb.3, implicit $scc
24+
; GCN-NEXT: S_BRANCH %bb.1
25+
; GCN-NEXT: {{ $}}
26+
; GCN-NEXT: bb.1:
27+
; GCN-NEXT: successors: %bb.3(0x80000000)
28+
; GCN-NEXT: {{ $}}
29+
; GCN-NEXT: %s0c:vgpr_32 = V_ADD_F32_e64 0, %s0a, 0, %const, 0, 0, implicit $mode, implicit $exec
30+
; GCN-NEXT: %s0d:vgpr_32 = V_ADD_F32_e64 0, %s0b, 0, %const, 0, 0, implicit $mode, implicit $exec
31+
; GCN-NEXT: S_BRANCH %bb.3
32+
; GCN-NEXT: {{ $}}
33+
; GCN-NEXT: bb.2:
34+
; GCN-NEXT: S_NOP 0
35+
; GCN-NEXT: S_ENDPGM 0
36+
; GCN-NEXT: {{ $}}
37+
; GCN-NEXT: bb.3:
38+
; GCN-NEXT: successors: %bb.4(0x80000000)
39+
; GCN-NEXT: {{ $}}
40+
; GCN-NEXT: %phi0:vgpr_32 = PHI %s0a, %bb.0, %s0c, %bb.1
41+
; GCN-NEXT: %phi1:vgpr_32 = PHI %s0b, %bb.0, %s0d, %bb.1
42+
; GCN-NEXT: S_BRANCH %bb.4
43+
; GCN-NEXT: {{ $}}
44+
; GCN-NEXT: bb.4:
45+
; GCN-NEXT: S_ENDPGM 0, implicit %phi0, implicit %phi1
46+
bb.0:
47+
%coord:vreg_64 = IMPLICIT_DEF
48+
%desc:sgpr_256 = IMPLICIT_DEF
49+
%c0:sreg_32 = IMPLICIT_DEF
50+
%c1:sreg_32 = IMPLICIT_DEF
51+
%const:vgpr_32 = IMPLICIT_DEF
52+
%load:vreg_64 = IMAGE_LOAD_V2_V2_gfx11 %coord:vreg_64, killed %desc:sgpr_256, 3, 1, -1, 0, 0, 0, 0, 0, 0, implicit $exec :: (dereferenceable load (s64), align 16, addrspace 4)
53+
%s0a:vgpr_32 = COPY %load.sub0:vreg_64
54+
%s0b:vgpr_32 = COPY %load.sub1:vreg_64
55+
S_CMP_EQ_U32 killed %c0:sreg_32, killed %c1:sreg_32, implicit-def $scc
56+
S_CBRANCH_SCC1 %bb.3, implicit $scc
57+
S_BRANCH %bb.1
58+
59+
bb.1:
60+
%s0c:vgpr_32 = V_ADD_F32_e64 0, %s0a:vgpr_32, 0, %const:vgpr_32, 0, 0, implicit $mode, implicit $exec
61+
%s0d:vgpr_32 = V_ADD_F32_e64 0, %s0b:vgpr_32, 0, %const:vgpr_32, 0, 0, implicit $mode, implicit $exec
62+
S_BRANCH %bb.3
63+
64+
bb.2:
65+
S_NOP 0
66+
S_ENDPGM 0
67+
68+
bb.3:
69+
%phi0:vgpr_32 = PHI %s0a:vgpr_32, %bb.0, %s0c:vgpr_32, %bb.1
70+
%phi1:vgpr_32 = PHI %s0b:vgpr_32, %bb.0, %s0d:vgpr_32, %bb.1
71+
S_BRANCH %bb.4
72+
73+
bb.4:
74+
S_ENDPGM 0, implicit %phi0:vgpr_32, implicit %phi1:vgpr_32
75+
...

0 commit comments

Comments
 (0)