[PATCH] D100638: [AST][Introspection] Avoid creating temporary strings when comparing LocationCalls.
Nathan James via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Fri Apr 16 03:51:02 PDT 2021
njames93 created this revision.
njames93 added a reviewer: steveire.
njames93 requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.
Adds a bit of boiler plate, but removing the need to build temporary strings to compare the calls definitely worth it.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D100638
Files:
clang/lib/Tooling/NodeIntrospection.cpp
Index: clang/lib/Tooling/NodeIntrospection.cpp
===================================================================
--- clang/lib/Tooling/NodeIntrospection.cpp
+++ clang/lib/Tooling/NodeIntrospection.cpp
@@ -13,6 +13,9 @@
#include "clang/Tooling/NodeIntrospection.h"
#include "clang/AST/AST.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
namespace clang {
@@ -49,6 +52,56 @@
return Result;
}
+/// lexicographical 3 way comparison.
+static int compareStringArray(llvm::ArrayRef<std::string> LHS,
+ llvm::ArrayRef<std::string> RHS) {
+ // Most accessors don't accept any arguments
+ if (LLVM_LIKELY(LHS.empty() && RHS.empty()))
+ return 0;
+ auto LI = LHS.begin(), LE = LHS.end(), RI = RHS.begin(), RE = RHS.end();
+ for (; LI != LE && RI != RE; ++LI, ++RI) {
+ if (auto Cmp = LI->compare(*RI))
+ return Cmp;
+ }
+ if (LI == LE && RI == RE)
+ return 0;
+ // Return -1 if Left contains less items, 1 if more items.
+ return LI == LE ? -1 : 1;
+}
+
+/// A 3 way comparison of what LHS and RHS would look like when formatted as a
+/// cpp string.
+static int compareLocationCall(const LocationCall &LHS,
+ const LocationCall &RHS) {
+ // Expand the call stacks into a vector so we can traverse it in reverse
+ // order.
+ llvm::SmallVector<const LocationCall *> Left, Right;
+ for (const LocationCall *Item = &LHS; Item; Item = Item->on())
+ Left.push_back(Item);
+ for (const LocationCall *Item = &RHS; Item; Item = Item->on())
+ Right.push_back(Item);
+
+ auto LI = Left.rbegin(), LE = Left.rend(), RI = Right.rbegin();
+ for (; LI != LE; ++LI, ++RI) {
+ // If we haven't returned up to here, both call stacks are the same up the
+ // here are the same. If we detect that RI is at the end, that means the
+ // rights last item was a SourceLocation/Range accessor. Therefore the
+ // preceding item in left should also return a Loc/Range and it should be
+ // the last item in its stack.
+ assert(RI != Right.rend());
+ if (auto Strcmp = (*LI)->name().compare((*RI)->name()))
+ return Strcmp;
+ if (auto ArgCmp = compareStringArray((*LI)->args(), (*RI)->args()))
+ return ArgCmp;
+ // As both calls are the same, they should both either return by value or
+ // both return by pointer.
+ assert((*LI)->returnsPointer() == (*RI)->returnsPointer());
+ }
+ // As before but flipped.
+ assert(RI == Right.rend());
+ return 0;
+}
+
namespace internal {
bool RangeLessThan::operator()(
std::pair<SourceRange, SharedLocationCall> const &LHS,
@@ -66,15 +119,13 @@
else if (LHS.first.getEnd() != RHS.first.getEnd())
return false;
- return LocationCallFormatterCpp::format(*LHS.second) <
- LocationCallFormatterCpp::format(*RHS.second);
+ return compareLocationCall(*LHS.second, *RHS.second) < 0;
}
bool RangeLessThan::operator()(
std::pair<SourceLocation, SharedLocationCall> const &LHS,
std::pair<SourceLocation, SharedLocationCall> const &RHS) const {
if (LHS.first == RHS.first)
- return LocationCallFormatterCpp::format(*LHS.second) <
- LocationCallFormatterCpp::format(*RHS.second);
+ return compareLocationCall(*LHS.second, *RHS.second) < 0;
return LHS.first < RHS.first;
}
} // namespace internal
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D100638.338056.patch
Type: text/x-patch
Size: 3411 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20210416/dfa7b34d/attachment.bin>
More information about the cfe-commits
mailing list