Skip some unnecessary type checks.

Summary:
Skip some unnecessary type checks wrt DynTypedNodes.
Add DynTypedNode::getUnchecked() to skip the runtime check when the type
is known.
Speed up DynTypedNode::operator== by using isSame() instead of
isBaseOf().
Skip the type check in MatcherInterface<T>::matches(). All calls come
from DynTypedMatcher::matches(), which already did the type check.
This change speeds up our clang-tidy benchmark by ~4%.

Reviewers: klimek

Subscribers: klimek, cfe-commits

Differential Revision: http://reviews.llvm.org/D6468

llvm-svn: 223134
This commit is contained in:
Samuel Benzaquen 2014-12-02 18:29:00 +00:00
parent 54b7d334c7
commit b6f0a83f41
2 changed files with 31 additions and 11 deletions

View File

@ -145,6 +145,8 @@ private:
template <class T> struct KindToKindId {
static const NodeKindId Id = NKI_None;
};
template <class T>
struct KindToKindId<const T> : KindToKindId<T> {};
/// \brief Per kind info.
struct KindInfo {
@ -221,6 +223,14 @@ public:
return BaseConverter<T>::get(NodeKind, Storage.buffer);
}
/// \brief Retrieve the stored node as type \c T.
///
/// Similar to \c get(), but asserts that the type is what we are expecting.
template <typename T>
const T &getUnchecked() const {
return BaseConverter<T>::getUnchecked(NodeKind, Storage.buffer);
}
ASTNodeKind getNodeKind() const { return NodeKind; }
/// \brief Returns a pointer that identifies the stored AST node.
@ -251,14 +261,15 @@ public:
return getMemoizationData() < Other.getMemoizationData();
}
bool operator==(const DynTypedNode &Other) const {
if (!NodeKind.isBaseOf(Other.NodeKind) &&
!Other.NodeKind.isBaseOf(NodeKind))
// DynTypedNode::create() stores the exact kind of the node in NodeKind.
// If they contain the same node, their NodeKind must be the same.
if (!NodeKind.isSame(Other.NodeKind))
return false;
// FIXME: Implement for other types.
if (ASTNodeKind::getFromNodeKind<QualType>().isBaseOf(NodeKind)) {
return *get<QualType>() == *Other.get<QualType>();
}
if (ASTNodeKind::getFromNodeKind<QualType>().isSame(NodeKind))
return getUnchecked<QualType>() == Other.getUnchecked<QualType>();
assert(getMemoizationData() && Other.getMemoizationData());
return getMemoizationData() == Other.getMemoizationData();
}
@ -274,10 +285,14 @@ private:
/// \brief Converter that uses dyn_cast<T> from a stored BaseT*.
template <typename T, typename BaseT> struct DynCastPtrConverter {
static const T *get(ASTNodeKind NodeKind, const char Storage[]) {
if (ASTNodeKind::getFromNodeKind<BaseT>().isBaseOf(NodeKind))
return dyn_cast<T>(*reinterpret_cast<BaseT *const *>(Storage));
if (ASTNodeKind::getFromNodeKind<T>().isBaseOf(NodeKind))
return cast<T>(*reinterpret_cast<BaseT *const *>(Storage));
return nullptr;
}
static const T &getUnchecked(ASTNodeKind NodeKind, const char Storage[]) {
assert(ASTNodeKind::getFromNodeKind<T>().isBaseOf(NodeKind));
return *cast<T>(*reinterpret_cast<BaseT *const *>(Storage));
}
static DynTypedNode create(const BaseT &Node) {
DynTypedNode Result;
Result.NodeKind = ASTNodeKind::getFromNode(Node);
@ -294,6 +309,10 @@ private:
return *reinterpret_cast<T *const *>(Storage);
return nullptr;
}
static const T &getUnchecked(ASTNodeKind NodeKind, const char Storage[]) {
assert(ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind));
return **reinterpret_cast<T *const *>(Storage);
}
static DynTypedNode create(const T &Node) {
DynTypedNode Result;
Result.NodeKind = ASTNodeKind::getFromNodeKind<T>();
@ -310,6 +329,10 @@ private:
return reinterpret_cast<const T *>(Storage);
return nullptr;
}
static const T &getUnchecked(ASTNodeKind NodeKind, const char Storage[]) {
assert(ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind));
return *reinterpret_cast<const T *>(Storage);
}
static DynTypedNode create(const T &Node) {
DynTypedNode Result;
Result.NodeKind = ASTNodeKind::getFromNodeKind<T>();

View File

@ -218,10 +218,7 @@ public:
bool dynMatches(const ast_type_traits::DynTypedNode &DynNode,
ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const override {
if (const T *Node = DynNode.get<T>()) {
return matches(*Node, Finder, Builder);
}
return false;
return matches(DynNode.getUnchecked<T>(), Finder, Builder);
}
};