Skip to content

Commit 52b247b

Browse files
authored
[PHIElimination] Handle subranges in LiveInterval updates (#69429)
Add subrange tracking and handling for LiveIntervals during PHI elimination. This requires extending MachineBasicBlock::SplitCriticalEdge to also update subrange intervals.
1 parent 18415c8 commit 52b247b

File tree

7 files changed

+86
-31
lines changed

7 files changed

+86
-31
lines changed

llvm/include/llvm/CodeGen/LiveInterval.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -520,8 +520,9 @@ namespace llvm {
520520
endIndex() < End.getBoundaryIndex();
521521
}
522522

523-
/// Remove the specified segment from this range. Note that the segment
524-
/// must be a single Segment in its entirety.
523+
/// Remove the specified interval from this live range.
524+
/// Does nothing if interval is not part of this live range.
525+
/// Note that the interval must be within a single Segment in its entirety.
525526
void removeSegment(SlotIndex Start, SlotIndex End,
526527
bool RemoveDeadValNo = false);
527528

llvm/include/llvm/CodeGen/LiveIntervals.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,13 @@ class VirtRegMap;
139139
return LI;
140140
}
141141

142+
/// Return an existing interval for \p Reg.
143+
/// If \p Reg has no interval then this creates a new empty one instead.
144+
/// Note: does not trigger interval computation.
145+
LiveInterval &getOrCreateEmptyInterval(Register Reg) {
146+
return hasInterval(Reg) ? getInterval(Reg) : createEmptyInterval(Reg);
147+
}
148+
142149
/// Interval removal.
143150
void removeInterval(Register Reg) {
144151
delete VirtRegIntervals[Reg];

llvm/lib/CodeGen/LiveInterval.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -563,13 +563,15 @@ VNInfo *LiveRange::extendInBlock(SlotIndex StartIdx, SlotIndex Kill) {
563563
return CalcLiveRangeUtilVector(this).extendInBlock(StartIdx, Kill);
564564
}
565565

566-
/// Remove the specified segment from this range. Note that the segment must
567-
/// be in a single Segment in its entirety.
568566
void LiveRange::removeSegment(SlotIndex Start, SlotIndex End,
569567
bool RemoveDeadValNo) {
570568
// Find the Segment containing this span.
571569
iterator I = find(Start);
572-
assert(I != end() && "Segment is not in range!");
570+
571+
// No Segment found, so nothing to do.
572+
if (I == end())
573+
return;
574+
573575
assert(I->containsInterval(Start, End)
574576
&& "Segment is not entirely in range!");
575577

llvm/lib/CodeGen/LiveIntervals.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -862,7 +862,7 @@ float LiveIntervals::getSpillWeight(bool isDef, bool isUse,
862862

863863
LiveRange::Segment
864864
LiveIntervals::addSegmentToEndOfBlock(Register Reg, MachineInstr &startInst) {
865-
LiveInterval &Interval = createEmptyInterval(Reg);
865+
LiveInterval &Interval = getOrCreateEmptyInterval(Reg);
866866
VNInfo *VN = Interval.getNextValue(
867867
SlotIndex(getInstructionIndex(startInst).getRegSlot()),
868868
getVNInfoAllocator());

llvm/lib/CodeGen/MachineBasicBlock.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1283,6 +1283,8 @@ MachineBasicBlock *MachineBasicBlock::SplitCriticalEdge(
12831283
assert(VNI &&
12841284
"PHI sources should be live out of their predecessors.");
12851285
LI.addSegment(LiveInterval::Segment(StartIndex, EndIndex, VNI));
1286+
for (auto &SR : LI.subranges())
1287+
SR.addSegment(LiveInterval::Segment(StartIndex, EndIndex, VNI));
12861288
}
12871289
}
12881290
}
@@ -1302,8 +1304,16 @@ MachineBasicBlock *MachineBasicBlock::SplitCriticalEdge(
13021304
VNInfo *VNI = LI.getVNInfoAt(PrevIndex);
13031305
assert(VNI && "LiveInterval should have VNInfo where it is live.");
13041306
LI.addSegment(LiveInterval::Segment(StartIndex, EndIndex, VNI));
1307+
// Update subranges with live values
1308+
for (auto &SR : LI.subranges()) {
1309+
VNInfo *VNI = SR.getVNInfoAt(PrevIndex);
1310+
if (VNI)
1311+
SR.addSegment(LiveInterval::Segment(StartIndex, EndIndex, VNI));
1312+
}
13051313
} else if (!isLiveOut && !isLastMBB) {
13061314
LI.removeSegment(StartIndex, EndIndex);
1315+
for (auto &SR : LI.subranges())
1316+
SR.removeSegment(StartIndex, EndIndex);
13071317
}
13081318
}
13091319

llvm/lib/CodeGen/PHIElimination.cpp

Lines changed: 45 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -389,7 +389,7 @@ void PHIElimination::LowerPHINode(MachineBasicBlock &MBB,
389389
if (IncomingReg) {
390390
// Add the region from the beginning of MBB to the copy instruction to
391391
// IncomingReg's live interval.
392-
LiveInterval &IncomingLI = LIS->createEmptyInterval(IncomingReg);
392+
LiveInterval &IncomingLI = LIS->getOrCreateEmptyInterval(IncomingReg);
393393
VNInfo *IncomingVNI = IncomingLI.getVNInfoAt(MBBStartIndex);
394394
if (!IncomingVNI)
395395
IncomingVNI = IncomingLI.getNextValue(MBBStartIndex,
@@ -400,24 +400,47 @@ void PHIElimination::LowerPHINode(MachineBasicBlock &MBB,
400400
}
401401

402402
LiveInterval &DestLI = LIS->getInterval(DestReg);
403-
assert(!DestLI.empty() && "PHIs should have nonempty LiveIntervals.");
404-
if (DestLI.endIndex().isDead()) {
405-
// A dead PHI's live range begins and ends at the start of the MBB, but
406-
// the lowered copy, which will still be dead, needs to begin and end at
407-
// the copy instruction.
408-
VNInfo *OrigDestVNI = DestLI.getVNInfoAt(MBBStartIndex);
409-
assert(OrigDestVNI && "PHI destination should be live at block entry.");
410-
DestLI.removeSegment(MBBStartIndex, MBBStartIndex.getDeadSlot());
411-
DestLI.createDeadDef(DestCopyIndex.getRegSlot(),
412-
LIS->getVNInfoAllocator());
413-
DestLI.removeValNo(OrigDestVNI);
414-
} else {
415-
// Otherwise, remove the region from the beginning of MBB to the copy
416-
// instruction from DestReg's live interval.
417-
DestLI.removeSegment(MBBStartIndex, DestCopyIndex.getRegSlot());
418-
VNInfo *DestVNI = DestLI.getVNInfoAt(DestCopyIndex.getRegSlot());
403+
assert(!DestLI.empty() && "PHIs should have non-empty LiveIntervals.");
404+
405+
SlotIndex NewStart = DestCopyIndex.getRegSlot();
406+
407+
SmallVector<LiveRange *> ToUpdate({&DestLI});
408+
for (auto &SR : DestLI.subranges())
409+
ToUpdate.push_back(&SR);
410+
411+
for (auto LR : ToUpdate) {
412+
auto DestSegment = LR->find(MBBStartIndex);
413+
assert(DestSegment != LR->end() &&
414+
"PHI destination must be live in block");
415+
416+
if (LR->endIndex().isDead()) {
417+
// A dead PHI's live range begins and ends at the start of the MBB, but
418+
// the lowered copy, which will still be dead, needs to begin and end at
419+
// the copy instruction.
420+
VNInfo *OrigDestVNI = LR->getVNInfoAt(DestSegment->start);
421+
assert(OrigDestVNI && "PHI destination should be live at block entry.");
422+
LR->removeSegment(DestSegment->start, DestSegment->start.getDeadSlot());
423+
LR->createDeadDef(NewStart, LIS->getVNInfoAllocator());
424+
LR->removeValNo(OrigDestVNI);
425+
continue;
426+
}
427+
428+
// Destination copies are not inserted in the same order as the PHI nodes
429+
// they replace. Hence the start of the live range may need to be adjusted
430+
// to match the actual slot index of the copy.
431+
if (DestSegment->start > NewStart) {
432+
VNInfo *VNI = LR->getVNInfoAt(DestSegment->start);
433+
assert(VNI && "value should be defined for known segment");
434+
LR->addSegment(
435+
LiveInterval::Segment(NewStart, DestSegment->start, VNI));
436+
} else if (DestSegment->start < NewStart) {
437+
assert(DestSegment->start >= MBBStartIndex);
438+
assert(DestSegment->end >= DestCopyIndex.getRegSlot());
439+
LR->removeSegment(DestSegment->start, NewStart);
440+
}
441+
VNInfo *DestVNI = LR->getVNInfoAt(NewStart);
419442
assert(DestVNI && "PHI destination should be live at its definition.");
420-
DestVNI->def = DestCopyIndex.getRegSlot();
443+
DestVNI->def = NewStart;
421444
}
422445
}
423446

@@ -612,6 +635,10 @@ void PHIElimination::LowerPHINode(MachineBasicBlock &MBB,
612635
SlotIndex LastUseIndex = LIS->getInstructionIndex(*KillInst);
613636
SrcLI.removeSegment(LastUseIndex.getRegSlot(),
614637
LIS->getMBBEndIdx(&opBlock));
638+
for (auto &SR : SrcLI.subranges()) {
639+
SR.removeSegment(LastUseIndex.getRegSlot(),
640+
LIS->getMBBEndIdx(&opBlock));
641+
}
615642
}
616643
}
617644
}

llvm/test/CodeGen/AMDGPU/split-mbb-lis-subrange.mir

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
# 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
2+
# RUN: llc -march=amdgcn -mcpu=gfx1100 -verify-machineinstrs -run-pass liveintervals,phi-node-elimination -o - %s | FileCheck -check-prefixes=GCN %s
33

4-
# This test simply checks that liveintervals pass verification.
4+
# This checks liveintervals pass verification and phi-node-elimination correctly preserves them.
55

66
---
77
name: split_critical_edge_subranges
88
tracksRegLiveness: true
99
body: |
1010
; GCN-LABEL: name: split_critical_edge_subranges
1111
; GCN: bb.0:
12-
; GCN-NEXT: successors: %bb.3(0x40000000), %bb.1(0x40000000)
12+
; GCN-NEXT: successors: %bb.5(0x40000000), %bb.1(0x40000000)
1313
; GCN-NEXT: {{ $}}
1414
; GCN-NEXT: %coord:vreg_64 = IMPLICIT_DEF
1515
; GCN-NEXT: %desc:sgpr_256 = IMPLICIT_DEF
@@ -20,14 +20,22 @@ body: |
2020
; GCN-NEXT: %s0a:vgpr_32 = COPY %load.sub0
2121
; GCN-NEXT: %s0b:vgpr_32 = COPY %load.sub1
2222
; 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
23+
; GCN-NEXT: S_CBRANCH_SCC0 %bb.1, implicit $scc
24+
; GCN-NEXT: {{ $}}
25+
; GCN-NEXT: bb.5:
26+
; GCN-NEXT: successors: %bb.3(0x80000000)
27+
; GCN-NEXT: {{ $}}
28+
; GCN-NEXT: [[COPY:%[0-9]+]]:vgpr_32 = COPY %s0a
29+
; GCN-NEXT: [[COPY1:%[0-9]+]]:vgpr_32 = COPY %s0b
30+
; GCN-NEXT: S_BRANCH %bb.3
2531
; GCN-NEXT: {{ $}}
2632
; GCN-NEXT: bb.1:
2733
; GCN-NEXT: successors: %bb.3(0x80000000)
2834
; GCN-NEXT: {{ $}}
2935
; GCN-NEXT: %s0c:vgpr_32 = V_ADD_F32_e64 0, %s0a, 0, %const, 0, 0, implicit $mode, implicit $exec
3036
; GCN-NEXT: %s0d:vgpr_32 = V_ADD_F32_e64 0, %s0b, 0, %const, 0, 0, implicit $mode, implicit $exec
37+
; GCN-NEXT: [[COPY2:%[0-9]+]]:vgpr_32 = COPY %s0c
38+
; GCN-NEXT: [[COPY3:%[0-9]+]]:vgpr_32 = COPY %s0d
3139
; GCN-NEXT: S_BRANCH %bb.3
3240
; GCN-NEXT: {{ $}}
3341
; GCN-NEXT: bb.2:
@@ -37,8 +45,8 @@ body: |
3745
; GCN-NEXT: bb.3:
3846
; GCN-NEXT: successors: %bb.4(0x80000000)
3947
; 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
48+
; GCN-NEXT: %phi1:vgpr_32 = COPY [[COPY3]]
49+
; GCN-NEXT: %phi0:vgpr_32 = COPY [[COPY2]]
4250
; GCN-NEXT: S_BRANCH %bb.4
4351
; GCN-NEXT: {{ $}}
4452
; GCN-NEXT: bb.4:

0 commit comments

Comments
 (0)