@@ -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
129133void 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
216218void PseudoLoweringEmitter::emitLoweringEmitter (raw_ostream &o) {
0 commit comments