[llvm] CodeGen: Trim each PHI source subregister lane at its own last read (PR #226209)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 24 08:46:39 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-regalloc
Author: Matt Arsenault (arsenm)
<details>
<summary>Changes</summary>
This fixes verifier errors when LiveIntervals is computed in SSA.
Eliminating a PHI with LiveIntervals available, it shortens the live range
of the source register to its last read in the predecessor block, and shortened
each subrange to that same point. That is wrong when several PHIs read different
subregisters of the same source value: each lane's real last read is a different
one of the inserted copies, so trimming all of them at the last read of the whole
register leaves the earlier lanes live past their final use. The verifier rejects
this with "Instruction ending live segment doesn't read the register".
The per-lane read points cannot be recovered from the original live ranges, so
the new subreg copies need to be tracked.
Co-Authored-By: Claude Opus 5 <noreply@<!-- -->anthropic.com>
---
Full diff: https://github.com/llvm/llvm-project/pull/226209.diff
2 Files Affected:
- (modified) llvm/lib/CodeGen/PHIElimination.cpp (+56-5)
- (added) llvm/test/CodeGen/Hexagon/phi-elim-subreg-lanes.mir (+341)
``````````diff
diff --git a/llvm/lib/CodeGen/PHIElimination.cpp b/llvm/lib/CodeGen/PHIElimination.cpp
index de69ca8d91898..e749d8bbeb001 100644
--- a/llvm/lib/CodeGen/PHIElimination.cpp
+++ b/llvm/lib/CodeGen/PHIElimination.cpp
@@ -30,6 +30,7 @@
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineInstrBundle.h"
#include "llvm/CodeGen/MachineLoopInfo.h"
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/MachinePostDominators.h"
@@ -114,6 +115,18 @@ class PHIEliminationImpl {
// Count the number of non-undef PHI uses of each register in each BB.
VRegPHIUse VRegPHIUseCount;
+ struct PHISrcLaneKill {
+ LaneBitmask Lanes;
+ SlotIndex Index;
+ };
+
+ using PHISrcLaneKillMap =
+ DenseMap<BBVRegPair, SmallVector<PHISrcLaneKill, 2>>;
+
+ // Index of each PHI source copy inserted in a BB, and the lanes of the
+ // source register it reads.
+ PHISrcLaneKillMap PHISrcLaneKills;
+
// Defs of PHI sources which are implicit_def.
SmallPtrSet<MachineInstr *, 4> ImpDefs;
@@ -308,6 +321,7 @@ bool PHIEliminationImpl::run(MachineFunction &MF) {
LoweredPHIs.clear();
ImpDefs.clear();
VRegPHIUseCount.clear();
+ PHISrcLaneKills.clear();
MF.getProperties().setNoPHIs();
@@ -718,6 +732,15 @@ void PHIEliminationImpl::LowerPHINode(MachineBasicBlock &MBB,
SI &&
"Expected SI to be available to insert new MI if LIS is available");
LIS->addSegmentToEndOfBlock(IncomingReg, *NewSrcInstr);
+
+ if (!SrcUndef && LIS->getInterval(SrcReg).hasSubRanges()) {
+ LaneBitmask Lanes =
+ SrcSubReg ? MRI->getTargetRegisterInfo()->getSubRegIndexLaneMask(
+ SrcSubReg)
+ : LaneBitmask::getAll();
+ PHISrcLaneKills[BBVRegPair(opBlock.getNumber(), SrcReg)].push_back(
+ {Lanes, LIS->getInstructionIndex(*NewSrcInstr).getRegSlot()});
+ }
}
if (!SrcUndef &&
@@ -736,6 +759,12 @@ void PHIEliminationImpl::LowerPHINode(MachineBasicBlock &MBB,
}
}
+ PHISrcLaneKillMap::iterator KillsIt = PHISrcLaneKills.end();
+ if (SrcLI.hasSubRanges()) {
+ KillsIt =
+ PHISrcLaneKills.find(BBVRegPair(opBlock.getNumber(), SrcReg));
+ }
+
if (!isLiveOut) {
MachineBasicBlock::iterator KillInst = opBlock.end();
for (MachineBasicBlock::iterator Term = InsertPos;
@@ -766,13 +795,35 @@ void PHIEliminationImpl::LowerPHINode(MachineBasicBlock &MBB,
"Cannot find kill instruction");
SlotIndex LastUseIndex = LIS->getInstructionIndex(*KillInst);
- SrcLI.removeSegment(LastUseIndex.getRegSlot(),
- LIS->getMBBEndIdx(&opBlock));
- for (auto &SR : SrcLI.subranges()) {
- SR.removeSegment(LastUseIndex.getRegSlot(),
- LIS->getMBBEndIdx(&opBlock));
+ SlotIndex BlockEndIndex = LIS->getMBBEndIdx(&opBlock);
+ SrcLI.removeSegment(LastUseIndex.getRegSlot(), BlockEndIndex);
+ if (KillsIt != PHISrcLaneKills.end()) {
+ LaneBitmask KillLanes =
+ AnalyzeVirtRegLanesInBundle(*KillInst, SrcReg, *MRI,
+ *MRI->getTargetRegisterInfo())
+ .first;
+
+ // Each lane dies at its own last read, which can be earlier than
+ // the last read of the whole register.
+ KillsIt->second.push_back({KillLanes, LastUseIndex.getRegSlot()});
+
+ for (LiveInterval::SubRange &SR : SrcLI.subranges()) {
+ LiveQueryResult LRQ = SR.Query(LastUseIndex);
+ if (!LRQ.valueOut())
+ continue;
+
+ for (const PHISrcLaneKill &Kill : reverse(KillsIt->second)) {
+ if ((Kill.Lanes & SR.LaneMask).any()) {
+ SR.removeSegment(Kill.Index, LRQ.endPoint());
+ break;
+ }
+ }
+ }
}
}
+
+ if (KillsIt != PHISrcLaneKills.end())
+ PHISrcLaneKills.erase(KillsIt);
}
}
}
diff --git a/llvm/test/CodeGen/Hexagon/phi-elim-subreg-lanes.mir b/llvm/test/CodeGen/Hexagon/phi-elim-subreg-lanes.mir
new file mode 100644
index 0000000000000..64639d14da1bf
--- /dev/null
+++ b/llvm/test/CodeGen/Hexagon/phi-elim-subreg-lanes.mir
@@ -0,0 +1,341 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -mtriple=hexagon -passes='require<live-intervals>,phi-node-elimination' -o - %s | FileCheck %s
+
+# Two PHIs read different subregisters of a value defined in the same
+# block, so each lane dies at its own last read.
+---
+name: two_phis_read_different_subregs
+tracksRegLiveness: true
+body: |
+ ; CHECK-LABEL: name: two_phis_read_different_subregs
+ ; CHECK: bb.0:
+ ; CHECK-NEXT: successors: %bb.1(0x80000000)
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[A2_tfrsi:%[0-9]+]]:intregs = A2_tfrsi 0
+ ; CHECK-NEXT: [[A2_tfrsi1:%[0-9]+]]:intregs = A2_tfrsi 1
+ ; CHECK-NEXT: [[A2_combineii:%[0-9]+]]:doubleregs = A2_combineii 4, 4
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:intregs = COPY [[A2_tfrsi]]
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:intregs = COPY [[A2_tfrsi1]]
+ ; CHECK-NEXT: J2_jump %bb.1, implicit-def dead $pc
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.1:
+ ; CHECK-NEXT: successors: %bb.1(0x40000000), %bb.2(0x40000000)
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY2:%[0-9]+]]:intregs = COPY [[COPY1]]
+ ; CHECK-NEXT: [[COPY3:%[0-9]+]]:intregs = COPY [[COPY]]
+ ; CHECK-NEXT: [[REG_SEQUENCE:%[0-9]+]]:doubleregs = REG_SEQUENCE [[COPY3]], %subreg.isub_lo, [[COPY2]], %subreg.isub_hi
+ ; CHECK-NEXT: [[A2_vaddw:%[0-9]+]]:doubleregs = A2_vaddw [[REG_SEQUENCE]], [[A2_combineii]]
+ ; CHECK-NEXT: [[C2_cmpeqi:%[0-9]+]]:predregs = C2_cmpeqi [[COPY3]], 0
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:intregs = COPY [[A2_vaddw]].isub_lo
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:intregs = COPY [[A2_vaddw]].isub_hi
+ ; CHECK-NEXT: J2_jumpt [[C2_cmpeqi]], %bb.1, implicit-def dead $pc
+ ; CHECK-NEXT: J2_jump %bb.2, implicit-def dead $pc
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.2:
+ ; CHECK-NEXT: PS_jmpret $r31, implicit-def dead $pc
+ bb.0:
+ successors: %bb.1
+
+ %0:intregs = A2_tfrsi 0
+ %1:intregs = A2_tfrsi 1
+ %2:doubleregs = A2_combineii 4, 4
+ J2_jump %bb.1, implicit-def dead $pc
+
+ bb.1:
+ successors: %bb.1, %bb.2
+
+ %3:intregs = PHI %0, %bb.0, %6.isub_lo, %bb.1
+ %4:intregs = PHI %1, %bb.0, %6.isub_hi, %bb.1
+ %5:doubleregs = REG_SEQUENCE %3, %subreg.isub_lo, %4, %subreg.isub_hi
+ %6:doubleregs = A2_vaddw %5, %2
+ %7:predregs = C2_cmpeqi %3, 0
+ J2_jumpt %7, %bb.1, implicit-def dead $pc
+ J2_jump %bb.2, implicit-def dead $pc
+
+ bb.2:
+ PS_jmpret $r31, implicit-def dead $pc
+...
+
+# The terminator reads a lane no PHI reads, so that lane already dies
+# there and must not be trimmed again.
+---
+name: terminator_reads_lane_no_phi_reads
+tracksRegLiveness: true
+body: |
+ ; CHECK-LABEL: name: terminator_reads_lane_no_phi_reads
+ ; CHECK: bb.0:
+ ; CHECK-NEXT: successors: %bb.1(0x80000000)
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[A2_tfrsi:%[0-9]+]]:intregs = A2_tfrsi 0
+ ; CHECK-NEXT: [[A2_combineii:%[0-9]+]]:doubleregs = A2_combineii 4, 4
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:intregs = COPY [[A2_tfrsi]]
+ ; CHECK-NEXT: J2_jump %bb.1, implicit-def dead $pc
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.1:
+ ; CHECK-NEXT: successors: %bb.1(0x40000000), %bb.2(0x40000000)
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:intregs = COPY [[COPY]]
+ ; CHECK-NEXT: [[REG_SEQUENCE:%[0-9]+]]:doubleregs = REG_SEQUENCE [[COPY1]], %subreg.isub_lo, [[COPY1]], %subreg.isub_hi
+ ; CHECK-NEXT: [[A2_vaddw:%[0-9]+]]:doubleregs = A2_vaddw [[REG_SEQUENCE]], [[A2_combineii]]
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:intregs = COPY [[A2_vaddw]].isub_lo
+ ; CHECK-NEXT: J4_cmpeqi_t_jumpnv_t [[A2_vaddw]].isub_hi, 0, %bb.1, implicit-def $pc
+ ; CHECK-NEXT: J2_jump %bb.2, implicit-def dead $pc
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.2:
+ ; CHECK-NEXT: PS_jmpret $r31, implicit-def dead $pc
+ bb.0:
+ successors: %bb.1
+
+ %0:intregs = A2_tfrsi 0
+ %2:doubleregs = A2_combineii 4, 4
+ J2_jump %bb.1, implicit-def dead $pc
+
+ bb.1:
+ successors: %bb.1, %bb.2
+
+ %3:intregs = PHI %0, %bb.0, %6.isub_lo, %bb.1
+ %5:doubleregs = REG_SEQUENCE %3, %subreg.isub_lo, %3, %subreg.isub_hi
+ %6:doubleregs = A2_vaddw %5, %2
+ J4_cmpeqi_t_jumpnv_t %6.isub_hi, 0, %bb.1, implicit-def $pc
+ J2_jump %bb.2, implicit-def dead $pc
+
+ bb.2:
+ PS_jmpret $r31, implicit-def dead $pc
+...
+
+# The terminator reads a lane a PHI also reads, so that lane dies at the
+# terminator and the other at its copy.
+---
+name: terminator_reads_phi_read_lane
+tracksRegLiveness: true
+body: |
+ ; CHECK-LABEL: name: terminator_reads_phi_read_lane
+ ; CHECK: bb.0:
+ ; CHECK-NEXT: successors: %bb.1(0x80000000)
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[A2_tfrsi:%[0-9]+]]:intregs = A2_tfrsi 0
+ ; CHECK-NEXT: [[A2_tfrsi1:%[0-9]+]]:intregs = A2_tfrsi 1
+ ; CHECK-NEXT: [[A2_combineii:%[0-9]+]]:doubleregs = A2_combineii 4, 4
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:intregs = COPY [[A2_tfrsi]]
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:intregs = COPY [[A2_tfrsi1]]
+ ; CHECK-NEXT: J2_jump %bb.1, implicit-def dead $pc
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.1:
+ ; CHECK-NEXT: successors: %bb.1(0x40000000), %bb.2(0x40000000)
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY2:%[0-9]+]]:intregs = COPY [[COPY1]]
+ ; CHECK-NEXT: [[COPY3:%[0-9]+]]:intregs = COPY [[COPY]]
+ ; CHECK-NEXT: [[REG_SEQUENCE:%[0-9]+]]:doubleregs = REG_SEQUENCE [[COPY3]], %subreg.isub_lo, [[COPY2]], %subreg.isub_hi
+ ; CHECK-NEXT: [[A2_vaddw:%[0-9]+]]:doubleregs = A2_vaddw [[REG_SEQUENCE]], [[A2_combineii]]
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:intregs = COPY [[A2_vaddw]].isub_lo
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:intregs = COPY [[A2_vaddw]].isub_hi
+ ; CHECK-NEXT: J4_cmpeqi_t_jumpnv_t [[A2_vaddw]].isub_hi, 0, %bb.1, implicit-def $pc
+ ; CHECK-NEXT: J2_jump %bb.2, implicit-def dead $pc
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.2:
+ ; CHECK-NEXT: PS_jmpret $r31, implicit-def dead $pc
+ bb.0:
+ successors: %bb.1
+
+ %0:intregs = A2_tfrsi 0
+ %1:intregs = A2_tfrsi 1
+ %2:doubleregs = A2_combineii 4, 4
+ J2_jump %bb.1, implicit-def dead $pc
+
+ bb.1:
+ successors: %bb.1, %bb.2
+
+ %3:intregs = PHI %0, %bb.0, %6.isub_lo, %bb.1
+ %4:intregs = PHI %1, %bb.0, %6.isub_hi, %bb.1
+ %5:doubleregs = REG_SEQUENCE %3, %subreg.isub_lo, %4, %subreg.isub_hi
+ %6:doubleregs = A2_vaddw %5, %2
+ J4_cmpeqi_t_jumpnv_t %6.isub_hi, 0, %bb.1, implicit-def $pc
+ J2_jump %bb.2, implicit-def dead $pc
+
+ bb.2:
+ PS_jmpret $r31, implicit-def dead $pc
+...
+
+# A PHI reads the whole register before another reads one subregister, so
+# the lane not read by the last copy dies at the whole register copy.
+---
+name: whole_reg_phi_lowered_before_subreg_phi
+tracksRegLiveness: true
+body: |
+ ; CHECK-LABEL: name: whole_reg_phi_lowered_before_subreg_phi
+ ; CHECK: bb.0:
+ ; CHECK-NEXT: successors: %bb.1(0x80000000)
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[A2_tfrsi:%[0-9]+]]:intregs = A2_tfrsi 0
+ ; CHECK-NEXT: [[A2_combineii:%[0-9]+]]:doubleregs = A2_combineii 4, 4
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:doubleregs = COPY [[A2_combineii]]
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:intregs = COPY [[A2_tfrsi]]
+ ; CHECK-NEXT: J2_jump %bb.1, implicit-def dead $pc
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.1:
+ ; CHECK-NEXT: successors: %bb.1(0x40000000), %bb.2(0x40000000)
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY2:%[0-9]+]]:intregs = COPY [[COPY1]]
+ ; CHECK-NEXT: [[COPY3:%[0-9]+]]:doubleregs = COPY [[COPY]]
+ ; CHECK-NEXT: [[REG_SEQUENCE:%[0-9]+]]:doubleregs = REG_SEQUENCE [[COPY2]], %subreg.isub_lo, [[COPY2]], %subreg.isub_hi
+ ; CHECK-NEXT: [[A2_vaddw:%[0-9]+]]:doubleregs = A2_vaddw [[COPY3]], [[REG_SEQUENCE]]
+ ; CHECK-NEXT: [[C2_cmpeqi:%[0-9]+]]:predregs = C2_cmpeqi [[COPY2]], 0
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:doubleregs = COPY [[A2_vaddw]]
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:intregs = COPY [[A2_vaddw]].isub_lo
+ ; CHECK-NEXT: J2_jumpt [[C2_cmpeqi]], %bb.1, implicit-def dead $pc
+ ; CHECK-NEXT: J2_jump %bb.2, implicit-def dead $pc
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.2:
+ ; CHECK-NEXT: PS_jmpret $r31, implicit-def dead $pc
+ bb.0:
+ successors: %bb.1
+
+ %0:intregs = A2_tfrsi 0
+ %2:doubleregs = A2_combineii 4, 4
+ J2_jump %bb.1, implicit-def dead $pc
+
+ bb.1:
+ successors: %bb.1, %bb.2
+
+ %4:doubleregs = PHI %2, %bb.0, %6, %bb.1
+ %3:intregs = PHI %0, %bb.0, %6.isub_lo, %bb.1
+ %5:doubleregs = REG_SEQUENCE %3, %subreg.isub_lo, %3, %subreg.isub_hi
+ %6:doubleregs = A2_vaddw %4, %5
+ %7:predregs = C2_cmpeqi %3, 0
+ J2_jumpt %7, %bb.1, implicit-def dead $pc
+ J2_jump %bb.2, implicit-def dead $pc
+
+ bb.2:
+ PS_jmpret $r31, implicit-def dead $pc
+...
+
+# Two PHIs read the same lane, which dies at the later of the two copies.
+---
+name: two_phis_read_same_subreg
+tracksRegLiveness: true
+body: |
+ ; CHECK-LABEL: name: two_phis_read_same_subreg
+ ; CHECK: bb.0:
+ ; CHECK-NEXT: successors: %bb.1(0x80000000)
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[A2_tfrsi:%[0-9]+]]:intregs = A2_tfrsi 0
+ ; CHECK-NEXT: [[A2_tfrsi1:%[0-9]+]]:intregs = A2_tfrsi 1
+ ; CHECK-NEXT: [[A2_combineii:%[0-9]+]]:doubleregs = A2_combineii 4, 4
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:intregs = COPY [[A2_tfrsi]]
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:intregs = COPY [[A2_tfrsi]]
+ ; CHECK-NEXT: [[COPY2:%[0-9]+]]:intregs = COPY [[A2_tfrsi1]]
+ ; CHECK-NEXT: J2_jump %bb.1, implicit-def dead $pc
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.1:
+ ; CHECK-NEXT: successors: %bb.1(0x40000000), %bb.2(0x40000000)
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY3:%[0-9]+]]:intregs = COPY [[COPY2]]
+ ; CHECK-NEXT: [[COPY4:%[0-9]+]]:intregs = COPY [[COPY1]]
+ ; CHECK-NEXT: [[COPY5:%[0-9]+]]:intregs = COPY [[COPY]]
+ ; CHECK-NEXT: [[REG_SEQUENCE:%[0-9]+]]:doubleregs = REG_SEQUENCE [[COPY5]], %subreg.isub_lo, [[COPY3]], %subreg.isub_hi
+ ; CHECK-NEXT: [[A2_vaddw:%[0-9]+]]:doubleregs = A2_vaddw [[REG_SEQUENCE]], [[A2_combineii]]
+ ; CHECK-NEXT: [[C2_cmpeqi:%[0-9]+]]:predregs = C2_cmpeqi [[COPY4]], 0
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:intregs = COPY [[A2_vaddw]].isub_lo
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:intregs = COPY [[A2_vaddw]].isub_lo
+ ; CHECK-NEXT: [[COPY2:%[0-9]+]]:intregs = COPY [[A2_vaddw]].isub_hi
+ ; CHECK-NEXT: J2_jumpt [[C2_cmpeqi]], %bb.1, implicit-def dead $pc
+ ; CHECK-NEXT: J2_jump %bb.2, implicit-def dead $pc
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.2:
+ ; CHECK-NEXT: PS_jmpret $r31, implicit-def dead $pc
+ bb.0:
+ successors: %bb.1
+
+ %0:intregs = A2_tfrsi 0
+ %1:intregs = A2_tfrsi 1
+ %2:doubleregs = A2_combineii 4, 4
+ J2_jump %bb.1, implicit-def dead $pc
+
+ bb.1:
+ successors: %bb.1, %bb.2
+
+ %3:intregs = PHI %0, %bb.0, %6.isub_lo, %bb.1
+ %4:intregs = PHI %0, %bb.0, %6.isub_lo, %bb.1
+ %8:intregs = PHI %1, %bb.0, %6.isub_hi, %bb.1
+ %5:doubleregs = REG_SEQUENCE %3, %subreg.isub_lo, %8, %subreg.isub_hi
+ %6:doubleregs = A2_vaddw %5, %2
+ %7:predregs = C2_cmpeqi %4, 0
+ J2_jumpt %7, %bb.1, implicit-def dead $pc
+ J2_jump %bb.2, implicit-def dead $pc
+
+ bb.2:
+ PS_jmpret $r31, implicit-def dead $pc
+...
+
+# The second of two identical PHIs reuses the first copy, so it does not
+# add a later read of the lane.
+---
+name: identical_phis_reuse_one_copy
+tracksRegLiveness: true
+body: |
+ ; CHECK-LABEL: name: identical_phis_reuse_one_copy
+ ; CHECK: bb.0:
+ ; CHECK-NEXT: successors: %bb.2(0x40000000), %bb.1(0x40000000)
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[A2_tfrsi:%[0-9]+]]:intregs = A2_tfrsi 0
+ ; CHECK-NEXT: [[A2_combineii:%[0-9]+]]:doubleregs = A2_combineii 4, 4
+ ; CHECK-NEXT: [[A2_vaddw:%[0-9]+]]:doubleregs = A2_vaddw [[A2_combineii]], [[A2_combineii]]
+ ; CHECK-NEXT: [[C2_cmpeqi:%[0-9]+]]:predregs = C2_cmpeqi [[A2_tfrsi]], 0
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:intregs = COPY [[A2_vaddw]].isub_lo
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:intregs = COPY [[A2_vaddw]].isub_hi
+ ; CHECK-NEXT: J2_jumpt [[C2_cmpeqi]], %bb.2, implicit-def dead $pc
+ ; CHECK-NEXT: J2_jump %bb.1, implicit-def dead $pc
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.1:
+ ; CHECK-NEXT: successors: %bb.2(0x40000000), %bb.3(0x40000000)
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[A2_tfrsi1:%[0-9]+]]:intregs = A2_tfrsi 7
+ ; CHECK-NEXT: [[C2_cmpeqi1:%[0-9]+]]:predregs = C2_cmpeqi [[A2_tfrsi1]], 0
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:intregs = COPY [[A2_tfrsi1]]
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:intregs = COPY [[A2_tfrsi1]]
+ ; CHECK-NEXT: J2_jumpt [[C2_cmpeqi1]], %bb.2, implicit-def dead $pc
+ ; CHECK-NEXT: J2_jump %bb.3, implicit-def dead $pc
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.2:
+ ; CHECK-NEXT: successors: %bb.3(0x80000000)
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY2:%[0-9]+]]:intregs = COPY [[COPY1]]
+ ; CHECK-NEXT: [[COPY3:%[0-9]+]]:intregs = COPY [[COPY]]
+ ; CHECK-NEXT: [[COPY4:%[0-9]+]]:intregs = COPY [[COPY]]
+ ; CHECK-NEXT: [[A2_add:%[0-9]+]]:intregs = A2_add [[COPY4]], [[COPY3]]
+ ; CHECK-NEXT: dead [[A2_add1:%[0-9]+]]:intregs = A2_add [[A2_add]], [[COPY2]]
+ ; CHECK-NEXT: J2_jump %bb.3, implicit-def dead $pc
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.3:
+ ; CHECK-NEXT: PS_jmpret $r31, implicit-def dead $pc
+ bb.0:
+ successors: %bb.1, %bb.3
+
+ %0:intregs = A2_tfrsi 0
+ %2:doubleregs = A2_combineii 4, 4
+ %6:doubleregs = A2_vaddw %2, %2
+ %7:predregs = C2_cmpeqi %0, 0
+ J2_jumpt %7, %bb.1, implicit-def dead $pc
+ J2_jump %bb.3, implicit-def dead $pc
+
+ bb.3:
+ successors: %bb.1, %bb.2
+
+ %10:intregs = A2_tfrsi 7
+ %11:predregs = C2_cmpeqi %10, 0
+ J2_jumpt %11, %bb.1, implicit-def dead $pc
+ J2_jump %bb.2, implicit-def dead $pc
+
+ bb.1:
+ successors: %bb.2
+
+ %3:intregs = PHI %6.isub_lo, %bb.0, %10, %bb.3
+ %4:intregs = PHI %6.isub_lo, %bb.0, %10, %bb.3
+ %5:intregs = PHI %6.isub_hi, %bb.0, %10, %bb.3
+ %12:intregs = A2_add %3, %4
+ %13:intregs = A2_add %12, %5
+ J2_jump %bb.2, implicit-def dead $pc
+
+ bb.2:
+ PS_jmpret $r31, implicit-def dead $pc
+...
``````````
</details>
https://github.com/llvm/llvm-project/pull/226209
More information about the llvm-commits
mailing list