Nice!
On 19 March 2015 at 12:06, Benjamin Kramer <[email protected]> wrote: > 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 > > > _______________________________________________ > cfe-commits mailing list > [email protected] > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits _______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
