r232726 - Devirtualize Attr and all subclasses.
Rafael EspĂndola
rafael.espindola at gmail.com
Thu Mar 19 09:21:25 PDT 2015
Nice!
On 19 March 2015 at 12:06, Benjamin Kramer <benny.kra at googlemail.com> 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
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
More information about the cfe-commits
mailing list