Skip to content

Commit b9f1de0

Browse files
authored
[TableGen] Combine the two separate OperandMapping loops in PseudoLoweringEmitter. (#136007)
Previously we had one loop over the DAG for immediates and registers and another loop over the destination operands for mapping from the source. Now we have a single loop over the destination operands that handles immediates, registers, and named operands. A helper method is added so we can handle operands and sub-operands specified by a sub-dag. My goal is to allow a named operand to appear in a sub-dag which wasn't supported before. This will allow the destination instruction to have an operand with sub-operands when the source does not have sub operands. For RISC-V, I'm looking into using an operand with sub-operands to represent an reg+offset memory address. I need to be able to lower a pseudo instruction that only has a register operand to an instruction that has a reg+offset operand. The offset will be filled in with 0 during expansion and the register will be copied from the source. The expansion would look like this: def PseudoCALLIndirect : Pseudo<(outs), (ins GPRJALR:$rs1), [(riscv_call GPRJALR:$rs1)]>, PseudoInstExpansion<(JALR X1, (ops GPR:$rs1, 0))>;
1 parent d35bf17 commit b9f1de0

File tree

1 file changed

+98
-96
lines changed

1 file changed

+98
-96
lines changed

llvm/utils/TableGen/PseudoLoweringEmitter.cpp

Lines changed: 98 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,11 @@ class PseudoLoweringEmitter {
5151

5252
SmallVector<PseudoExpansion, 64> Expansions;
5353

54-
unsigned addDagOperandMapping(const Record *Rec, const DagInit *Dag,
55-
const CodeGenInstruction &Insn,
56-
IndexedMap<OpData> &OperandMap,
57-
unsigned BaseIdx);
54+
void addOperandMapping(unsigned MIOpNo, unsigned NumOps, const Record *Rec,
55+
const DagInit *Dag, unsigned DagIdx,
56+
const Record *OpRec, IndexedMap<OpData> &OperandMap,
57+
const StringMap<unsigned> &SourceOperands,
58+
const CodeGenInstruction &SourceInsn);
5859
void evaluateExpansion(const Record *Pseudo);
5960
void emitLoweringEmitter(raw_ostream &o);
6061

@@ -66,64 +67,67 @@ class PseudoLoweringEmitter {
6667
};
6768
} // End anonymous namespace
6869

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

89-
// Normal operands should always have the same type, or we have a
90-
// problem.
91-
// FIXME: We probably shouldn't ever get a non-zero BaseIdx here.
92-
assert(BaseIdx == 0 && "Named subargument in pseudo expansion?!");
93-
if (DI->getDef() != Insn.Operands[BaseIdx + i].Rec)
94-
PrintFatalError(Rec, "In pseudo instruction '" + Rec->getName() +
95-
"', operand type '" + DI->getDef()->getName() +
96-
"' does not match expansion operand type '" +
97-
Insn.Operands[BaseIdx + i].Rec->getName() +
98-
"'");
99-
// Source operand maps to destination operand. The Data element
100-
// will be filled in later, just set the Kind for now. Do it
101-
// for each corresponding MachineInstr operand, not just the first.
102-
for (unsigned I = 0, E = Insn.Operands[i].MINumOperands; I != E; ++I)
103-
OperandMap[BaseIdx + i + I].Kind = OpData::Operand;
104-
OpsAdded += Insn.Operands[i].MINumOperands;
105-
} else if (const IntInit *II = dyn_cast<IntInit>(Dag->getArg(i))) {
106-
auto &Entry = OperandMap[BaseIdx + i];
107-
Entry.Kind = OpData::Imm;
108-
Entry.Data.Imm = II->getValue();
109-
++OpsAdded;
110-
} else if (const auto *BI = dyn_cast<BitsInit>(Dag->getArg(i))) {
111-
auto &Entry = OperandMap[BaseIdx + i];
112-
Entry.Kind = OpData::Imm;
113-
Entry.Data.Imm = *BI->convertInitializerToInt();
114-
++OpsAdded;
115-
} else if (const DagInit *SubDag = dyn_cast<DagInit>(Dag->getArg(i))) {
116-
// Just add the operands recursively. This is almost certainly
117-
// a constant value for a complex operand (> 1 MI operand).
118-
unsigned NewOps =
119-
addDagOperandMapping(Rec, SubDag, Insn, OperandMap, BaseIdx + i);
120-
OpsAdded += NewOps;
121-
// Since we added more than one, we also need to adjust the base.
122-
BaseIdx += NewOps - 1;
123-
} else
124-
llvm_unreachable("Unhandled pseudo-expansion argument type!");
125-
}
126-
return OpsAdded;
87+
if (DI->getDef() != OpRec)
88+
PrintFatalError(Rec, "In pseudo instruction '" + Rec->getName() +
89+
"', operand type '" + DI->getDef()->getName() +
90+
"' does not match expansion operand type '" +
91+
OpRec->getName() + "'");
92+
93+
StringMap<unsigned>::const_iterator SourceOp =
94+
SourceOperands.find(Dag->getArgNameStr(DagIdx));
95+
if (SourceOp == SourceOperands.end())
96+
PrintFatalError(Rec, "In pseudo instruction '" + Rec->getName() +
97+
"', output operand '" +
98+
Dag->getArgNameStr(DagIdx) +
99+
"' has no matching source operand");
100+
const auto &SrcOpnd = SourceInsn.Operands[SourceOp->getValue()];
101+
if (NumOps != SrcOpnd.MINumOperands)
102+
PrintFatalError(
103+
Rec,
104+
"In pseudo instruction '" + Rec->getName() + "', output operand '" +
105+
OpRec->getName() +
106+
"' has a different number of sub operands than source operand '" +
107+
SrcOpnd.Rec->getName() + "'");
108+
109+
// Source operand maps to destination operand. Do it for each corresponding
110+
// MachineInstr operand, not just the first.
111+
for (unsigned I = 0, E = NumOps; I != E; ++I) {
112+
auto &Entry = OperandMap[MIOpNo + I];
113+
Entry.Kind = OpData::Operand;
114+
Entry.Data.Operand = SrcOpnd.MIOperandNo + I;
115+
}
116+
117+
LLVM_DEBUG(dbgs() << " " << SourceOp->getValue() << " ==> " << DagIdx
118+
<< "\n");
119+
} else if (const auto *II = dyn_cast<IntInit>(DagArg)) {
120+
assert(NumOps == 1);
121+
auto &Entry = OperandMap[MIOpNo];
122+
Entry.Kind = OpData::Imm;
123+
Entry.Data.Imm = II->getValue();
124+
} else if (const auto *BI = dyn_cast<BitsInit>(DagArg)) {
125+
assert(NumOps == 1);
126+
auto &Entry = OperandMap[MIOpNo];
127+
Entry.Kind = OpData::Imm;
128+
Entry.Data.Imm = *BI->convertInitializerToInt();
129+
} else
130+
llvm_unreachable("Unhandled pseudo-expansion argument type!");
127131
}
128132

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

