diff options
author | Reid Kleckner <rnk@google.com> | 2016-01-26 22:33:19 +0000 |
---|---|---|
committer | Reid Kleckner <rnk@google.com> | 2016-01-26 22:33:19 +0000 |
commit | c2752daa6bf70786ebbb448208af8fb62a431ecc (patch) | |
tree | 30f5d3485a097097f1b05b97a178e64753b9a89d /llvm/lib/IR/IntrinsicInst.cpp | |
parent | 7da47b8ef5efc16caef8cbd45f495baf9b383370 (diff) | |
download | bcm5719-llvm-c2752daa6bf70786ebbb448208af8fb62a431ecc.tar.gz bcm5719-llvm-c2752daa6bf70786ebbb448208af8fb62a431ecc.zip |
Handle more edge cases in intrinsic name binary search
I tried to make the AMDGPU intrinsic info table use this instead of
another StringMatcher, and some issues arose.
llvm-svn: 258871
Diffstat (limited to 'llvm/lib/IR/IntrinsicInst.cpp')
-rw-r--r-- | llvm/lib/IR/IntrinsicInst.cpp | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/llvm/lib/IR/IntrinsicInst.cpp b/llvm/lib/IR/IntrinsicInst.cpp index b9b5a29091d..427cfef5fa3 100644 --- a/llvm/lib/IR/IntrinsicInst.cpp +++ b/llvm/lib/IR/IntrinsicInst.cpp @@ -25,6 +25,7 @@ #include "llvm/IR/Constants.h" #include "llvm/IR/GlobalVariable.h" #include "llvm/IR/Metadata.h" +#include "llvm/Support/raw_ostream.h" using namespace llvm; //===----------------------------------------------------------------------===// @@ -79,3 +80,41 @@ const Value *DbgValueInst::getValue() const { } Value *DbgValueInst::getValue() { return getValueImpl(getArgOperand(0)); } + +int llvm::Intrinsic::lookupLLVMIntrinsicByName(ArrayRef<const char *> NameTable, + StringRef Name) { + assert(Name.startswith("llvm.")); + + // Do successive binary searches of the dotted name components. For + // "llvm.gc.experimental.statepoint.p1i8.p1i32", we will find the range of + // intrinsics starting with "llvm.gc", then "llvm.gc.experimental", then + // "llvm.gc.experimental.statepoint", and then we will stop as the range is + // size 1. During the search, we can skip the prefix that we already know is + // identical. By using strncmp we consider names with differing suffixes to + // be part of the equal range. + size_t CmpStart = 0; + size_t CmpEnd = 4; // Skip the "llvm" component. + const char *const *Low = NameTable.begin(); + const char *const *High = NameTable.end(); + const char *const *LastLow = Low; + while (CmpEnd < Name.size() && High - Low > 0) { + CmpStart = CmpEnd; + CmpEnd = Name.find('.', CmpStart + 1); + CmpEnd = CmpEnd == StringRef::npos ? Name.size() : CmpEnd; + auto Cmp = [CmpStart, CmpEnd](const char *LHS, const char *RHS) { + return strncmp(LHS + CmpStart, RHS + CmpStart, CmpEnd - CmpStart) < 0; + }; + LastLow = Low; + std::tie(Low, High) = std::equal_range(Low, High, Name.data(), Cmp); + } + if (High - Low > 0) + LastLow = Low; + + if (LastLow == NameTable.end()) + return -1; + StringRef NameFound = *LastLow; + if (Name == NameFound || + (Name.startswith(NameFound) && Name[NameFound.size()] == '.')) + return LastLow - NameTable.begin(); + return -1; +} |