[CodeGen][AMDGPU] TwoAddress: Only skip undef COPY at REG_SEQUENCE lowering when there is Live info or no uses for subreg (#175598)

Currently, the compiler doesn't create a COPY for undef operands while
lowering REG_SEQUENCE, and only if LIS information is available, it
propagates the undef flag to the subreg uses. So, if LIS isn't
available, we can end up with some uses without def of those lanes.
Now, we check which lanes are used in a single scan of
use_nodbg_operands() per REG_SEQ, and perform the skip of the COPY only
if LIS is avaible (as undef will be propagated later) or if there are no
uses for that lane.
There is still a scan of the use list, but now it's only one per REG_SEQ
and I think it's necessary, as there is no guarantee to have LIS or
other analysis pass information at this stage.

This is a proposal fix for issue:
https://github.com/llvm/llvm-project/issues/175596

---------

Co-authored-by: Carl Ritson <critson@perlfu.co.uk>
This commit is contained in:
Felipe Quezada 2026-02-13 13:46:30 -03:00 committed by GitHub
parent ede1a9626b
commit 9deb4fda30
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 86 additions and 2 deletions

View File

@ -2014,6 +2014,16 @@ void TwoAddressInstructionImpl::eliminateRegSequence(
}
}
// If there are no live intervals information, we scan the use list once
// in order to find which subregisters are used.
LaneBitmask UsedLanes = LaneBitmask::getNone();
if (!LIS) {
for (MachineOperand &Use : MRI->use_nodbg_operands(DstReg)) {
if (unsigned SubReg = Use.getSubReg())
UsedLanes |= TRI->getSubRegIndexLaneMask(SubReg);
}
}
LaneBitmask UndefLanes = LaneBitmask::getNone();
bool DefEmitted = false;
for (unsigned i = 1, e = MI.getNumOperands(); i < e; i += 2) {
@ -2021,9 +2031,14 @@ void TwoAddressInstructionImpl::eliminateRegSequence(
Register SrcReg = UseMO.getReg();
unsigned SubIdx = MI.getOperand(i+1).getImm();
// Nothing needs to be inserted for undef operands.
// Unless there are no live intervals, and they are used at a later
// instruction as operand.
if (UseMO.isUndef()) {
UndefLanes |= TRI->getSubRegIndexLaneMask(SubIdx);
continue;
LaneBitmask LaneMask = TRI->getSubRegIndexLaneMask(SubIdx);
if (LIS || (UsedLanes & LaneMask).none()) {
UndefLanes |= LaneMask;
continue;
}
}
// Defer any kill flag to the last operand using SrcReg. Otherwise, we

View File

@ -0,0 +1,69 @@
# RUN: llc -mtriple=amdgcn-amd-amdhsa -verify-machineinstrs -run-pass=twoaddressinstruction -o - %s | FileCheck -check-prefix=CHECK %s
# RUN: llc -mtriple=amdgcn-amd-amdhsa -verify-machineinstrs -run-pass=liveintervals,twoaddressinstruction -o - %s | FileCheck -check-prefix=LIS %s
# Checks that while lowering REG_SEQUENCE, undef COPY are not skipped if there is no LIS
# information
---
name: regsequence-undef-subreg-use
noPhis: true
body: |
bb.0:
; CHECK-LABEL: name: regsequence-undef-subreg-use
; CHECK: [[COPY:%[0-9]+]]:sgpr_32 = S_MOV_B32 0, implicit $exec
; CHECK-NEXT: undef [[DEF:%[0-9]+]].sub0:sreg_64 = COPY [[COPY]]
; CHECK-NEXT: [[DEF:%[0-9]+]].sub1:sreg_64 = COPY undef [[UND:%[0-9]+]]:sgpr_32
; CHECK-NEXT: [[OTH:%[0-9]+]]:vgpr_32 = V_MOV_B32_e32 [[DEF]].sub1
; LIS-LABEL: name: regsequence-undef-subreg-use
; LIS: [[COPY:%[0-9]+]]:sgpr_32 = S_MOV_B32 0, implicit $exec
; LIS-NEXT: undef [[DEF:%[0-9]+]].sub0:sreg_64 = COPY [[COPY]]
; LIS-NEXT: [[OTH:%[0-9]+]]:vgpr_32 = V_MOV_B32_e32 undef [[DEF]].sub1
%0:sgpr_32 = S_MOV_B32 0, implicit $exec
%1:sreg_64 = REG_SEQUENCE %0, %subreg.sub0, undef %2:sgpr_32, %subreg.sub1
%3:vgpr_32 = V_MOV_B32_e32 %1.sub1, implicit $exec
...
---
name: regsequence-undef-subreg-without-use
noPhis: true
body: |
bb.0:
; CHECK-LABEL: name: regsequence-undef-subreg-without-use
; CHECK: [[COPY:%[0-9]+]]:sgpr_32 = S_MOV_B32 0, implicit $exec
; CHECK-NEXT: undef [[DEF:%[0-9]+]].sub0:sreg_64 = COPY [[COPY]]
; LIS-LABEL: name: regsequence-undef-subreg-without-use
; LIS: [[COPY:%[0-9]+]]:sgpr_32 = S_MOV_B32 0, implicit $exec
; LIS-NEXT: undef [[DEF:%[0-9]+]].sub0:sreg_64 = COPY [[COPY]]
%0:sgpr_32 = S_MOV_B32 0, implicit $exec
%1:sreg_64 = REG_SEQUENCE %0, %subreg.sub0, undef %2:sgpr_32, %subreg.sub1
...
---
name: regsequence-undef-subreg-full-reg-use
noPhis: true
body: |
bb.0:
; CHECK-LABEL: name: regsequence-undef-subreg-full-reg-use
; CHECK: [[COPY:%[0-9]+]]:sgpr_32 = S_MOV_B32 0, implicit $exec
; CHECK-NEXT: undef [[DEF:%[0-9]+]].sub0:sreg_64 = COPY [[COPY]]
; CHECK-NEXT: [[OTH:%[0-9]+]]:vreg_64 = COPY [[DEF]], implicit $exec
; LIS-LABEL: name: regsequence-undef-subreg-full-reg-use
; LIS: [[COPY:%[0-9]+]]:sgpr_32 = S_MOV_B32 0, implicit $exec
; LIS-NEXT: undef [[DEF:%[0-9]+]].sub0:sreg_64 = COPY [[COPY]]
; LIS-NEXT: [[OTH:%[0-9]+]]:vreg_64 = COPY [[DEF]], implicit $exec
%0:sgpr_32 = S_MOV_B32 0, implicit $exec
%1:sreg_64 = REG_SEQUENCE %0, %subreg.sub0, undef %2:sgpr_32, %subreg.sub1
%3:vreg_64 = COPY %1, implicit $exec
...