160-
unsigned NumMIOperands = 0;
161-
for (const auto &Op : Insn.Operands)
162-
NumMIOperands += Op.MINumOperands;
163-
IndexedMap<OpData> OperandMap;
164-
OperandMap.grow(NumMIOperands);
165-
166-
addDagOperandMapping(Rec, Dag, Insn, OperandMap, 0);
167-
168164
// If there are more operands that weren't in the DAG, they have to
169165
// be operands that have default values, or we have an error. Currently,
170166
// Operands that are a subclass of OperandWithDefaultOp have default values.
@@ -180,37 +176,43 @@ void PseudoLoweringEmitter::evaluateExpansion(const Record *Rec) {
180176
for (const auto &[Idx, SrcOp] : enumerate(SourceInsn.Operands))
181177
SourceOperands[SrcOp.Name] = Idx;
182178

183-
LLVM_DEBUG(dbgs() << " Operand mapping:\n");
184-
for (const auto &[Idx, Opnd] : enumerate(Insn.Operands)) {
185-
// We've already handled constant values. Just map instruction operands
186-
// here.
187-
if (OperandMap[Opnd.MIOperandNo].Kind != OpData::Operand)
188-
continue;
189-
StringMap<unsigned>::iterator SourceOp =
190-
SourceOperands.find(Dag->getArgNameStr(Idx));
191-
if (SourceOp == SourceOperands.end())
192-
PrintFatalError(Rec, "In pseudo instruction '" + Rec->getName() +
193-
"', output operand '" + Dag->getArgNameStr(Idx) +
194-
"' has no matching source operand");
195-
const auto &SrcOpnd = SourceInsn.Operands[SourceOp->getValue()];
196-
if (Opnd.MINumOperands != SrcOpnd.MINumOperands)
197-
PrintFatalError(
198-
Rec,
199-
"In pseudo instruction '" + Rec->getName() + "', output operand '" +
200-
Opnd.Rec->getName() +
201-
"' has a different number of sub operands than source operand '" +
202-
SrcOpnd.Rec->getName() + "'");
179+
unsigned NumMIOperands = 0;
180+
for (const auto &Op : Insn.Operands)
181+
NumMIOperands += Op.MINumOperands;
182+
IndexedMap<OpData> OperandMap;
183+
OperandMap.grow(NumMIOperands);
203184

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

209-
LLVM_DEBUG(dbgs() << " " << SourceOp->getValue() << " ==> " << Idx
210-
<< "\n");
192+
if (const auto *SubDag = dyn_cast<DagInit>(Dag->getArg(Idx))) {
193+
if (!DstOp.MIOperandInfo || DstOp.MIOperandInfo->getNumArgs() == 0)
194+
PrintFatalError(Rec, "In pseudo instruction '" + Rec->getName() +
195+
"', operand '" + DstOp.Rec->getName() +
196+
"' does not have suboperands");
197+
if (DstOp.MINumOperands != SubDag->getNumArgs()) {
198+
PrintFatalError(
199+
Rec, "In pseudo instruction '" + Rec->getName() + "', '" +
200+
SubDag->getAsString() +
201+
"' has wrong number of operands for operand type '" +
202+
DstOp.Rec->getName() + "'");
203+
}
204+
for (unsigned I = 0, E = DstOp.MINumOperands; I != E; ++I) {
205+
auto *OpndRec = cast<DefInit>(DstOp.MIOperandInfo->getArg(I))->getDef();
206+
addOperandMapping(MIOpNo + I, 1, Rec, SubDag, I, OpndRec, OperandMap,
207+
SourceOperands, SourceInsn);
208+
}
209+
} else {
210+
addOperandMapping(MIOpNo, DstOp.MINumOperands, Rec, Dag, Idx, DstOp.Rec,
211+
OperandMap, SourceOperands, SourceInsn);
212+
}
211213
}
212214

213-
Expansions.push_back(PseudoExpansion(SourceInsn, Insn, OperandMap));
215+
Expansions.emplace_back(SourceInsn, Insn, OperandMap);
214216
}
215217

216218
void PseudoLoweringEmitter::emitLoweringEmitter(raw_ostream &o) {

0 commit comments

Comments
 (0)