3434using namespace llvm ;
3535
3636// / Table of string intrinsic names indexed by enum value.
37- static constexpr const char *const IntrinsicNameTable[] = {
38- " not_intrinsic" ,
3937#define GET_INTRINSIC_NAME_TABLE
4038#include " llvm/IR/IntrinsicImpl.inc"
4139#undef GET_INTRINSIC_NAME_TABLE
42- };
4340
4441StringRef Intrinsic::getBaseName (ID id) {
4542 assert (id < num_intrinsics && " Invalid intrinsic ID!" );
46- return IntrinsicNameTable[id];
43+ return IntrinsicNameTable + IntrinsicNameOffsetTable [id];
4744}
4845
4946StringRef Intrinsic::getName (ID id) {
@@ -621,9 +618,12 @@ bool Intrinsic::isTargetIntrinsic(Intrinsic::ID IID) {
621618 return IID > TargetInfos[0 ].Count ;
622619}
623620
624- int llvm::Intrinsic::lookupLLVMIntrinsicByName (ArrayRef<const char *> NameTable,
625- StringRef Name,
626- StringRef Target) {
621+ // / Looks up Name in NameTable via binary search. NameTable must be sorted
622+ // / and all entries must start with "llvm.". If NameTable contains an exact
623+ // / match for Name or a prefix of Name followed by a dot, its index in
624+ // / NameTable is returned. Otherwise, -1 is returned.
625+ static int lookupLLVMIntrinsicByName (ArrayRef<unsigned > NameOffsetTable,
626+ StringRef Name, StringRef Target = " " ) {
627627 assert (Name.starts_with (" llvm." ) && " Unexpected intrinsic prefix" );
628628 assert (Name.drop_front (5 ).starts_with (Target) && " Unexpected target" );
629629
@@ -638,36 +638,53 @@ int llvm::Intrinsic::lookupLLVMIntrinsicByName(ArrayRef<const char *> NameTable,
638638 if (!Target.empty ())
639639 CmpEnd += 1 + Target.size (); // skip the .target component.
640640
641- const char * const * Low = NameTable .begin ();
642- const char * const * High = NameTable .end ();
643- const char * const *LastLow = Low;
641+ const unsigned * Low = NameOffsetTable .begin ();
642+ const unsigned * High = NameOffsetTable .end ();
643+ const unsigned *LastLow = Low;
644644 while (CmpEnd < Name.size () && High - Low > 0 ) {
645645 size_t CmpStart = CmpEnd;
646646 CmpEnd = Name.find (' .' , CmpStart + 1 );
647647 CmpEnd = CmpEnd == StringRef::npos ? Name.size () : CmpEnd;
648- auto Cmp = [CmpStart, CmpEnd](const char *LHS, const char *RHS) {
649- return strncmp (LHS + CmpStart, RHS + CmpStart, CmpEnd - CmpStart) < 0 ;
648+ auto Cmp = [CmpStart, CmpEnd](auto LHS, auto RHS) {
649+ // `equal_range` requires the comparison to work with either side being an
650+ // offset or the value. Detect which kind each side is to set up the
651+ // compared strings.
652+ const char *LHSStr;
653+ if constexpr (std::is_integral_v<decltype (LHS)>) {
654+ LHSStr = &IntrinsicNameTable[LHS];
655+ } else {
656+ LHSStr = LHS;
657+ }
658+ const char *RHSStr;
659+ if constexpr (std::is_integral_v<decltype (RHS)>) {
660+ RHSStr = &IntrinsicNameTable[RHS];
661+ } else {
662+ RHSStr = RHS;
663+ }
664+ return strncmp (LHSStr + CmpStart, RHSStr + CmpStart, CmpEnd - CmpStart) <
665+ 0 ;
650666 };
651667 LastLow = Low;
652668 std::tie (Low, High) = std::equal_range (Low, High, Name.data (), Cmp);
653669 }
654670 if (High - Low > 0 )
655671 LastLow = Low;
656672
657- if (LastLow == NameTable .end ())
673+ if (LastLow == NameOffsetTable .end ())
658674 return -1 ;
659- StringRef NameFound = *LastLow;
675+ StringRef NameFound = &IntrinsicNameTable[ *LastLow] ;
660676 if (Name == NameFound ||
661677 (Name.starts_with (NameFound) && Name[NameFound.size ()] == ' .' ))
662- return LastLow - NameTable .begin ();
678+ return LastLow - NameOffsetTable .begin ();
663679 return -1 ;
664680}
665681
666- // / Find the segment of \c IntrinsicNameTable for intrinsics with the same
682+ // / Find the segment of \c IntrinsicNameOffsetTable for intrinsics with the same
667683// / target as \c Name, or the generic table if \c Name is not target specific.
668684// /
669- // / Returns the relevant slice of \c IntrinsicNameTable and the target name.
670- static std::pair<ArrayRef<const char *>, StringRef>
685+ // / Returns the relevant slice of \c IntrinsicNameOffsetTable and the target
686+ // / name.
687+ static std::pair<ArrayRef<unsigned >, StringRef>
671688findTargetSubtable (StringRef Name) {
672689 assert (Name.starts_with (" llvm." ));
673690
@@ -680,25 +697,26 @@ findTargetSubtable(StringRef Name) {
680697 // We've either found the target or just fall back to the generic set, which
681698 // is always first.
682699 const auto &TI = It != Targets.end () && It->Name == Target ? *It : Targets[0 ];
683- return {ArrayRef (&IntrinsicNameTable[1 ] + TI.Offset , TI.Count ), TI.Name };
700+ return {ArrayRef (&IntrinsicNameOffsetTable[1 ] + TI.Offset , TI.Count ),
701+ TI.Name };
684702}
685703
686704// / This does the actual lookup of an intrinsic ID which matches the given
687705// / function name.
688706Intrinsic::ID Intrinsic::lookupIntrinsicID (StringRef Name) {
689- auto [NameTable , Target] = findTargetSubtable (Name);
690- int Idx = Intrinsic:: lookupLLVMIntrinsicByName (NameTable , Name, Target);
707+ auto [NameOffsetTable , Target] = findTargetSubtable (Name);
708+ int Idx = lookupLLVMIntrinsicByName (NameOffsetTable , Name, Target);
691709 if (Idx == -1 )
692710 return Intrinsic::not_intrinsic;
693711
694712 // Intrinsic IDs correspond to the location in IntrinsicNameTable, but we have
695713 // an index into a sub-table.
696- int Adjust = NameTable .data () - IntrinsicNameTable ;
714+ int Adjust = NameOffsetTable .data () - IntrinsicNameOffsetTable ;
697715 Intrinsic::ID ID = static_cast <Intrinsic::ID>(Idx + Adjust);
698716
699717 // If the intrinsic is not overloaded, require an exact match. If it is
700718 // overloaded, require either exact or prefix match.
701- const auto MatchSize = strlen (NameTable[ Idx]);
719+ const auto MatchSize = strlen (&IntrinsicNameTable[NameOffsetTable[ Idx] ]);
702720 assert (Name.size () >= MatchSize && " Expected either exact or prefix match" );
703721 bool IsExactMatch = Name.size () == MatchSize;
704722 return IsExactMatch || Intrinsic::isOverloaded (ID) ? ID
0 commit comments