@@ -2547,53 +2547,58 @@ static void emitIsSubclass(CodeGenTarget &Target,
25472547 OS << " if (A == B)\n " ;
25482548 OS << " return true;\n\n " ;
25492549
2550- bool EmittedSwitch = false ;
2550+ // TODO: Use something like SequenceToOffsetTable to allow sequences to
2551+ // overlap in this table.
2552+ SmallVector<bool > SuperClassData;
2553+
2554+ OS << " [[maybe_unused]] static constexpr struct {\n " ;
2555+ OS << " uint32_t Offset;\n " ;
2556+ OS << " uint16_t Start;\n " ;
2557+ OS << " uint16_t Length;\n " ;
2558+ OS << " } Table[] = {\n " ;
2559+ OS << " {0, 0, 0},\n " ; // InvalidMatchClass
2560+ OS << " {0, 0, 0},\n " ; // OptionalMatchClass
25512561 for (const auto &A : Infos) {
2552- std::vector<StringRef> SuperClasses;
2553- if (A.IsOptional )
2554- SuperClasses.push_back (" OptionalMatchClass" );
2555- for (const auto &B : Infos) {
2556- if (&A != &B && A.isSubsetOf (B))
2557- SuperClasses.push_back (B.Name );
2558- }
2559-
2560- if (SuperClasses.empty ())
2561- continue ;
2562-
2563- // If this is the first SuperClass, emit the switch header.
2564- if (!EmittedSwitch) {
2565- OS << " switch (A) {\n " ;
2566- OS << " default:\n " ;
2567- OS << " return false;\n " ;
2568- EmittedSwitch = true ;
2569- }
2570-
2571- OS << " \n case " << A.Name << " :\n " ;
2572-
2573- if (SuperClasses.size () == 1 ) {
2574- OS << " return B == " << SuperClasses.back () << " ;\n " ;
2575- continue ;
2576- }
2577-
2578- if (!SuperClasses.empty ()) {
2579- OS << " switch (B) {\n " ;
2580- OS << " default: return false;\n " ;
2581- for (StringRef SC : SuperClasses)
2582- OS << " case " << SC << " : return true;\n " ;
2583- OS << " }\n " ;
2584- } else {
2585- // No case statement to emit
2586- OS << " return false;\n " ;
2587- }
2562+ SmallVector<bool > SuperClasses;
2563+ SuperClasses.push_back (false ); // InvalidMatchClass
2564+ SuperClasses.push_back (A.IsOptional ); // OptionalMatchClass
2565+ for (const auto &B : Infos)
2566+ SuperClasses.push_back (&A != &B && A.isSubsetOf (B));
2567+
2568+ // Trim leading and trailing zeros.
2569+ auto End = find_if (reverse (SuperClasses), [](bool B) { return B; }).base ();
2570+ auto Start =
2571+ std::find_if (SuperClasses.begin (), End, [](bool B) { return B; });
2572+
2573+ unsigned Offset = SuperClassData.size ();
2574+ SuperClassData.append (Start, End);
2575+
2576+ OS << " {" << Offset << " , " << (Start - SuperClasses.begin ()) << " , "
2577+ << (End - Start) << " },\n " ;
25882578 }
2579+ OS << " };\n\n " ;
25892580
2590- // If there were case statements emitted into the string stream write the
2591- // default.
2592- if (EmittedSwitch)
2593- OS << " }\n " ;
2594- else
2581+ if (SuperClassData.empty ()) {
25952582 OS << " return false;\n " ;
2596-
2583+ } else {
2584+ // Dump the boolean data packed into bytes.
2585+ SuperClassData.append (-SuperClassData.size () % 8 , false );
2586+ OS << " static constexpr uint8_t Data[] = {\n " ;
2587+ for (unsigned I = 0 , E = SuperClassData.size (); I < E; I += 8 ) {
2588+ unsigned Byte = 0 ;
2589+ for (unsigned J = 0 ; J < 8 ; ++J)
2590+ Byte |= (unsigned )SuperClassData[I + J] << J;
2591+ OS << formatv (" {:X2},\n " , Byte);
2592+ }
2593+ OS << " };\n\n " ;
2594+
2595+ OS << " auto &Entry = Table[A];\n " ;
2596+ OS << " unsigned Idx = B - Entry.Start;\n " ;
2597+ OS << " if (Idx >= Entry.Length)\n " ;
2598+ OS << " return false;\n " ;
2599+ OS << " Idx += Entry.Offset;\n " ;
2600+ OS << " return (Data[Idx / 8] >> (Idx % 8)) & 1;\n " ;
2601+ }
25972602 OS << " }\n\n " ;
25982603}
25992604
0 commit comments