34
34
using namespace llvm ;
35
35
36
36
// / Table of string intrinsic names indexed by enum value.
37
- static constexpr const char *const IntrinsicNameTable[] = {
38
- " not_intrinsic" ,
39
37
#define GET_INTRINSIC_NAME_TABLE
40
38
#include " llvm/IR/IntrinsicImpl.inc"
41
39
#undef GET_INTRINSIC_NAME_TABLE
42
- };
43
40
44
41
StringRef Intrinsic::getBaseName (ID id) {
45
42
assert (id < num_intrinsics && " Invalid intrinsic ID!" );
46
- return IntrinsicNameTable[id];
43
+ return IntrinsicNameTable + IntrinsicNameOffsetTable [id];
47
44
}
48
45
49
46
StringRef Intrinsic::getName (ID id) {
@@ -621,9 +618,12 @@ bool Intrinsic::isTargetIntrinsic(Intrinsic::ID IID) {
621
618
return IID > TargetInfos[0 ].Count ;
622
619
}
623
620
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 = " " ) {
627
627
assert (Name.starts_with (" llvm." ) && " Unexpected intrinsic prefix" );
628
628
assert (Name.drop_front (5 ).starts_with (Target) && " Unexpected target" );
629
629
@@ -638,36 +638,53 @@ int llvm::Intrinsic::lookupLLVMIntrinsicByName(ArrayRef<const char *> NameTable,
638
638
if (!Target.empty ())
639
639
CmpEnd += 1 + Target.size (); // skip the .target component.
640
640
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;
644
644
while (CmpEnd < Name.size () && High - Low > 0 ) {
645
645
size_t CmpStart = CmpEnd;
646
646
CmpEnd = Name.find (' .' , CmpStart + 1 );
647
647
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 ;
650
666
};
651
667
LastLow = Low;
652
668
std::tie (Low, High) = std::equal_range (Low, High, Name.data (), Cmp);
653
669
}
654
670
if (High - Low > 0 )
655
671
LastLow = Low;
656
672
657
- if (LastLow == NameTable .end ())
673
+ if (LastLow == NameOffsetTable .end ())
658
674
return -1 ;
659
- StringRef NameFound = *LastLow;
675
+ StringRef NameFound = &IntrinsicNameTable[ *LastLow] ;
660
676
if (Name == NameFound ||
661
677
(Name.starts_with (NameFound) && Name[NameFound.size ()] == ' .' ))
662
- return LastLow - NameTable .begin ();
678
+ return LastLow - NameOffsetTable .begin ();
663
679
return -1 ;
664
680
}
665
681
666
- // / Find the segment of \c IntrinsicNameTable for intrinsics with the same
682
+ // / Find the segment of \c IntrinsicNameOffsetTable for intrinsics with the same
667
683
// / target as \c Name, or the generic table if \c Name is not target specific.
668
684
// /
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>
671
688
findTargetSubtable (StringRef Name) {
672
689
assert (Name.starts_with (" llvm." ));
673
690
@@ -680,25 +697,26 @@ findTargetSubtable(StringRef Name) {
680
697
// We've either found the target or just fall back to the generic set, which
681
698
// is always first.
682
699
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 };
684
702
}
685
703
686
704
// / This does the actual lookup of an intrinsic ID which matches the given
687
705
// / function name.
688
706
Intrinsic::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);
691
709
if (Idx == -1 )
692
710
return Intrinsic::not_intrinsic;
693
711
694
712
// Intrinsic IDs correspond to the location in IntrinsicNameTable, but we have
695
713
// an index into a sub-table.
696
- int Adjust = NameTable .data () - IntrinsicNameTable ;
714
+ int Adjust = NameOffsetTable .data () - IntrinsicNameOffsetTable ;
697
715
Intrinsic::ID ID = static_cast <Intrinsic::ID>(Idx + Adjust);
698
716
699
717
// If the intrinsic is not overloaded, require an exact match. If it is
700
718
// overloaded, require either exact or prefix match.
701
- const auto MatchSize = strlen (NameTable[ Idx]);
719
+ const auto MatchSize = strlen (&IntrinsicNameTable[NameOffsetTable[ Idx] ]);
702
720
assert (Name.size () >= MatchSize && " Expected either exact or prefix match" );
703
721
bool IsExactMatch = Name.size () == MatchSize;
704
722
return IsExactMatch || Intrinsic::isOverloaded (ID) ? ID
0 commit comments