aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/CodeGen/TwoAddressInstructionPass.cpp
diff options
context:
space:
mode:
authorCarl Ritson <carl.ritson@amd.com>2024-02-07 16:46:00 +0900
committerGitHub <noreply@github.com>2024-02-07 16:46:00 +0900
commit9bda1de0b6096d26e87fed18cb681cc3e5b8319a (patch)
treeda4f16feb6363ccd0b85ffb5fd97e930291c6059 /llvm/lib/CodeGen/TwoAddressInstructionPass.cpp
parentea4f44e85f7ca884d42b9b12bd13bab47c3e5d3c (diff)
downloadllvm-9bda1de0b6096d26e87fed18cb681cc3e5b8319a.zip
llvm-9bda1de0b6096d26e87fed18cb681cc3e5b8319a.tar.gz
llvm-9bda1de0b6096d26e87fed18cb681cc3e5b8319a.tar.bz2
[TwoAddressInstruction] Propagate undef flags for partial defs (#79286)
If part of a register (lowered from REG_SEQUENCE) is undefined then we should propagate undef flags to uses of those lanes. This is only performed when live intervals are present as it requires live intervals to correctly match uses to defs, and the primary goal is to allow precise computation of subrange intervals.
Diffstat (limited to 'llvm/lib/CodeGen/TwoAddressInstructionPass.cpp')
-rw-r--r--llvm/lib/CodeGen/TwoAddressInstructionPass.cpp32
1 files changed, 26 insertions, 6 deletions
diff --git a/llvm/lib/CodeGen/TwoAddressInstructionPass.cpp b/llvm/lib/CodeGen/TwoAddressInstructionPass.cpp
index 74d7904..ebacbc4 100644
--- a/llvm/lib/CodeGen/TwoAddressInstructionPass.cpp
+++ b/llvm/lib/CodeGen/TwoAddressInstructionPass.cpp
@@ -1929,21 +1929,27 @@ eliminateRegSequence(MachineBasicBlock::iterator &MBBI) {
Register DstReg = MI.getOperand(0).getReg();
SmallVector<Register, 4> OrigRegs;
+ VNInfo *DefVN = nullptr;
if (LIS) {
OrigRegs.push_back(MI.getOperand(0).getReg());
for (unsigned i = 1, e = MI.getNumOperands(); i < e; i += 2)
OrigRegs.push_back(MI.getOperand(i).getReg());
+ if (LIS->hasInterval(DstReg)) {
+ DefVN = LIS->getInterval(DstReg)
+ .Query(LIS->getInstructionIndex(MI))
+ .valueOut();
+ }
}
+ LaneBitmask UndefLanes = LaneBitmask::getNone();
bool DefEmitted = false;
- bool DefIsPartial = false;
for (unsigned i = 1, e = MI.getNumOperands(); i < e; i += 2) {
MachineOperand &UseMO = MI.getOperand(i);
Register SrcReg = UseMO.getReg();
unsigned SubIdx = MI.getOperand(i+1).getImm();
// Nothing needs to be inserted for undef operands.
if (UseMO.isUndef()) {
- DefIsPartial = true;
+ UndefLanes |= TRI->getSubRegIndexLaneMask(SubIdx);
continue;
}
@@ -1991,11 +1997,25 @@ eliminateRegSequence(MachineBasicBlock::iterator &MBBI) {
MI.removeOperand(j);
} else {
if (LIS) {
- // Force interval recomputation if we moved from full definition
- // of register to partial.
- if (DefIsPartial && LIS->hasInterval(DstReg) &&
- MRI->shouldTrackSubRegLiveness(DstReg))
+ // Force live interval recomputation if we moved to a partial definition
+ // of the register. Undef flags must be propagate to uses of undefined
+ // subregister for accurate interval computation.
+ if (UndefLanes.any() && DefVN && MRI->shouldTrackSubRegLiveness(DstReg)) {
+ auto &LI = LIS->getInterval(DstReg);
+ for (MachineOperand &UseOp : MRI->use_operands(DstReg)) {
+ unsigned SubReg = UseOp.getSubReg();
+ if (UseOp.isUndef() || !SubReg)
+ continue;
+ auto *VN =
+ LI.getVNInfoAt(LIS->getInstructionIndex(*UseOp.getParent()));
+ if (DefVN != VN)
+ continue;
+ LaneBitmask LaneMask = TRI->getSubRegIndexLaneMask(SubReg);
+ if ((UndefLanes & LaneMask).any())
+ UseOp.setIsUndef(true);
+ }
LIS->removeInterval(DstReg);
+ }
LIS->RemoveMachineInstrFromMaps(MI);
}