r232726 - Devirtualize Attr and all subclasses.
Benjamin Kramer
benny.kra at googlemail.com
Thu Mar 19 09:06:49 PDT 2015
Author: d0k
Date: Thu Mar 19 11:06:49 2015
New Revision: 232726
URL: http://llvm.org/viewvc/llvm-project?rev=232726&view=rev
Log:
Devirtualize Attr and all subclasses.
We know all subclasses in tblgen so just generate a giant switch for
the few virtual methods or turn them into a member variable using spare
bits. The giant jump tables aren't pretty but still much smaller than
a vtable for every attribute, shrinking Release+Asserts clang by ~400k.
Also halves the size of the Attr base class. No functional change
intended.
Modified:
cfe/trunk/include/clang/AST/Attr.h
cfe/trunk/lib/AST/AttrImpl.cpp
cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp
Modified: cfe/trunk/include/clang/AST/Attr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Attr.h?rev=232726&r1=232725&r2=232726&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Attr.h (original)
+++ cfe/trunk/include/clang/AST/Attr.h Thu Mar 19 11:06:49 2015
@@ -52,8 +52,8 @@ protected:
bool Inherited : 1;
bool IsPackExpansion : 1;
bool Implicit : 1;
-
- virtual ~Attr();
+ bool IsLateParsed : 1;
+ bool DuplicatesAllowed : 1;
void* operator new(size_t bytes) throw() {
llvm_unreachable("Attrs cannot be allocated with regular 'new'.");
@@ -74,9 +74,11 @@ public:
}
protected:
- Attr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex = 0)
+ Attr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex,
+ bool IsLateParsed, bool DuplicatesAllowed)
: Range(R), AttrKind(AK), SpellingListIndex(SpellingListIndex),
- Inherited(false), IsPackExpansion(false), Implicit(false) {}
+ Inherited(false), IsPackExpansion(false), Implicit(false),
+ IsLateParsed(IsLateParsed), DuplicatesAllowed(DuplicatesAllowed) {}
public:
@@ -85,7 +87,7 @@ public:
}
unsigned getSpellingListIndex() const { return SpellingListIndex; }
- virtual const char *getSpelling() const = 0;
+ const char *getSpelling() const;
SourceLocation getLocation() const { return Range.getBegin(); }
SourceRange getRange() const { return Range; }
@@ -102,25 +104,24 @@ public:
bool isPackExpansion() const { return IsPackExpansion; }
// Clone this attribute.
- virtual Attr *clone(ASTContext &C) const = 0;
+ Attr *clone(ASTContext &C) const;
- virtual bool isLateParsed() const { return false; }
+ bool isLateParsed() const { return IsLateParsed; }
// Pretty print this attribute.
- virtual void printPretty(raw_ostream &OS,
- const PrintingPolicy &Policy) const = 0;
+ void printPretty(raw_ostream &OS, const PrintingPolicy &Policy) const;
/// \brief By default, attributes cannot be duplicated when being merged;
/// however, an attribute can override this. Returns true if the attribute
/// can be duplicated when merging.
- virtual bool duplicatesAllowed() const { return false; }
+ bool duplicatesAllowed() const { return DuplicatesAllowed; }
};
class InheritableAttr : public Attr {
- virtual void anchor();
protected:
- InheritableAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex = 0)
- : Attr(AK, R, SpellingListIndex) {}
+ InheritableAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex,
+ bool IsLateParsed, bool DuplicatesAllowed)
+ : Attr(AK, R, SpellingListIndex, IsLateParsed, DuplicatesAllowed) {}
public:
void setInherited(bool I) { Inherited = I; }
@@ -132,11 +133,11 @@ public:
};
class InheritableParamAttr : public InheritableAttr {
- void anchor() override;
protected:
- InheritableParamAttr(attr::Kind AK, SourceRange R,
- unsigned SpellingListIndex = 0)
- : InheritableAttr(AK, R, SpellingListIndex) {}
+ InheritableParamAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex,
+ bool IsLateParsed, bool DuplicatesAllowed)
+ : InheritableAttr(AK, R, SpellingListIndex, IsLateParsed,
+ DuplicatesAllowed) {}
public:
// Implement isa/cast/dyncast/etc.
Modified: cfe/trunk/lib/AST/AttrImpl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/AttrImpl.cpp?rev=232726&r1=232725&r2=232726&view=diff
==============================================================================
--- cfe/trunk/lib/AST/AttrImpl.cpp (original)
+++ cfe/trunk/lib/AST/AttrImpl.cpp Thu Mar 19 11:06:49 2015
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
//
-// This file contains out-of-line virtual methods for Attr classes.
+// This file contains out-of-line methods for Attr classes.
//
//===----------------------------------------------------------------------===//
@@ -18,10 +18,4 @@
#include "llvm/ADT/StringSwitch.h"
using namespace clang;
-Attr::~Attr() { }
-
-void InheritableAttr::anchor() { }
-
-void InheritableParamAttr::anchor() { }
-
#include "clang/AST/AttrImpl.inc"
Modified: cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp?rev=232726&r1=232725&r2=232726&view=diff
==============================================================================
--- cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp (original)
+++ cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp Thu Mar 19 11:06:49 2015
@@ -1520,7 +1520,9 @@ void EmitClangAttrClass(RecordKeeper &Re
OS << "unsigned SI\n";
OS << " )\n";
- OS << " : " << SuperName << "(attr::" << R.getName() << ", R, SI)\n";
+ OS << " : " << SuperName << "(attr::" << R.getName() << ", R, SI, "
+ << R.getValueAsBit("LateParsed") << ", "
+ << R.getValueAsBit("DuplicatesAllowedWhileMerging") << ")\n";
for (auto const &ai : Args) {
OS << " , ";
@@ -1552,7 +1554,9 @@ void EmitClangAttrClass(RecordKeeper &Re
OS << "unsigned SI\n";
OS << " )\n";
- OS << " : " << SuperName << "(attr::" << R.getName() << ", R, SI)\n";
+ OS << " : " << SuperName << "(attr::" << R.getName() << ", R, SI, "
+ << R.getValueAsBit("LateParsed") << ", "
+ << R.getValueAsBit("DuplicatesAllowedWhileMerging") << ")\n";
for (auto const &ai : Args) {
OS << " , ";
@@ -1571,10 +1575,10 @@ void EmitClangAttrClass(RecordKeeper &Re
OS << " }\n\n";
}
- OS << " " << R.getName() << "Attr *clone(ASTContext &C) const override;\n";
+ OS << " " << R.getName() << "Attr *clone(ASTContext &C) const;\n";
OS << " void printPretty(raw_ostream &OS,\n"
- << " const PrintingPolicy &Policy) const override;\n";
- OS << " const char *getSpelling() const override;\n";
+ << " const PrintingPolicy &Policy) const;\n";
+ OS << " const char *getSpelling() const;\n";
if (!ElideSpelling) {
assert(!SemanticToSyntacticMap.empty() && "Empty semantic mapping list");
@@ -1603,13 +1607,6 @@ void EmitClangAttrClass(RecordKeeper &Re
OS << " static bool classof(const Attr *A) { return A->getKind() == "
<< "attr::" << R.getName() << "; }\n";
- bool LateParsed = R.getValueAsBit("LateParsed");
- OS << " bool isLateParsed() const override { return "
- << LateParsed << "; }\n";
-
- if (R.getValueAsBit("DuplicatesAllowedWhileMerging"))
- OS << " bool duplicatesAllowed() const override { return true; }\n\n";
-
OS << "};\n\n";
}
@@ -1652,6 +1649,36 @@ void EmitClangAttrImpl(RecordKeeper &Rec
writePrettyPrintFunction(R, Args, OS);
writeGetSpellingFunction(R, OS);
}
+
+ // Instead of relying on virtual dispatch we just create a huge dispatch
+ // switch. This is both smaller and faster than virtual functions.
+ auto EmitFunc = [&](const char *Method) {
+ OS << " switch (getKind()) {\n";
+ for (const auto *Attr : Attrs) {
+ const Record &R = *Attr;
+ if (!R.getValueAsBit("ASTNode"))
+ continue;
+
+ OS << " case attr::" << R.getName() << ":\n";
+ OS << " return cast<" << R.getName() << "Attr>(this)->" << Method
+ << ";\n";
+ }
+ OS << " case attr::NUM_ATTRS:\n";
+ OS << " break;\n";
+ OS << " }\n";
+ OS << " llvm_unreachable(\"Unexpected attribute kind!\");\n";
+ OS << "}\n\n";
+ };
+
+ OS << "const char *Attr::getSpelling() const {\n";
+ EmitFunc("getSpelling()");
+
+ OS << "Attr *Attr::clone(ASTContext &C) const {\n";
+ EmitFunc("clone(C)");
+
+ OS << "void Attr::printPretty(raw_ostream &OS, "
+ "const PrintingPolicy &Policy) const {\n";
+ EmitFunc("printPretty(OS, Policy)");
}
} // end namespace clang
More information about the cfe-commits
mailing list