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<std::string, 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<std::string>> OperandMap;
260+
261+ // Max operand index seen.
262+ unsigned MaxOperandNo = 0 ;
263+ unsigned NumOperandNames = 0 ;
264+
265+ for (const CodeGenInstruction *Inst : NumberedInstructions) {
266+ if (!Inst->TheDef ->getValueAsBit (" UseNamedOperandTable" ))
267+ continue ;
268+ std::map<unsigned , unsigned > OpList;
269+ for (const auto &Info : Inst->Operands ) {
270+ auto [I, Inserted] = OperandNameToID.try_emplace (Info.Name , 0 );
271+ if (Inserted)
272+ I->second = NumOperandNames++;
273+ OpList[I->second ] = Info.MIOperandNo ;
274+ MaxOperandNo = std::max (MaxOperandNo, Info.MIOperandNo );
275+ }
276+ OperandMap[OpList].push_back (Inst->TheDef ->getName ().str ());
277+ }
278+
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,31 @@ 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 <= std::numeric_limits<int16_t >::max ());
300+ StringRef Type = MaxOperandNo <= std::numeric_limits<int8_t >::max ()
301+ ? " int8_t"
302+ : " int16_t" ;
303+ OS << " static constexpr " << Type << " OperandMap[][" << NumOperandNames
312304 << " ] = {\n " ;
313305 for (const auto &Entry : OperandMap) {
314306 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 ) << " , " ;
320307
308+ // Emit a row of the OperandMap table.
309+ OS << " {" ;
310+ for (int i = 0 ; i < static_cast <int >(NumOperandNames); ++i) {
311+ unsigned ID = OperandEnumToID[i];
312+ OS << (OpList.count (ID) ? (int )OpList.find (ID)->second : -1 ) << " , " ;
313+ }
321314 OS << " },\n " ;
322315 }
323316 OS << " };\n " ;
324317
325318 OS << " switch(Opcode) {\n " ;
326- unsigned TableIndex = 0 ;
327- for (const auto &Entry : OperandMap) {
319+ for (const auto &[TableIndex, Entry] : enumerate(OperandMap)) {
328320 for (const std::string &Name : Entry.second )
329- OS << " case " << Name << " :\n " ;
330-
331- OS << " return OperandMap[" << TableIndex++ << " ][NamedIdx];\n " ;
321+ OS << " case " << Namespace << " ::" << Name << " :\n " ;
322+ OS << " return OperandMap[" << TableIndex << " ][NamedIdx];\n " ;
332323 }
333324 OS << " default: return -1;\n " ;
334325 OS << " }\n " ;
0 commit comments