@@ -2547,53 +2547,58 @@ static void emitIsSubclass(CodeGenTarget &Target,
2547
2547
OS << " if (A == B)\n " ;
2548
2548
OS << " return true;\n\n " ;
2549
2549
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
2551
2561
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 " ;
2588
2578
}
2579
+ OS << " };\n\n " ;
2589
2580
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 ()) {
2595
2582
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
+ }
2597
2602
OS << " }\n\n " ;
2598
2603
}
2599
2604
0 commit comments