Skip to content

AMDGPU: Generalize instruction shrinking code #93810

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 30, 2024
Merged
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
56 changes: 28 additions & 28 deletions llvm/lib/Target/AMDGPU/SIInstrInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4486,46 +4486,46 @@ static void copyFlagsToImplicitVCC(MachineInstr &MI,
MachineInstr *SIInstrInfo::buildShrunkInst(MachineInstr &MI,
unsigned Op32) const {
MachineBasicBlock *MBB = MI.getParent();

const MCInstrDesc &Op32Desc = get(Op32);
MachineInstrBuilder Inst32 =
BuildMI(*MBB, MI, MI.getDebugLoc(), get(Op32))
BuildMI(*MBB, MI, MI.getDebugLoc(), Op32Desc)
.setMIFlags(MI.getFlags());

// Add the dst operand if the 32-bit encoding also has an explicit $vdst.
// For VOPC instructions, this is replaced by an implicit def of vcc.
if (AMDGPU::hasNamedOperand(Op32, AMDGPU::OpName::vdst)) {
// dst
Inst32.add(MI.getOperand(0));
} else if (AMDGPU::hasNamedOperand(Op32, AMDGPU::OpName::sdst)) {
// VOPCX instructions won't be writing to an explicit dst, so this should
// not fail for these instructions.
assert(((MI.getOperand(0).getReg() == AMDGPU::VCC) ||
(MI.getOperand(0).getReg() == AMDGPU::VCC_LO)) &&
"Unexpected case");
}

Inst32.add(*getNamedOperand(MI, AMDGPU::OpName::src0));

const MachineOperand *Src1 = getNamedOperand(MI, AMDGPU::OpName::src1);
if (Src1)
Inst32.add(*Src1);
// We assume the defs of the shrunk opcode are in the same order, and the
// shrunk opcode loses the last def (SGPR def, in the VOP3->VOPC case).
for (int I = 0, E = Op32Desc.getNumDefs(); I != E; ++I)
Inst32.add(MI.getOperand(I));

const MachineOperand *Src2 = getNamedOperand(MI, AMDGPU::OpName::src2);

if (Src2) {
int Op32Src2Idx = AMDGPU::getNamedOperandIdx(Op32, AMDGPU::OpName::src2);
if (Op32Src2Idx != -1) {
Inst32.add(*Src2);
} else {
// In the case of V_CNDMASK_B32_e32, the explicit operand src2 is
// replaced with an implicit read of vcc or vcc_lo. The implicit read
// of vcc was already added during the initial BuildMI, but we
// 1) may need to change vcc to vcc_lo to preserve the original register
// 2) have to preserve the original flags.
fixImplicitOperands(*Inst32);
copyFlagsToImplicitVCC(*Inst32, *Src2);
int Idx = MI.getNumExplicitDefs();
for (const MachineOperand &Use : MI.explicit_uses()) {
int OpTy = MI.getDesc().operands()[Idx++].OperandType;
if (OpTy == AMDGPU::OPERAND_INPUT_MODS || OpTy == MCOI::OPERAND_IMMEDIATE)
Copy link
Contributor

Choose a reason for hiding this comment

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

What cases does OPERAND_IMMEDIATE cover? Does this mean we don't copy any immediate operands, and if so why not?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's the default case for custom operands. The most common cases are clamp and omod

continue;

if (&Use == Src2) {
if (AMDGPU::getNamedOperandIdx(Op32, AMDGPU::OpName::src2) == -1) {
// In the case of V_CNDMASK_B32_e32, the explicit operand src2 is
// replaced with an implicit read of vcc or vcc_lo. The implicit read
// of vcc was already added during the initial BuildMI, but we
// 1) may need to change vcc to vcc_lo to preserve the original register
// 2) have to preserve the original flags.
fixImplicitOperands(*Inst32);
copyFlagsToImplicitVCC(*Inst32, *Src2);
continue;
}
}

Inst32.add(Use);
}

// FIXME: Losing implicit operands

return Inst32;
}

Expand Down
Loading