Skip to content

[TableGen] Combine the two separate OperandMapping loops in PseudoLoweringEmitter. #136007

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 3 commits into from
Apr 16, 2025
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
194 changes: 98 additions & 96 deletions llvm/utils/TableGen/PseudoLoweringEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,11 @@ class PseudoLoweringEmitter {

SmallVector<PseudoExpansion, 64> Expansions;

unsigned addDagOperandMapping(const Record *Rec, const DagInit *Dag,
const CodeGenInstruction &Insn,
IndexedMap<OpData> &OperandMap,
unsigned BaseIdx);
void addOperandMapping(unsigned MIOpNo, unsigned NumOps, const Record *Rec,
const DagInit *Dag, unsigned DagIdx,
const Record *OpRec, IndexedMap<OpData> &OperandMap,
const StringMap<unsigned> &SourceOperands,
const CodeGenInstruction &SourceInsn);
void evaluateExpansion(const Record *Pseudo);
void emitLoweringEmitter(raw_ostream &o);

Expand All @@ -66,64 +67,67 @@ class PseudoLoweringEmitter {
};
} // End anonymous namespace

// FIXME: This pass currently can only expand a pseudo to a single instruction.
// The pseudo expansion really should take a list of dags, not just
// a single dag, so we can do fancier things.
unsigned PseudoLoweringEmitter::addDagOperandMapping(
const Record *Rec, const DagInit *Dag, const CodeGenInstruction &Insn,
IndexedMap<OpData> &OperandMap, unsigned BaseIdx) {
unsigned OpsAdded = 0;
for (unsigned i = 0, e = Dag->getNumArgs(); i != e; ++i) {
if (const DefInit *DI = dyn_cast<DefInit>(Dag->getArg(i))) {
// Physical register reference. Explicit check for the special case
// "zero_reg" definition.
if (DI->getDef()->isSubClassOf("Register") ||
DI->getDef()->getName() == "zero_reg") {
auto &Entry = OperandMap[BaseIdx + i];
Entry.Kind = OpData::Reg;
Entry.Data.Reg = DI->getDef();
++OpsAdded;
continue;
}
void PseudoLoweringEmitter::addOperandMapping(
unsigned MIOpNo, unsigned NumOps, const Record *Rec, const DagInit *Dag,
unsigned DagIdx, const Record *OpRec, IndexedMap<OpData> &OperandMap,
const StringMap<unsigned> &SourceOperands,
const CodeGenInstruction &SourceInsn) {
const Init *DagArg = Dag->getArg(DagIdx);
if (const DefInit *DI = dyn_cast<DefInit>(DagArg)) {
// Physical register reference. Explicit check for the special case
// "zero_reg" definition.
if (DI->getDef()->isSubClassOf("Register") ||
DI->getDef()->getName() == "zero_reg") {
auto &Entry = OperandMap[MIOpNo];
Entry.Kind = OpData::Reg;
Entry.Data.Reg = DI->getDef();
return;
}

// Normal operands should always have the same type, or we have a
// problem.
// FIXME: We probably shouldn't ever get a non-zero BaseIdx here.
assert(BaseIdx == 0 && "Named subargument in pseudo expansion?!");
if (DI->getDef() != Insn.Operands[BaseIdx + i].Rec)
PrintFatalError(Rec, "In pseudo instruction '" + Rec->getName() +
"', operand type '" + DI->getDef()->getName() +
"' does not match expansion operand type '" +
Insn.Operands[BaseIdx + i].Rec->getName() +
"'");
// Source operand maps to destination operand. The Data element
// will be filled in later, just set the Kind for now. Do it
// for each corresponding MachineInstr operand, not just the first.
for (unsigned I = 0, E = Insn.Operands[i].MINumOperands; I != E; ++I)
OperandMap[BaseIdx + i + I].Kind = OpData::Operand;
OpsAdded += Insn.Operands[i].MINumOperands;
} else if (const IntInit *II = dyn_cast<IntInit>(Dag->getArg(i))) {
auto &Entry = OperandMap[BaseIdx + i];
Entry.Kind = OpData::Imm;
Entry.Data.Imm = II->getValue();
++OpsAdded;
} else if (const auto *BI = dyn_cast<BitsInit>(Dag->getArg(i))) {
auto &Entry = OperandMap[BaseIdx + i];
Entry.Kind = OpData::Imm;
Entry.Data.Imm = *BI->convertInitializerToInt();
++OpsAdded;
} else if (const DagInit *SubDag = dyn_cast<DagInit>(Dag->getArg(i))) {
// Just add the operands recursively. This is almost certainly
// a constant value for a complex operand (> 1 MI operand).
unsigned NewOps =
addDagOperandMapping(Rec, SubDag, Insn, OperandMap, BaseIdx + i);
OpsAdded += NewOps;
// Since we added more than one, we also need to adjust the base.
BaseIdx += NewOps - 1;
} else
llvm_unreachable("Unhandled pseudo-expansion argument type!");
}
return OpsAdded;
if (DI->getDef() != OpRec)
PrintFatalError(Rec, "In pseudo instruction '" + Rec->getName() +
"', operand type '" + DI->getDef()->getName() +
"' does not match expansion operand type '" +
OpRec->getName() + "'");

StringMap<unsigned>::const_iterator SourceOp =
SourceOperands.find(Dag->getArgNameStr(DagIdx));
if (SourceOp == SourceOperands.end())
PrintFatalError(Rec, "In pseudo instruction '" + Rec->getName() +
"', output operand '" +
Dag->getArgNameStr(DagIdx) +
"' has no matching source operand");
const auto &SrcOpnd = SourceInsn.Operands[SourceOp->getValue()];
if (NumOps != SrcOpnd.MINumOperands)
PrintFatalError(
Rec,
"In pseudo instruction '" + Rec->getName() + "', output operand '" +
OpRec->getName() +
"' has a different number of sub operands than source operand '" +
SrcOpnd.Rec->getName() + "'");

// Source operand maps to destination operand. Do it for each corresponding
// MachineInstr operand, not just the first.
for (unsigned I = 0, E = NumOps; I != E; ++I) {
auto &Entry = OperandMap[MIOpNo + I];
Entry.Kind = OpData::Operand;
Entry.Data.Operand = SrcOpnd.MIOperandNo + I;
}

LLVM_DEBUG(dbgs() << " " << SourceOp->getValue() << " ==> " << DagIdx
<< "\n");
} else if (const auto *II = dyn_cast<IntInit>(DagArg)) {
assert(NumOps == 1);
auto &Entry = OperandMap[MIOpNo];
Entry.Kind = OpData::Imm;
Entry.Data.Imm = II->getValue();
} else if (const auto *BI = dyn_cast<BitsInit>(DagArg)) {
assert(NumOps == 1);
auto &Entry = OperandMap[MIOpNo];
Entry.Kind = OpData::Imm;
Entry.Data.Imm = *BI->convertInitializerToInt();
} else
llvm_unreachable("Unhandled pseudo-expansion argument type!");
}

void PseudoLoweringEmitter::evaluateExpansion(const Record *Rec) {
Expand Down Expand Up @@ -157,14 +161,6 @@ void PseudoLoweringEmitter::evaluateExpansion(const Record *Rec) {
"', result operator '" + Operator->getName() +
"' has the wrong number of operands");

unsigned NumMIOperands = 0;
for (const auto &Op : Insn.Operands)
NumMIOperands += Op.MINumOperands;
IndexedMap<OpData> OperandMap;
OperandMap.grow(NumMIOperands);

addDagOperandMapping(Rec, Dag, Insn, OperandMap, 0);

// If there are more operands that weren't in the DAG, they have to
// be operands that have default values, or we have an error. Currently,
// Operands that are a subclass of OperandWithDefaultOp have default values.
Expand All @@ -180,37 +176,43 @@ void PseudoLoweringEmitter::evaluateExpansion(const Record *Rec) {
for (const auto &[Idx, SrcOp] : enumerate(SourceInsn.Operands))
SourceOperands[SrcOp.Name] = Idx;

LLVM_DEBUG(dbgs() << " Operand mapping:\n");
for (const auto &[Idx, Opnd] : enumerate(Insn.Operands)) {
// We've already handled constant values. Just map instruction operands
// here.
if (OperandMap[Opnd.MIOperandNo].Kind != OpData::Operand)
continue;
StringMap<unsigned>::iterator SourceOp =
SourceOperands.find(Dag->getArgNameStr(Idx));
if (SourceOp == SourceOperands.end())
PrintFatalError(Rec, "In pseudo instruction '" + Rec->getName() +
"', output operand '" + Dag->getArgNameStr(Idx) +
"' has no matching source operand");
const auto &SrcOpnd = SourceInsn.Operands[SourceOp->getValue()];
if (Opnd.MINumOperands != SrcOpnd.MINumOperands)
PrintFatalError(
Rec,
"In pseudo instruction '" + Rec->getName() + "', output operand '" +
Opnd.Rec->getName() +
"' has a different number of sub operands than source operand '" +
SrcOpnd.Rec->getName() + "'");
unsigned NumMIOperands = 0;
for (const auto &Op : Insn.Operands)
NumMIOperands += Op.MINumOperands;
IndexedMap<OpData> OperandMap;
OperandMap.grow(NumMIOperands);

// Map the source operand to the destination operand index for each
// MachineInstr operand.
for (unsigned I = 0, E = Opnd.MINumOperands; I != E; ++I)
OperandMap[Opnd.MIOperandNo + I].Data.Operand = SrcOpnd.MIOperandNo + I;
// FIXME: This pass currently can only expand a pseudo to a single
// instruction. The pseudo expansion really should take a list of dags, not
// just a single dag, so we can do fancier things.
LLVM_DEBUG(dbgs() << " Operand mapping:\n");
for (const auto &[Idx, DstOp] : enumerate(Insn.Operands)) {
unsigned MIOpNo = DstOp.MIOperandNo;

LLVM_DEBUG(dbgs() << " " << SourceOp->getValue() << " ==> " << Idx
<< "\n");
if (const auto *SubDag = dyn_cast<DagInit>(Dag->getArg(Idx))) {
if (!DstOp.MIOperandInfo || DstOp.MIOperandInfo->getNumArgs() == 0)
PrintFatalError(Rec, "In pseudo instruction '" + Rec->getName() +
"', operand '" + DstOp.Rec->getName() +
"' does not have suboperands");
if (DstOp.MINumOperands != SubDag->getNumArgs()) {
PrintFatalError(
Rec, "In pseudo instruction '" + Rec->getName() + "', '" +
SubDag->getAsString() +
"' has wrong number of operands for operand type '" +
DstOp.Rec->getName() + "'");
}
for (unsigned I = 0, E = DstOp.MINumOperands; I != E; ++I) {
auto *OpndRec = cast<DefInit>(DstOp.MIOperandInfo->getArg(I))->getDef();
addOperandMapping(MIOpNo + I, 1, Rec, SubDag, I, OpndRec, OperandMap,
SourceOperands, SourceInsn);
}
} else {
addOperandMapping(MIOpNo, DstOp.MINumOperands, Rec, Dag, Idx, DstOp.Rec,
OperandMap, SourceOperands, SourceInsn);
}
}

Expansions.push_back(PseudoExpansion(SourceInsn, Insn, OperandMap));
Expansions.emplace_back(SourceInsn, Insn, OperandMap);
}

void PseudoLoweringEmitter::emitLoweringEmitter(raw_ostream &o) {
Expand Down
Loading