[PATCH] D100638: [AST][Introspection] Avoid creating temporary strings when comparing LocationCalls.

Nathan James via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Sat Apr 17 23:50:59 PDT 2021


njames93 updated this revision to Diff 338356.
njames93 added a comment.

Rebase and remove Args from comparison.
Add quick check for skippig common prefix calls.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D100638/new/

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 {
@@ -40,6 +43,42 @@
   return Result;
 }
 
+/// A 3 way comparison of LHS and RHS based on call names.
+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();
+  // It's common for 2 location calls to start with the same prefix:
+  // getTypeSourceInfo()->getTypeLoc().getAs<..>().getLocalSourceRange()
+  // getTypeSourceInfo()->getTypeLoc().getLocalSourceRange()
+  // We can use pointer identity to quickly try and skip these cases.
+  for (; LI != LE && *LI == *RI; *LI++, *RI++)
+    assert(RI != Right.rend());
+  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;
+    // 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,
@@ -57,15 +96,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.338356.patch
Type: text/x-patch
Size: 3032 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20210418/ec9c9624/attachment.bin>


More information about the cfe-commits mailing list