Hi klimek,
ASTNodeKind::isBaseOf shows in one of the top lines of the profile when
running a large clang-tidy benchmark. This rewrite reduces its total time from
6.1% to 3.7%:
< 11.06s 6.14% 13.29% 11.06s 6.14%:
clang::ast_type_traits::ASTNodeKind::isBaseOf
> 5.75s 3.70% 10.35% 5.75s 3.70%:
> clang::ast_type_traits::ASTNodeKind::isBaseOf
http://reviews.llvm.org/D5577
Files:
.gitignore
include/clang/AST/ASTTypeTraits.h
lib/AST/ASTTypeTraits.cpp
lib/ASTMatchers/Dynamic/VariantValue.cpp
unittests/AST/ASTTypeTraitsTest.cpp
Index: .gitignore
===================================================================
--- .gitignore
+++ .gitignore
@@ -29,7 +29,7 @@
# Directories to ignore (do not add trailing '/'s, they skip symlinks).
#==============================================================================#
# Clang extra user tools, which is tracked independently (clang-tools-extra).
-tools/extra
+# !!! alexfh: track tools/extra in the same git directory tools/extra
# Sphinx build products
docs/_build
docs/analyzer/_build
Index: include/clang/AST/ASTTypeTraits.h
===================================================================
--- include/clang/AST/ASTTypeTraits.h
+++ include/clang/AST/ASTTypeTraits.h
@@ -64,9 +64,12 @@
bool isSame(ASTNodeKind Other) const;
/// \brief Returns \c true if \c this is a base kind of (or same as) \c Other.
+ bool isBaseOf(ASTNodeKind Other) const;
+
+ /// \brief Returns \c true if \c this is a base kind of (or same as) \c Other.
/// \param Distance If non-null, used to return the distance between \c this
/// and \c Other in the class hierarchy.
- bool isBaseOf(ASTNodeKind Other, unsigned *Distance = nullptr) const;
+ bool isBaseOf(ASTNodeKind Other, unsigned &Distance) const;
/// \brief String representation of the kind.
StringRef asStringRef() const;
@@ -100,15 +103,11 @@
NKI_NumberOfKinds
};
+ struct NodeParentMap;
+
/// \brief Use getFromNodeKind<T>() to construct the kind.
ASTNodeKind(NodeKindId KindId) : KindId(KindId) {}
- /// \brief Returns \c true if \c Base is a base kind of (or same as) \c
- /// Derived.
- /// \param Distance If non-null, used to return the distance between \c Base
- /// and \c Derived in the class hierarchy.
- static bool isBaseOf(NodeKindId Base, NodeKindId Derived, unsigned *Distance);
-
/// \brief Helper meta-function to convert a kind T to its enum value.
///
/// This struct is specialized below for all known kinds.
Index: lib/AST/ASTTypeTraits.cpp
===================================================================
--- lib/AST/ASTTypeTraits.cpp
+++ lib/AST/ASTTypeTraits.cpp
@@ -16,6 +16,7 @@
#include "clang/AST/ASTTypeTraits.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclCXX.h"
+#include "llvm/Support/ManagedStatic.h"
namespace clang {
namespace ast_type_traits {
@@ -39,27 +40,34 @@
#include "clang/AST/TypeNodes.def"
};
-bool ASTNodeKind::isBaseOf(ASTNodeKind Other, unsigned *Distance) const {
- return isBaseOf(KindId, Other.KindId, Distance);
+struct ASTNodeKind::NodeParentMap {
+ NodeParentMap() {
+ for (unsigned Node = NKI_None; Node < NKI_NumberOfKinds; ++Node) {
+ for (unsigned Parent = NKI_None; Parent < NKI_NumberOfKinds; ++Parent)
+ ParentDistances[Node][Parent] = -1U;
+ unsigned Distance = 0;
+ for (unsigned Parent = Node; Parent != NKI_None;
+ Parent = ASTNodeKind::AllKindInfo[Parent].ParentId)
+ ParentDistances[Node][Parent] = Distance++;
+ }
+ }
+
+ unsigned ParentDistances[NKI_NumberOfKinds][NKI_NumberOfKinds];
+};
+
+bool ASTNodeKind::isBaseOf(ASTNodeKind Other) const {
+ static const NodeParentMap *Map = new NodeParentMap;
+ return Map->ParentDistances[Other.KindId][KindId] != -1U;
+}
+bool ASTNodeKind::isBaseOf(ASTNodeKind Other, unsigned &Distance) const {
+ static const NodeParentMap *Map = new NodeParentMap;
+ return (Distance = Map->ParentDistances[Other.KindId][KindId]) != -1U;
}
bool ASTNodeKind::isSame(ASTNodeKind Other) const {
return KindId != NKI_None && KindId == Other.KindId;
}
-bool ASTNodeKind::isBaseOf(NodeKindId Base, NodeKindId Derived,
- unsigned *Distance) {
- if (Base == NKI_None || Derived == NKI_None) return false;
- unsigned Dist = 0;
- while (Derived != Base && Derived != NKI_None) {
- Derived = AllKindInfo[Derived].ParentId;
- ++Dist;
- }
- if (Distance)
- *Distance = Dist;
- return Derived == Base;
-}
-
StringRef ASTNodeKind::asStringRef() const { return AllKindInfo[KindId].Name; }
ASTNodeKind ASTNodeKind::getFromNode(const Decl &D) {
Index: lib/ASTMatchers/Dynamic/VariantValue.cpp
===================================================================
--- lib/ASTMatchers/Dynamic/VariantValue.cpp
+++ lib/ASTMatchers/Dynamic/VariantValue.cpp
@@ -41,7 +41,7 @@
return true;
}
unsigned Distance;
- if (!MatcherKind.isBaseOf(To.MatcherKind, &Distance))
+ if (!MatcherKind.isBaseOf(To.MatcherKind, Distance))
return false;
if (Specificity)
Index: unittests/AST/ASTTypeTraitsTest.cpp
===================================================================
--- unittests/AST/ASTTypeTraitsTest.cpp
+++ unittests/AST/ASTTypeTraitsTest.cpp
@@ -36,14 +36,14 @@
TEST(ASTNodeKind, BaseDistances) {
unsigned Distance = 1;
- EXPECT_TRUE(DNT<Expr>().isBaseOf(DNT<Expr>(), &Distance));
+ EXPECT_TRUE(DNT<Expr>().isBaseOf(DNT<Expr>(), Distance));
EXPECT_EQ(0u, Distance);
- EXPECT_TRUE(DNT<Stmt>().isBaseOf(DNT<IfStmt>(), &Distance));
+ EXPECT_TRUE(DNT<Stmt>().isBaseOf(DNT<IfStmt>(), Distance));
EXPECT_EQ(1u, Distance);
Distance = 3;
- EXPECT_TRUE(DNT<DeclaratorDecl>().isBaseOf(DNT<ParmVarDecl>(), &Distance));
+ EXPECT_TRUE(DNT<DeclaratorDecl>().isBaseOf(DNT<ParmVarDecl>(), Distance));
EXPECT_EQ(2u, Distance);
}
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits