Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
140 changes: 71 additions & 69 deletions llvm/lib/Target/AMDGPU/SIInstrInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4044,28 +4044,31 @@ static unsigned getNewFMAInst(const GCNSubtarget &ST, unsigned Opc) {
}
}

/// Helper struct for the implementation of 3-address conversion to communicate
/// updates made to instruction operands.
struct SIInstrInfo::ThreeAddressUpdates {
/// Other instruction whose def is no longer used by the converted
/// instruction.
MachineInstr *RemoveMIUse = nullptr;
};

MachineInstr *SIInstrInfo::convertToThreeAddress(MachineInstr &MI,
LiveVariables *LV,
LiveIntervals *LIS) const {
MachineBasicBlock &MBB = *MI.getParent();
unsigned Opc = MI.getOpcode();
ThreeAddressUpdates U;
MachineInstr *NewMI = convertToThreeAddressImpl(MI, U);

// Handle MFMA.
int NewMFMAOpc = AMDGPU::getMFMAEarlyClobberOp(Opc);
if (NewMFMAOpc != -1) {
MachineInstrBuilder MIB =
BuildMI(MBB, MI, MI.getDebugLoc(), get(NewMFMAOpc));
for (unsigned I = 0, E = MI.getNumOperands(); I != E; ++I)
MIB.add(MI.getOperand(I));
updateLiveVariables(LV, MI, *MIB);
if (NewMI) {
updateLiveVariables(LV, MI, *NewMI);
if (LIS) {
LIS->ReplaceMachineInstrInMaps(MI, *MIB);
LIS->ReplaceMachineInstrInMaps(MI, *NewMI);
// SlotIndex of defs needs to be updated when converting to early-clobber
MachineOperand &Def = MIB->getOperand(0);
MachineOperand &Def = NewMI->getOperand(0);
if (Def.isEarlyClobber() && Def.isReg() &&
LIS->hasInterval(Def.getReg())) {
SlotIndex OldIndex = LIS->getInstructionIndex(*MIB).getRegSlot(false);
SlotIndex NewIndex = LIS->getInstructionIndex(*MIB).getRegSlot(true);
SlotIndex OldIndex = LIS->getInstructionIndex(*NewMI).getRegSlot(false);
SlotIndex NewIndex = LIS->getInstructionIndex(*NewMI).getRegSlot(true);
auto &LI = LIS->getInterval(Def.getReg());
auto UpdateDefIndex = [&](LiveRange &LR) {
auto *S = LR.find(OldIndex);
Expand All @@ -4080,6 +4083,58 @@ MachineInstr *SIInstrInfo::convertToThreeAddress(MachineInstr &MI,
UpdateDefIndex(SR);
}
}
}

if (U.RemoveMIUse) {
MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
// The only user is the instruction which will be killed.
Register DefReg = U.RemoveMIUse->getOperand(0).getReg();

if (MRI.hasOneNonDBGUse(DefReg)) {
// We cannot just remove the DefMI here, calling pass will crash.
U.RemoveMIUse->setDesc(get(AMDGPU::IMPLICIT_DEF));
U.RemoveMIUse->getOperand(0).setIsDead(true);
for (unsigned I = U.RemoveMIUse->getNumOperands() - 1; I != 0; --I)
U.RemoveMIUse->removeOperand(I);
if (LV)
LV->getVarInfo(DefReg).AliveBlocks.clear();
}

if (LIS) {
LiveInterval &DefLI = LIS->getInterval(DefReg);

// We cannot delete the original instruction here, so hack out the use
// in the original instruction with a dummy register so we can use
// shrinkToUses to deal with any multi-use edge cases. Other targets do
// not have the complexity of deleting a use to consider here.
Register DummyReg = MRI.cloneVirtualRegister(DefReg);
for (MachineOperand &MIOp : MI.uses()) {
if (MIOp.isReg() && MIOp.getReg() == DefReg) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Preexisting, but this looks broken for subregisters

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree this looks dodgy, but it turns out to be fine because it only mutates the old, 2-address instruction that is erased almost immediately afterwards anyway.

CodeGen/AMDGPU/gfx10-twoaddr-fma.mir hits the case where this is a subregister use.

MIOp.setIsUndef(true);
MIOp.setReg(DummyReg);
}
}

LIS->shrinkToUses(&DefLI);
}
}

return NewMI;
}

MachineInstr *
SIInstrInfo::convertToThreeAddressImpl(MachineInstr &MI,
ThreeAddressUpdates &U) const {
MachineBasicBlock &MBB = *MI.getParent();
unsigned Opc = MI.getOpcode();

// Handle MFMA.
int NewMFMAOpc = AMDGPU::getMFMAEarlyClobberOp(Opc);
if (NewMFMAOpc != -1) {
MachineInstrBuilder MIB =
BuildMI(MBB, MI, MI.getDebugLoc(), get(NewMFMAOpc));
for (unsigned I = 0, E = MI.getNumOperands(); I != E; ++I)
MIB.add(MI.getOperand(I));
return MIB;
}

Expand All @@ -4089,11 +4144,6 @@ MachineInstr *SIInstrInfo::convertToThreeAddress(MachineInstr &MI,
.setMIFlags(MI.getFlags());
for (unsigned I = 0, E = MI.getNumOperands(); I != E; ++I)
MIB->addOperand(MI.getOperand(I));

updateLiveVariables(LV, MI, *MIB);
if (LIS)
LIS->ReplaceMachineInstrInMaps(MI, *MIB);

return MIB;
}

Expand Down Expand Up @@ -4164,39 +4214,6 @@ MachineInstr *SIInstrInfo::convertToThreeAddress(MachineInstr &MI,
(ST.getConstantBusLimit(Opc) > 1 || !Src0->isReg() ||
!RI.isSGPRReg(MBB.getParent()->getRegInfo(), Src0->getReg()))) {
MachineInstr *DefMI;
const auto killDef = [&]() -> void {
MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
// The only user is the instruction which will be killed.
Register DefReg = DefMI->getOperand(0).getReg();

if (MRI.hasOneNonDBGUse(DefReg)) {
// We cannot just remove the DefMI here, calling pass will crash.
DefMI->setDesc(get(AMDGPU::IMPLICIT_DEF));
DefMI->getOperand(0).setIsDead(true);
for (unsigned I = DefMI->getNumOperands() - 1; I != 0; --I)
DefMI->removeOperand(I);
if (LV)
LV->getVarInfo(DefReg).AliveBlocks.clear();
}

if (LIS) {
LiveInterval &DefLI = LIS->getInterval(DefReg);

// We cannot delete the original instruction here, so hack out the use
// in the original instruction with a dummy register so we can use
// shrinkToUses to deal with any multi-use edge cases. Other targets do
// not have the complexity of deleting a use to consider here.
Register DummyReg = MRI.cloneVirtualRegister(DefReg);
for (MachineOperand &MIOp : MI.uses()) {
if (MIOp.isReg() && MIOp.getReg() == DefReg) {
MIOp.setIsUndef(true);
MIOp.setReg(DummyReg);
}
}

LIS->shrinkToUses(&DefLI);
}
};

int64_t Imm;
if (!Src0Literal && getFoldableImm(Src2, Imm, &DefMI)) {
Expand All @@ -4208,10 +4225,7 @@ MachineInstr *SIInstrInfo::convertToThreeAddress(MachineInstr &MI,
.add(*Src1)
.addImm(Imm)
.setMIFlags(MI.getFlags());
updateLiveVariables(LV, MI, *MIB);
if (LIS)
LIS->ReplaceMachineInstrInMaps(MI, *MIB);
killDef();
U.RemoveMIUse = DefMI;
return MIB;
}
}
Expand All @@ -4224,11 +4238,7 @@ MachineInstr *SIInstrInfo::convertToThreeAddress(MachineInstr &MI,
.addImm(Imm)
.add(*Src2)
.setMIFlags(MI.getFlags());
updateLiveVariables(LV, MI, *MIB);

if (LIS)
LIS->ReplaceMachineInstrInMaps(MI, *MIB);
killDef();
U.RemoveMIUse = DefMI;
return MIB;
}
}
Expand All @@ -4247,12 +4257,7 @@ MachineInstr *SIInstrInfo::convertToThreeAddress(MachineInstr &MI,
.addImm(Imm)
.add(*Src2)
.setMIFlags(MI.getFlags());
updateLiveVariables(LV, MI, *MIB);

if (LIS)
LIS->ReplaceMachineInstrInMaps(MI, *MIB);
if (DefMI)
killDef();
U.RemoveMIUse = DefMI;
return MIB;
}
}
Expand Down Expand Up @@ -4281,9 +4286,6 @@ MachineInstr *SIInstrInfo::convertToThreeAddress(MachineInstr &MI,
.setMIFlags(MI.getFlags());
if (AMDGPU::hasNamedOperand(NewOpc, AMDGPU::OpName::op_sel))
MIB.addImm(OpSel ? OpSel->getImm() : 0);
updateLiveVariables(LV, MI, *MIB);
if (LIS)
LIS->ReplaceMachineInstrInMaps(MI, *MIB);
return MIB;
}

Expand Down
5 changes: 5 additions & 0 deletions llvm/lib/Target/AMDGPU/SIInstrInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ struct SIInstrWorklist {
};

class SIInstrInfo final : public AMDGPUGenInstrInfo {
struct ThreeAddressUpdates;

private:
const SIRegisterInfo RI;
const GCNSubtarget &ST;
Expand Down Expand Up @@ -190,6 +192,9 @@ class SIInstrInfo final : public AMDGPUGenInstrInfo {

bool resultDependsOnExec(const MachineInstr &MI) const;

MachineInstr *convertToThreeAddressImpl(MachineInstr &MI,
ThreeAddressUpdates &Updates) const;

protected:
/// If the specific machine instruction is a instruction that moves/copies
/// value from one register to another register return destination and source
Expand Down