4040
4141using namespace llvm ;
4242
43- cl::OptionCategory InstrInfoEmitterCat (" Options for -gen-instr-info" );
43+ static cl::OptionCategory InstrInfoEmitterCat (" Options for -gen-instr-info" );
4444static cl::opt<bool > ExpandMIOperandInfo (
4545 " instr-info-expand-mi-operand-info" ,
4646 cl::desc (" Expand operand's MIOperandInfo DAG into suboperands" ),
@@ -67,13 +67,6 @@ class InstrInfoEmitter {
6767 typedef std::vector<OperandInfoTy> OperandInfoListTy;
6868 typedef std::map<OperandInfoTy, unsigned > OperandInfoMapTy;
6969
70- // / The keys of this map are maps which have OpName enum values as their keys
71- // / and instruction operand indices as their values. The values of this map
72- // / are lists of instruction names.
73- typedef std::map<std::map<unsigned , unsigned >, std::vector<std::string>>
74- OpNameMapTy;
75- typedef std::map<std::string, unsigned >::iterator StrUintMapIter;
76-
7770 // / Generate member functions in the target-specific GenInstrInfo class.
7871 // /
7972 // / This method is used to custom expand TIIPredicate definitions.
@@ -95,15 +88,9 @@ class InstrInfoEmitter {
9588 void emitOperandTypeMappings (
9689 raw_ostream &OS, const CodeGenTarget &Target,
9790 ArrayRef<const CodeGenInstruction *> NumberedInstructions);
98- void
99- initOperandMapData (ArrayRef<const CodeGenInstruction *> NumberedInstructions,
100- StringRef Namespace,
101- std::map<std::string, unsigned > &Operands,
102- OpNameMapTy &OperandMap);
10391 void emitOperandNameMappings (
10492 raw_ostream &OS, const CodeGenTarget &Target,
10593 ArrayRef<const CodeGenInstruction *> NumberedInstructions);
106-
10794 void emitLogicalOperandSizeMappings (
10895 raw_ostream &OS, StringRef Namespace,
10996 ArrayRef<const CodeGenInstruction *> NumberedInstructions);
@@ -239,35 +226,6 @@ void InstrInfoEmitter::EmitOperandInfo(raw_ostream &OS,
239226 }
240227}
241228
242- // / Initialize data structures for generating operand name mappings.
243- // /
244- // / \param Operands [out] A map used to generate the OpName enum with operand
245- // / names as its keys and operand enum values as its values.
246- // / \param OperandMap [out] A map for representing the operand name mappings for
247- // / each instructions. This is used to generate the OperandMap table as
248- // / well as the getNamedOperandIdx() function.
249- void InstrInfoEmitter::initOperandMapData (
250- ArrayRef<const CodeGenInstruction *> NumberedInstructions,
251- StringRef Namespace, std::map<std::string, unsigned > &Operands,
252- OpNameMapTy &OperandMap) {
253- unsigned NumOperands = 0 ;
254- for (const CodeGenInstruction *Inst : NumberedInstructions) {
255- if (!Inst->TheDef ->getValueAsBit (" UseNamedOperandTable" ))
256- continue ;
257- std::map<unsigned , unsigned > OpList;
258- for (const auto &Info : Inst->Operands ) {
259- StrUintMapIter I = Operands.find (Info.Name );
260-
261- if (I == Operands.end ()) {
262- I = Operands.insert (Operands.begin (), {Info.Name , NumOperands++});
263- }
264- OpList[I->second ] = Info.MIOperandNo ;
265- }
266- OperandMap[OpList].push_back (Namespace.str () +
267- " ::" + Inst->TheDef ->getName ().str ());
268- }
269- }
270-
271229// / Generate a table and function for looking up the indices of operands by
272230// / name.
273231// /
@@ -283,22 +241,52 @@ void InstrInfoEmitter::emitOperandNameMappings(
283241 raw_ostream &OS, const CodeGenTarget &Target,
284242 ArrayRef<const CodeGenInstruction *> NumberedInstructions) {
285243 StringRef Namespace = Target.getInstNamespace ();
286- // Map of operand names to their enumeration value. This will be used to
287- // generate the OpName enum.
288- std::map<std::string, unsigned > Operands;
289- OpNameMapTy OperandMap;
290244
291- initOperandMapData (NumberedInstructions, Namespace, Operands, OperandMap);
245+ // / To facilitate assigning OpName enum values in the sorted alphabetical
246+ // / order, we go through an indirection from OpName -> ID, and Enum -> ID.
247+ // / This allows us to build the OpList and assign IDs to OpNames in a single
248+ // / scan of the instructions below.
249+
250+ // Map of operand names to their ID.
251+ std::map<StringRef, unsigned > OperandNameToID;
252+ // Map from operand name enum value -> ID.
253+ std::vector<unsigned > OperandEnumToID;
254+
255+ // / The keys of this map is a map which have OpName ID values as their keys
256+ // / and instruction operand indices as their values. The values of this map
257+ // / are lists of instruction names. This map helps to unique entries among
258+ // / instructions that have identical OpName -> Operand index mapping.
259+ std::map<std::map<unsigned , unsigned >, std::vector<StringRef>> OperandMap;
260+
261+ // Max operand index seen.
262+ unsigned MaxOperandNo = 0 ;
263+
264+ for (const CodeGenInstruction *Inst : NumberedInstructions) {
265+ if (!Inst->TheDef ->getValueAsBit (" UseNamedOperandTable" ))
266+ continue ;
267+ std::map<unsigned , unsigned > OpList;
268+ for (const auto &Info : Inst->Operands ) {
269+ unsigned ID =
270+ OperandNameToID.try_emplace (Info.Name , OperandNameToID.size ())
271+ .first ->second ;
272+ OpList[ID] = Info.MIOperandNo ;
273+ MaxOperandNo = std::max (MaxOperandNo, Info.MIOperandNo );
274+ }
275+ OperandMap[OpList].push_back (Inst->TheDef ->getName ());
276+ }
277+
278+ const size_t NumOperandNames = OperandNameToID.size ();
279+ OperandEnumToID.reserve (NumOperandNames);
280+ for (const auto &Op : OperandNameToID)
281+ OperandEnumToID.push_back (Op.second );
292282
293283 OS << " #ifdef GET_INSTRINFO_OPERAND_ENUM\n " ;
294284 OS << " #undef GET_INSTRINFO_OPERAND_ENUM\n " ;
295285 OS << " namespace llvm::" << Namespace << " ::OpName {\n " ;
296286 OS << " enum {\n " ;
297- for (const auto &Op : Operands)
298- OS << " " << Op.first << " = " << Op.second << " ,\n " ;
299-
300- OS << " OPERAND_LAST" ;
301- OS << " \n };\n " ;
287+ for (const auto &[I, Op] : enumerate(OperandNameToID))
288+ OS << " " << Op.first << " = " << I << " ,\n " ;
289+ OS << " };\n " ;
302290 OS << " } // end namespace llvm::" << Namespace << " ::OpName\n " ;
303291 OS << " #endif //GET_INSTRINFO_OPERAND_ENUM\n\n " ;
304292
@@ -307,28 +295,30 @@ void InstrInfoEmitter::emitOperandNameMappings(
307295 OS << " namespace llvm::" << Namespace << " {\n " ;
308296 OS << " LLVM_READONLY\n " ;
309297 OS << " int16_t getNamedOperandIdx(uint16_t Opcode, uint16_t NamedIdx) {\n " ;
310- if (!Operands.empty ()) {
311- OS << " static const int16_t OperandMap [][" << Operands.size ()
298+ if (NumOperandNames != 0 ) {
299+ assert (MaxOperandNo <= INT16_MAX &&
300+ " Too many operands for the operand name -> index table" );
301+ StringRef Type = MaxOperandNo <= INT8_MAX ? " int8_t" : " int16_t" ;
302+ OS << " static constexpr " << Type << " OperandMap[][" << NumOperandNames
312303 << " ] = {\n " ;
313304 for (const auto &Entry : OperandMap) {
314305 const std::map<unsigned , unsigned > &OpList = Entry.first ;
315- OS << " {" ;
316-
317- // Emit a row of the OperandMap table
318- for (unsigned i = 0 , e = Operands.size (); i != e; ++i)
319- OS << (OpList.count (i) == 0 ? -1 : (int )OpList.find (i)->second ) << " , " ;
320306
307+ // Emit a row of the OperandMap table.
308+ OS << " {" ;
309+ for (unsigned ID : OperandEnumToID) {
310+ auto Iter = OpList.find (ID);
311+ OS << (Iter != OpList.end () ? (int )Iter->second : -1 ) << " , " ;
312+ }
321313 OS << " },\n " ;
322314 }
323- OS << " };\n " ;
315+ OS << " };\n " ;
324316
325317 OS << " switch(Opcode) {\n " ;
326- unsigned TableIndex = 0 ;
327- for (const auto &Entry : OperandMap) {
328- for (const std::string &Name : Entry.second )
329- OS << " case " << Name << " :\n " ;
330-
331- OS << " return OperandMap[" << TableIndex++ << " ][NamedIdx];\n " ;
318+ for (const auto &[TableIndex, Entry] : enumerate(OperandMap)) {
319+ for (StringRef Name : Entry.second )
320+ OS << " case " << Namespace << " ::" << Name << " :\n " ;
321+ OS << " return OperandMap[" << TableIndex << " ][NamedIdx];\n " ;
332322 }
333323 OS << " default: return -1;\n " ;
334324 OS << " }\n " ;
0 commit comments