[clang] [clang] Optimize castToDeclContext for 2% improvement in build times (PR #76825)
https://github.com/Destroyerrrocket created https://github.com/llvm/llvm-project/pull/76825 None >From 1ab4538e194f9a77c500e4a93b1875eb7e76dcf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pol=20Marcet=20Sard=C3=A0?= Date: Wed, 3 Jan 2024 16:00:42 +0100 Subject: [PATCH] [clang] Optimize castToDeclContext for 2% improvement in build times --- clang/include/clang/AST/DeclCXX.h | 8 ++ clang/lib/AST/DeclBase.cpp| 50 +++- clang/utils/TableGen/ClangASTNodesEmitter.cpp | 107 +++--- clang/utils/TableGen/TableGen.cpp | 3 +- clang/utils/TableGen/TableGenBackends.h | 3 +- 5 files changed, 97 insertions(+), 74 deletions(-) diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index 432293583576b5..984a4d8bab5e77 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -2044,6 +2044,14 @@ class RequiresExprBodyDecl : public Decl, public DeclContext { // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == RequiresExprBody; } + + static DeclContext *castToDeclContext(const RequiresExprBodyDecl *D) { +return static_cast(const_cast(D)); + } + + static RequiresExprBodyDecl *castFromDeclContext(const DeclContext *DC) { +return static_cast(const_cast(DC)); + } }; /// Represents a static or instance method of a struct/union/class. diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index 5e03f0223d311c..b1733c2d052a65 100644 --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/lib/AST/DeclBase.cpp @@ -930,20 +930,14 @@ const AttrVec &Decl::getAttrs() const { Decl *Decl::castFromDeclContext (const DeclContext *D) { Decl::Kind DK = D->getDeclKind(); - switch(DK) { -#define DECL(NAME, BASE) -#define DECL_CONTEXT(NAME) \ -case Decl::NAME: \ - return static_cast(const_cast(D)); -#define DECL_CONTEXT_BASE(NAME) -#include "clang/AST/DeclNodes.inc" -default: + switch (DK) { #define DECL(NAME, BASE) -#define DECL_CONTEXT_BASE(NAME) \ - if (DK >= first##NAME && DK <= last##NAME) \ -return static_cast(const_cast(D)); +#define DECL_CONTEXT(NAME) \ + case Decl::NAME: \ +return static_cast(const_cast(D)); #include "clang/AST/DeclNodes.inc" - llvm_unreachable("a decl that inherits DeclContext isn't handled"); + default: +llvm_unreachable("a decl that inherits DeclContext isn't handled"); } } @@ -951,18 +945,12 @@ DeclContext *Decl::castToDeclContext(const Decl *D) { Decl::Kind DK = D->getKind(); switch(DK) { #define DECL(NAME, BASE) -#define DECL_CONTEXT(NAME) \ -case Decl::NAME: \ - return static_cast(const_cast(D)); -#define DECL_CONTEXT_BASE(NAME) +#define DECL_CONTEXT(NAME) \ + case Decl::NAME: \ +return static_cast(const_cast(D)); #include "clang/AST/DeclNodes.inc" -default: -#define DECL(NAME, BASE) -#define DECL_CONTEXT_BASE(NAME) \ - if (DK >= first##NAME && DK <= last##NAME) \ -return static_cast(const_cast(D)); -#include "clang/AST/DeclNodes.inc" - llvm_unreachable("a decl that inherits DeclContext isn't handled"); + default: +llvm_unreachable("a decl that inherits DeclContext isn't handled"); } } @@ -1129,20 +1117,14 @@ DeclContext::DeclContext(Decl::Kind K) { } bool DeclContext::classof(const Decl *D) { - switch (D->getKind()) { + Decl::Kind DK = D->getKind(); + switch (DK) { #define DECL(NAME, BASE) #define DECL_CONTEXT(NAME) case Decl::NAME: -#define DECL_CONTEXT_BASE(NAME) #include "clang/AST/DeclNodes.inc" - return true; -default: -#define DECL(NAME, BASE) -#define DECL_CONTEXT_BASE(NAME) \ - if (D->getKind() >= Decl::first##NAME && \ - D->getKind() <= Decl::last##NAME) \ -return true; -#include "clang/AST/DeclNodes.inc" - return false; +return true; + default: +return false; } } diff --git a/clang/utils/TableGen/ClangASTNodesEmitter.cpp b/clang/utils/TableGen/ClangASTNodesEmitter.cpp index 16a1c74b9d91ad..63220aad50aecd 100644 --- a/clang/utils/TableGen/ClangASTNodesEmitter.cpp +++ b/clang/utils/TableGen/ClangASTNodesEmitter.cpp @@ -33,6 +33,7 @@ class ClangASTNodesEmitter { typedef std::multimap ChildMap; typedef ChildMap::const_iterator ChildIterator; + std::set PrioritizedClasses; RecordKeeper &Records; ASTNode Root; const std::string &NodeClassName; @@ -70,8 +71,15 @@ class ClangASTNodesEmitter { std::pair EmitNode(raw_ostream& OS, ASTNode Base); public: explicit ClangASTNodesEmitter(RecordKeeper &R, const std::string &N, -
[clang] [clang] Optimize castToDeclContext for 2% improvement in build times (PR #76825)
github-actions[bot] wrote: Thank you for submitting a Pull Request (PR) to the LLVM Project! This PR will be automatically labeled and the relevant teams will be notified. If you wish to, you can add reviewers by using the "Reviewers" section on this page. If this is not working for you, it is probably because you do not have write permissions for the repository. In which case you can instead tag reviewers by name in a comment by using `@` followed by their GitHub username. If you have received no comments on your PR for a week, you can request a review by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate is once a week. Please remember that you are asking for valuable time from other developers. If you have further questions, they may be answered by the [LLVM GitHub User Guide](https://llvm.org/docs/GitHub.html). You can also ask questions in a comment on this PR, on the [LLVM Discord](https://discord.com/invite/xS7Z362) or on the [forums](https://discourse.llvm.org/). https://github.com/llvm/llvm-project/pull/76825 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Optimize castToDeclContext for 2% improvement in build times (PR #76825)
llvmbot wrote: @llvm/pr-subscribers-clang Author: Pol M (Destroyerrrocket) Changes --- Full diff: https://github.com/llvm/llvm-project/pull/76825.diff 5 Files Affected: - (modified) clang/include/clang/AST/DeclCXX.h (+8) - (modified) clang/lib/AST/DeclBase.cpp (+16-34) - (modified) clang/utils/TableGen/ClangASTNodesEmitter.cpp (+69-38) - (modified) clang/utils/TableGen/TableGen.cpp (+2-1) - (modified) clang/utils/TableGen/TableGenBackends.h (+2-1) ``diff diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index 432293583576b5..984a4d8bab5e77 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -2044,6 +2044,14 @@ class RequiresExprBodyDecl : public Decl, public DeclContext { // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == RequiresExprBody; } + + static DeclContext *castToDeclContext(const RequiresExprBodyDecl *D) { +return static_cast(const_cast(D)); + } + + static RequiresExprBodyDecl *castFromDeclContext(const DeclContext *DC) { +return static_cast(const_cast(DC)); + } }; /// Represents a static or instance method of a struct/union/class. diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index 5e03f0223d311c..b1733c2d052a65 100644 --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/lib/AST/DeclBase.cpp @@ -930,20 +930,14 @@ const AttrVec &Decl::getAttrs() const { Decl *Decl::castFromDeclContext (const DeclContext *D) { Decl::Kind DK = D->getDeclKind(); - switch(DK) { -#define DECL(NAME, BASE) -#define DECL_CONTEXT(NAME) \ -case Decl::NAME: \ - return static_cast(const_cast(D)); -#define DECL_CONTEXT_BASE(NAME) -#include "clang/AST/DeclNodes.inc" -default: + switch (DK) { #define DECL(NAME, BASE) -#define DECL_CONTEXT_BASE(NAME) \ - if (DK >= first##NAME && DK <= last##NAME) \ -return static_cast(const_cast(D)); +#define DECL_CONTEXT(NAME) \ + case Decl::NAME: \ +return static_cast(const_cast(D)); #include "clang/AST/DeclNodes.inc" - llvm_unreachable("a decl that inherits DeclContext isn't handled"); + default: +llvm_unreachable("a decl that inherits DeclContext isn't handled"); } } @@ -951,18 +945,12 @@ DeclContext *Decl::castToDeclContext(const Decl *D) { Decl::Kind DK = D->getKind(); switch(DK) { #define DECL(NAME, BASE) -#define DECL_CONTEXT(NAME) \ -case Decl::NAME: \ - return static_cast(const_cast(D)); -#define DECL_CONTEXT_BASE(NAME) +#define DECL_CONTEXT(NAME) \ + case Decl::NAME: \ +return static_cast(const_cast(D)); #include "clang/AST/DeclNodes.inc" -default: -#define DECL(NAME, BASE) -#define DECL_CONTEXT_BASE(NAME) \ - if (DK >= first##NAME && DK <= last##NAME) \ -return static_cast(const_cast(D)); -#include "clang/AST/DeclNodes.inc" - llvm_unreachable("a decl that inherits DeclContext isn't handled"); + default: +llvm_unreachable("a decl that inherits DeclContext isn't handled"); } } @@ -1129,20 +1117,14 @@ DeclContext::DeclContext(Decl::Kind K) { } bool DeclContext::classof(const Decl *D) { - switch (D->getKind()) { + Decl::Kind DK = D->getKind(); + switch (DK) { #define DECL(NAME, BASE) #define DECL_CONTEXT(NAME) case Decl::NAME: -#define DECL_CONTEXT_BASE(NAME) #include "clang/AST/DeclNodes.inc" - return true; -default: -#define DECL(NAME, BASE) -#define DECL_CONTEXT_BASE(NAME) \ - if (D->getKind() >= Decl::first##NAME && \ - D->getKind() <= Decl::last##NAME) \ -return true; -#include "clang/AST/DeclNodes.inc" - return false; +return true; + default: +return false; } } diff --git a/clang/utils/TableGen/ClangASTNodesEmitter.cpp b/clang/utils/TableGen/ClangASTNodesEmitter.cpp index 16a1c74b9d91ad..63220aad50aecd 100644 --- a/clang/utils/TableGen/ClangASTNodesEmitter.cpp +++ b/clang/utils/TableGen/ClangASTNodesEmitter.cpp @@ -33,6 +33,7 @@ class ClangASTNodesEmitter { typedef std::multimap ChildMap; typedef ChildMap::const_iterator ChildIterator; + std::set PrioritizedClasses; RecordKeeper &Records; ASTNode Root; const std::string &NodeClassName; @@ -70,8 +71,15 @@ class ClangASTNodesEmitter { std::pair EmitNode(raw_ostream& OS, ASTNode Base); public: explicit ClangASTNodesEmitter(RecordKeeper &R, const std::string &N, -const std::string &S) -: Records(R), NodeClassName(N), BaseSuffix(S) {} +const std::string &S, +const std::string &Prio
[clang] [clang] Optimize castToDeclContext for 2% improvement in build times (PR #76825)
nikic wrote: https://llvm-compile-time-tracker.com/compare.php?from=98624914367bf9091919de330cf322fb6d5e468f&to=7d398e29b0180aacc646fed5406ad7fbd4b30c02&stat=instructions%3Au Nice results for C++ code! https://github.com/llvm/llvm-project/pull/76825 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Optimize castToDeclContext for 2% improvement in build times (PR #76825)
Destroyerrrocket wrote: Yeah, I also saw that in O3 most of the compile time is overshadowed by LLVM, so it makes perfect sense that the -O0 are the ones showing better results! https://github.com/llvm/llvm-project/pull/76825 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Optimize castToDeclContext for 2% improvement in build times (PR #76825)
https://github.com/shafik commented: Please add a detailed summary for this PR. The summary is what usually goes into the git log and it is important that the git log is useful for quick understanding of changes without having to dig into the details. https://github.com/llvm/llvm-project/pull/76825 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Optimize castToDeclContext for 2% improvement in build times (PR #76825)
https://github.com/shafik edited https://github.com/llvm/llvm-project/pull/76825 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Optimize castToDeclContext for 2% improvement in build times (PR #76825)
https://github.com/Destroyerrrocket edited https://github.com/llvm/llvm-project/pull/76825 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Optimize castToDeclContext for 2% improvement in build times (PR #76825)
Destroyerrrocket wrote: Copied description from the issue that tracks this PR (sorry, I'm away from my PC) https://github.com/llvm/llvm-project/pull/76825 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Optimize castToDeclContext for 2% improvement in build times (PR #76825)
https://github.com/Destroyerrrocket edited https://github.com/llvm/llvm-project/pull/76825 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Optimize castToDeclContext for 2% improvement in build times (PR #76825)
https://github.com/Endilll edited https://github.com/llvm/llvm-project/pull/76825 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Optimize castToDeclContext for 2% improvement in build times (PR #76825)
https://github.com/Endilll commented: Core idea of removing `DECL_CONTEXT_BASE` and range checks for `DeclContext` nodes seems correct to me, as all this machinery wasn't intended for `DeclContext` in the first place. This is apparent from TableGen definition, which lacks any base parameter: https://github.com/llvm/llvm-project/blob/463dad107f4cb60ae1d49138143d6797599fb1fb/clang/include/clang/Basic/DeclNodes.td#L10 But changes made to `ClangASTNodesEmitter.cpp` are not as clear to me. I'd expect it to simply opt out `DeclContext` nodes from some code generation, but instead I see a lot of changes concerned with `PrioritizedClasses`. It would be nice if you explain what's going on in that file. https://github.com/llvm/llvm-project/pull/76825 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Optimize castToDeclContext for 2% improvement in build times (PR #76825)
@@ -210,38 +253,26 @@ void clang::EmitClangDeclContext(RecordKeeper &Records, raw_ostream &OS) { OS << "#ifndef DECL_CONTEXT\n"; OS << "# define DECL_CONTEXT(DECL)\n"; OS << "#endif\n"; - - OS << "#ifndef DECL_CONTEXT_BASE\n"; - OS << "# define DECL_CONTEXT_BASE(DECL) DECL_CONTEXT(DECL)\n"; - OS << "#endif\n"; - - typedef std::set RecordSet; - typedef std::vector RecordVector; - - RecordVector DeclContextsVector -= Records.getAllDerivedDefinitions(DeclContextNodeClassName); - RecordVector Decls = Records.getAllDerivedDefinitions(DeclNodeClassName); - RecordSet DeclContexts (DeclContextsVector.begin(), DeclContextsVector.end()); - - for (RecordVector::iterator i = Decls.begin(), e = Decls.end(); i != e; ++i) { -Record *R = *i; - -if (Record *B = R->getValueAsOptionalDef(BaseFieldName)) { - if (DeclContexts.find(B) != DeclContexts.end()) { -OS << "DECL_CONTEXT_BASE(" << B->getName() << ")\n"; -DeclContexts.erase(B); - } -} + + std::vector DeclContextsVector = + Records.getAllDerivedDefinitions(DeclContextNodeClassName); + std::vector Decls = + Records.getAllDerivedDefinitions(DeclNodeClassName); + + std::multimap Tree; + + const std::vector Stmts = + Records.getAllDerivedDefinitions(DeclNodeClassName); + + for (unsigned i = 0, e = Stmts.size(); i != e; ++i) { Endilll wrote: Is there a reason to avoid range-based `for` loop here? https://github.com/llvm/llvm-project/pull/76825 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Optimize castToDeclContext for 2% improvement in build times (PR #76825)
@@ -196,8 +227,20 @@ void ClangASTNodesEmitter::run(raw_ostream &OS) { } void clang::EmitClangASTNodes(RecordKeeper &RK, raw_ostream &OS, - const std::string &N, const std::string &S) { - ClangASTNodesEmitter(RK, N, S).run(OS); + const std::string &N, const std::string &S, + const std::string &PriorizeIfSubclassOf) { Endilll wrote: Why `const std::string &` instead of `std::string_view`? https://github.com/llvm/llvm-project/pull/76825 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Optimize castToDeclContext for 2% improvement in build times (PR #76825)
@@ -95,8 +103,31 @@ std::pair ClangASTNodesEmitter::EmitNode(raw_ostream &OS, if (!Base.isAbstract()) First = Last = Base; + class Comp { Endilll wrote: This class looks like a hand-written lambda closure type. Do we really need it in this form? https://github.com/llvm/llvm-project/pull/76825 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Optimize castToDeclContext for 2% improvement in build times (PR #76825)
@@ -95,8 +103,31 @@ std::pair ClangASTNodesEmitter::EmitNode(raw_ostream &OS, if (!Base.isAbstract()) First = Last = Base; + class Comp { cor3ntin wrote: Yes, this might as well be a lambda. I also think some comment to explain what PriorizeIfSubclassOf is and why it is used would be useful; We might very well forget why we put classes that are declcontext first in the future. https://github.com/llvm/llvm-project/pull/76825 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Optimize castToDeclContext for 2% improvement in build times (PR #76825)
Destroyerrrocket wrote: The reason for puting the classes with DeclContext closer together is to achieve a better code generation. Here's an example of the asssembly with just the removal of the DECL_CONTEXT_BASE macro: ``` clang::Decl::castToDeclContext(clang::Decl const*): # @clang::Decl::castToDeclContext(clang::Decl const*) .L_ZN5clang4Decl17castToDeclContextEPKS0_$local: movl 28(%rdi), %edx leaq .LJTI66_0(%rip), %rsi movq %rdi, %rax movl $40, %ecx andl $127, %edx decl %edx movslq (%rsi,%rdx,4), %rdx addq %rsi, %rdx jmpq *%rdx .LBB66_5: movl $48, %ecx addq %rcx, %rax retq .LBB66_1: addq %rcx, %rax retq .LBB66_2: movl $72, %ecx addq %rcx, %rax retq .LBB66_6: movl $64, %ecx addq %rcx, %rax retq .LBB66_7: movl $56, %ecx addq %rcx, %rax retq .LBB66_8: .LJTI66_0: ``` While this is better, it is still not performing ideally compared to just the load and an add of the final implementation. I'm of course open to suggestions if there is a better way of getting llvm to emit the right thing. I agree with @cor3ntin that a comment explaining the need for this order priorization is needed. https://github.com/llvm/llvm-project/pull/76825 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Optimize castToDeclContext for 2% improvement in build times (PR #76825)
@@ -95,8 +103,31 @@ std::pair ClangASTNodesEmitter::EmitNode(raw_ostream &OS, if (!Base.isAbstract()) First = Last = Base; + class Comp { Destroyerrrocket wrote: I'll make this a lambda https://github.com/llvm/llvm-project/pull/76825 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Optimize castToDeclContext for 2% improvement in build times (PR #76825)
@@ -196,8 +227,20 @@ void ClangASTNodesEmitter::run(raw_ostream &OS) { } void clang::EmitClangASTNodes(RecordKeeper &RK, raw_ostream &OS, - const std::string &N, const std::string &S) { - ClangASTNodesEmitter(RK, N, S).run(OS); + const std::string &N, const std::string &S, + const std::string &PriorizeIfSubclassOf) { Destroyerrrocket wrote: Conformity with surrounding code. I code like I see to not introduce another style. I can switch to std::string_view if you wish so! https://github.com/llvm/llvm-project/pull/76825 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Optimize castToDeclContext for 2% improvement in build times (PR #76825)
@@ -210,38 +253,26 @@ void clang::EmitClangDeclContext(RecordKeeper &Records, raw_ostream &OS) { OS << "#ifndef DECL_CONTEXT\n"; OS << "# define DECL_CONTEXT(DECL)\n"; OS << "#endif\n"; - - OS << "#ifndef DECL_CONTEXT_BASE\n"; - OS << "# define DECL_CONTEXT_BASE(DECL) DECL_CONTEXT(DECL)\n"; - OS << "#endif\n"; - - typedef std::set RecordSet; - typedef std::vector RecordVector; - - RecordVector DeclContextsVector -= Records.getAllDerivedDefinitions(DeclContextNodeClassName); - RecordVector Decls = Records.getAllDerivedDefinitions(DeclNodeClassName); - RecordSet DeclContexts (DeclContextsVector.begin(), DeclContextsVector.end()); - - for (RecordVector::iterator i = Decls.begin(), e = Decls.end(); i != e; ++i) { -Record *R = *i; - -if (Record *B = R->getValueAsOptionalDef(BaseFieldName)) { - if (DeclContexts.find(B) != DeclContexts.end()) { -OS << "DECL_CONTEXT_BASE(" << B->getName() << ")\n"; -DeclContexts.erase(B); - } -} + + std::vector DeclContextsVector = + Records.getAllDerivedDefinitions(DeclContextNodeClassName); + std::vector Decls = + Records.getAllDerivedDefinitions(DeclNodeClassName); + + std::multimap Tree; + + const std::vector Stmts = + Records.getAllDerivedDefinitions(DeclNodeClassName); + + for (unsigned i = 0, e = Stmts.size(); i != e; ++i) { Destroyerrrocket wrote: I copied over the Tree implementation a few lines up with some code removed. I will update both for loops, it certainly would improve readability. https://github.com/llvm/llvm-project/pull/76825 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Optimize castToDeclContext for 2% improvement in build times (PR #76825)
Pol Marcet =?utf-8?q?Sardà?= Message-ID: In-Reply-To: https://github.com/Destroyerrrocket updated https://github.com/llvm/llvm-project/pull/76825 >From 1ab4538e194f9a77c500e4a93b1875eb7e76dcf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pol=20Marcet=20Sard=C3=A0?= Date: Wed, 3 Jan 2024 16:00:42 +0100 Subject: [PATCH 1/2] [clang] Optimize castToDeclContext for 2% improvement in build times --- clang/include/clang/AST/DeclCXX.h | 8 ++ clang/lib/AST/DeclBase.cpp| 50 +++- clang/utils/TableGen/ClangASTNodesEmitter.cpp | 107 +++--- clang/utils/TableGen/TableGen.cpp | 3 +- clang/utils/TableGen/TableGenBackends.h | 3 +- 5 files changed, 97 insertions(+), 74 deletions(-) diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index 432293583576b5..984a4d8bab5e77 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -2044,6 +2044,14 @@ class RequiresExprBodyDecl : public Decl, public DeclContext { // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == RequiresExprBody; } + + static DeclContext *castToDeclContext(const RequiresExprBodyDecl *D) { +return static_cast(const_cast(D)); + } + + static RequiresExprBodyDecl *castFromDeclContext(const DeclContext *DC) { +return static_cast(const_cast(DC)); + } }; /// Represents a static or instance method of a struct/union/class. diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index 5e03f0223d311c..b1733c2d052a65 100644 --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/lib/AST/DeclBase.cpp @@ -930,20 +930,14 @@ const AttrVec &Decl::getAttrs() const { Decl *Decl::castFromDeclContext (const DeclContext *D) { Decl::Kind DK = D->getDeclKind(); - switch(DK) { -#define DECL(NAME, BASE) -#define DECL_CONTEXT(NAME) \ -case Decl::NAME: \ - return static_cast(const_cast(D)); -#define DECL_CONTEXT_BASE(NAME) -#include "clang/AST/DeclNodes.inc" -default: + switch (DK) { #define DECL(NAME, BASE) -#define DECL_CONTEXT_BASE(NAME) \ - if (DK >= first##NAME && DK <= last##NAME) \ -return static_cast(const_cast(D)); +#define DECL_CONTEXT(NAME) \ + case Decl::NAME: \ +return static_cast(const_cast(D)); #include "clang/AST/DeclNodes.inc" - llvm_unreachable("a decl that inherits DeclContext isn't handled"); + default: +llvm_unreachable("a decl that inherits DeclContext isn't handled"); } } @@ -951,18 +945,12 @@ DeclContext *Decl::castToDeclContext(const Decl *D) { Decl::Kind DK = D->getKind(); switch(DK) { #define DECL(NAME, BASE) -#define DECL_CONTEXT(NAME) \ -case Decl::NAME: \ - return static_cast(const_cast(D)); -#define DECL_CONTEXT_BASE(NAME) +#define DECL_CONTEXT(NAME) \ + case Decl::NAME: \ +return static_cast(const_cast(D)); #include "clang/AST/DeclNodes.inc" -default: -#define DECL(NAME, BASE) -#define DECL_CONTEXT_BASE(NAME) \ - if (DK >= first##NAME && DK <= last##NAME) \ -return static_cast(const_cast(D)); -#include "clang/AST/DeclNodes.inc" - llvm_unreachable("a decl that inherits DeclContext isn't handled"); + default: +llvm_unreachable("a decl that inherits DeclContext isn't handled"); } } @@ -1129,20 +1117,14 @@ DeclContext::DeclContext(Decl::Kind K) { } bool DeclContext::classof(const Decl *D) { - switch (D->getKind()) { + Decl::Kind DK = D->getKind(); + switch (DK) { #define DECL(NAME, BASE) #define DECL_CONTEXT(NAME) case Decl::NAME: -#define DECL_CONTEXT_BASE(NAME) #include "clang/AST/DeclNodes.inc" - return true; -default: -#define DECL(NAME, BASE) -#define DECL_CONTEXT_BASE(NAME) \ - if (D->getKind() >= Decl::first##NAME && \ - D->getKind() <= Decl::last##NAME) \ -return true; -#include "clang/AST/DeclNodes.inc" - return false; +return true; + default: +return false; } } diff --git a/clang/utils/TableGen/ClangASTNodesEmitter.cpp b/clang/utils/TableGen/ClangASTNodesEmitter.cpp index 16a1c74b9d91ad..63220aad50aecd 100644 --- a/clang/utils/TableGen/ClangASTNodesEmitter.cpp +++ b/clang/utils/TableGen/ClangASTNodesEmitter.cpp @@ -33,6 +33,7 @@ class ClangASTNodesEmitter { typedef std::multimap ChildMap; typedef ChildMap::const_iterator ChildIterator; + std::set PrioritizedClasses; RecordKeeper &Records; ASTNode Root; const std::string &NodeClassName; @@ -70,8 +71,15 @@ class ClangASTNodesEmitter { std::pair EmitNode(raw_ostream& OS, ASTNode Base); public: explicit ClangASTNod
[clang] [clang] Optimize castToDeclContext for 2% improvement in build times (PR #76825)
Pol Marcet =?utf-8?q?Sardà?= Message-ID: In-Reply-To: Destroyerrrocket wrote: Addressed the first review comments! Thank you for your time, I appreciate it :) https://github.com/llvm/llvm-project/pull/76825 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Optimize castToDeclContext for 2% improvement in build times (PR #76825)
Pol Marcet =?utf-8?q?Sardà?= Message-ID: In-Reply-To: https://github.com/Endilll edited https://github.com/llvm/llvm-project/pull/76825 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Optimize castToDeclContext for 2% improvement in build times (PR #76825)
Pol Marcet =?utf-8?q?Sardà?= Message-ID: In-Reply-To: @@ -95,8 +103,23 @@ std::pair ClangASTNodesEmitter::EmitNode(raw_ostream &OS, if (!Base.isAbstract()) First = Last = Base; + auto comp = [this](ASTNode LHS, ASTNode RHS) { +auto LHSPriorized = PrioritizedClasses.count(LHS) > 0; Endilll wrote: ```suggestion auto LHSPrioritized = PrioritizedClasses.count(LHS) > 0; ``` https://github.com/llvm/llvm-project/pull/76825 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Optimize castToDeclContext for 2% improvement in build times (PR #76825)
Pol Marcet =?utf-8?q?Sard=C3=A0?= Message-ID: In-Reply-To: https://github.com/Endilll approved this pull request. LGTM, but you should wait for more approvals before merging. https://github.com/llvm/llvm-project/pull/76825 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Optimize castToDeclContext for 2% improvement in build times (PR #76825)
Pol Marcet =?utf-8?q?Sard=C3=A0?= Message-ID: In-Reply-To: @@ -70,8 +71,15 @@ class ClangASTNodesEmitter { std::pair EmitNode(raw_ostream& OS, ASTNode Base); public: explicit ClangASTNodesEmitter(RecordKeeper &R, const std::string &N, -const std::string &S) -: Records(R), NodeClassName(N), BaseSuffix(S) {} +const std::string &S, +std::string_view PriorizeIfSubclassOf) + : Records(R), NodeClassName(N), BaseSuffix(S) { +auto vecPriorized = PriorizeIfSubclassOf.empty() Endilll wrote: ```suggestion auto vecPrioritized = PriorizeIfSubclassOf.empty() ``` https://github.com/llvm/llvm-project/pull/76825 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Optimize castToDeclContext for 2% improvement in build times (PR #76825)
Pol Marcet =?utf-8?q?Sardà?= Message-ID: In-Reply-To: https://github.com/cor3ntin edited https://github.com/llvm/llvm-project/pull/76825 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Optimize castToDeclContext for 2% improvement in build times (PR #76825)
Pol Marcet =?utf-8?q?Sard=C3=A0?= Message-ID: In-Reply-To: @@ -196,8 +217,20 @@ void ClangASTNodesEmitter::run(raw_ostream &OS) { } void clang::EmitClangASTNodes(RecordKeeper &RK, raw_ostream &OS, - const std::string &N, const std::string &S) { - ClangASTNodesEmitter(RK, N, S).run(OS); + const std::string &N, const std::string &S, + std::string_view PriorizeIfSubclassOf) { + ClangASTNodesEmitter(RK, N, S, PriorizeIfSubclassOf).run(OS); +} + +void printDeclContext(std::multimap &Tree, cor3ntin wrote: ```suggestion void printDeclContext(const std::multimap &Tree, ``` https://github.com/llvm/llvm-project/pull/76825 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Optimize castToDeclContext for 2% improvement in build times (PR #76825)
Pol Marcet =?utf-8?q?Sard=C3=A0?= Message-ID: In-Reply-To: https://github.com/cor3ntin approved this pull request. LGTM. 1% is a very consequential improvement, congrats! https://github.com/llvm/llvm-project/pull/76825 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Optimize castToDeclContext for 2% improvement in build times (PR #76825)
Pol Marcet =?utf-8?q?Sardà?= Message-ID: In-Reply-To: Destroyerrrocket wrote: Thank you! I truly appreciate the congrats! :D @Endilll I don't have write access (I think? I'm new here :) ), I think one of you will have to make the merge (not used to github, at work I use bitbucket, I might be wrong, I'm basing this on "Only those with [write access](https://docs.github.com/articles/what-are-the-different-access-permissions) to this repository can merge pull requests.") https://github.com/llvm/llvm-project/pull/76825 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Optimize castToDeclContext for 2% improvement in build times (PR #76825)
Pol Marcet =?utf-8?q?Sardà?= , Pol Marcet =?utf-8?q?Sardà?= Message-ID: In-Reply-To: https://github.com/Destroyerrrocket updated https://github.com/llvm/llvm-project/pull/76825 >From 1ab4538e194f9a77c500e4a93b1875eb7e76dcf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pol=20Marcet=20Sard=C3=A0?= Date: Wed, 3 Jan 2024 16:00:42 +0100 Subject: [PATCH 1/3] [clang] Optimize castToDeclContext for 2% improvement in build times --- clang/include/clang/AST/DeclCXX.h | 8 ++ clang/lib/AST/DeclBase.cpp| 50 +++- clang/utils/TableGen/ClangASTNodesEmitter.cpp | 107 +++--- clang/utils/TableGen/TableGen.cpp | 3 +- clang/utils/TableGen/TableGenBackends.h | 3 +- 5 files changed, 97 insertions(+), 74 deletions(-) diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index 432293583576b5..984a4d8bab5e77 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -2044,6 +2044,14 @@ class RequiresExprBodyDecl : public Decl, public DeclContext { // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == RequiresExprBody; } + + static DeclContext *castToDeclContext(const RequiresExprBodyDecl *D) { +return static_cast(const_cast(D)); + } + + static RequiresExprBodyDecl *castFromDeclContext(const DeclContext *DC) { +return static_cast(const_cast(DC)); + } }; /// Represents a static or instance method of a struct/union/class. diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index 5e03f0223d311c..b1733c2d052a65 100644 --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/lib/AST/DeclBase.cpp @@ -930,20 +930,14 @@ const AttrVec &Decl::getAttrs() const { Decl *Decl::castFromDeclContext (const DeclContext *D) { Decl::Kind DK = D->getDeclKind(); - switch(DK) { -#define DECL(NAME, BASE) -#define DECL_CONTEXT(NAME) \ -case Decl::NAME: \ - return static_cast(const_cast(D)); -#define DECL_CONTEXT_BASE(NAME) -#include "clang/AST/DeclNodes.inc" -default: + switch (DK) { #define DECL(NAME, BASE) -#define DECL_CONTEXT_BASE(NAME) \ - if (DK >= first##NAME && DK <= last##NAME) \ -return static_cast(const_cast(D)); +#define DECL_CONTEXT(NAME) \ + case Decl::NAME: \ +return static_cast(const_cast(D)); #include "clang/AST/DeclNodes.inc" - llvm_unreachable("a decl that inherits DeclContext isn't handled"); + default: +llvm_unreachable("a decl that inherits DeclContext isn't handled"); } } @@ -951,18 +945,12 @@ DeclContext *Decl::castToDeclContext(const Decl *D) { Decl::Kind DK = D->getKind(); switch(DK) { #define DECL(NAME, BASE) -#define DECL_CONTEXT(NAME) \ -case Decl::NAME: \ - return static_cast(const_cast(D)); -#define DECL_CONTEXT_BASE(NAME) +#define DECL_CONTEXT(NAME) \ + case Decl::NAME: \ +return static_cast(const_cast(D)); #include "clang/AST/DeclNodes.inc" -default: -#define DECL(NAME, BASE) -#define DECL_CONTEXT_BASE(NAME) \ - if (DK >= first##NAME && DK <= last##NAME) \ -return static_cast(const_cast(D)); -#include "clang/AST/DeclNodes.inc" - llvm_unreachable("a decl that inherits DeclContext isn't handled"); + default: +llvm_unreachable("a decl that inherits DeclContext isn't handled"); } } @@ -1129,20 +1117,14 @@ DeclContext::DeclContext(Decl::Kind K) { } bool DeclContext::classof(const Decl *D) { - switch (D->getKind()) { + Decl::Kind DK = D->getKind(); + switch (DK) { #define DECL(NAME, BASE) #define DECL_CONTEXT(NAME) case Decl::NAME: -#define DECL_CONTEXT_BASE(NAME) #include "clang/AST/DeclNodes.inc" - return true; -default: -#define DECL(NAME, BASE) -#define DECL_CONTEXT_BASE(NAME) \ - if (D->getKind() >= Decl::first##NAME && \ - D->getKind() <= Decl::last##NAME) \ -return true; -#include "clang/AST/DeclNodes.inc" - return false; +return true; + default: +return false; } } diff --git a/clang/utils/TableGen/ClangASTNodesEmitter.cpp b/clang/utils/TableGen/ClangASTNodesEmitter.cpp index 16a1c74b9d91ad..63220aad50aecd 100644 --- a/clang/utils/TableGen/ClangASTNodesEmitter.cpp +++ b/clang/utils/TableGen/ClangASTNodesEmitter.cpp @@ -33,6 +33,7 @@ class ClangASTNodesEmitter { typedef std::multimap ChildMap; typedef ChildMap::const_iterator ChildIterator; + std::set PrioritizedClasses; RecordKeeper &Records; ASTNode Root; const std::string &NodeClassName; @@ -70,8 +71,15 @@ class ClangASTNodesEmitter { std::pair EmitNode(raw_ostream& OS, ASTNode Base);
[clang] [clang] Optimize castToDeclContext for 2% improvement in build times (PR #76825)
Pol Marcet =?utf-8?q?Sardà?= , Pol Marcet =?utf-8?q?Sardà?= ,Pol M Message-ID: In-Reply-To: https://github.com/Destroyerrrocket updated https://github.com/llvm/llvm-project/pull/76825 >From 1ab4538e194f9a77c500e4a93b1875eb7e76dcf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pol=20Marcet=20Sard=C3=A0?= Date: Wed, 3 Jan 2024 16:00:42 +0100 Subject: [PATCH 1/4] [clang] Optimize castToDeclContext for 2% improvement in build times --- clang/include/clang/AST/DeclCXX.h | 8 ++ clang/lib/AST/DeclBase.cpp| 50 +++- clang/utils/TableGen/ClangASTNodesEmitter.cpp | 107 +++--- clang/utils/TableGen/TableGen.cpp | 3 +- clang/utils/TableGen/TableGenBackends.h | 3 +- 5 files changed, 97 insertions(+), 74 deletions(-) diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index 432293583576b5..984a4d8bab5e77 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -2044,6 +2044,14 @@ class RequiresExprBodyDecl : public Decl, public DeclContext { // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == RequiresExprBody; } + + static DeclContext *castToDeclContext(const RequiresExprBodyDecl *D) { +return static_cast(const_cast(D)); + } + + static RequiresExprBodyDecl *castFromDeclContext(const DeclContext *DC) { +return static_cast(const_cast(DC)); + } }; /// Represents a static or instance method of a struct/union/class. diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index 5e03f0223d311c..b1733c2d052a65 100644 --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/lib/AST/DeclBase.cpp @@ -930,20 +930,14 @@ const AttrVec &Decl::getAttrs() const { Decl *Decl::castFromDeclContext (const DeclContext *D) { Decl::Kind DK = D->getDeclKind(); - switch(DK) { -#define DECL(NAME, BASE) -#define DECL_CONTEXT(NAME) \ -case Decl::NAME: \ - return static_cast(const_cast(D)); -#define DECL_CONTEXT_BASE(NAME) -#include "clang/AST/DeclNodes.inc" -default: + switch (DK) { #define DECL(NAME, BASE) -#define DECL_CONTEXT_BASE(NAME) \ - if (DK >= first##NAME && DK <= last##NAME) \ -return static_cast(const_cast(D)); +#define DECL_CONTEXT(NAME) \ + case Decl::NAME: \ +return static_cast(const_cast(D)); #include "clang/AST/DeclNodes.inc" - llvm_unreachable("a decl that inherits DeclContext isn't handled"); + default: +llvm_unreachable("a decl that inherits DeclContext isn't handled"); } } @@ -951,18 +945,12 @@ DeclContext *Decl::castToDeclContext(const Decl *D) { Decl::Kind DK = D->getKind(); switch(DK) { #define DECL(NAME, BASE) -#define DECL_CONTEXT(NAME) \ -case Decl::NAME: \ - return static_cast(const_cast(D)); -#define DECL_CONTEXT_BASE(NAME) +#define DECL_CONTEXT(NAME) \ + case Decl::NAME: \ +return static_cast(const_cast(D)); #include "clang/AST/DeclNodes.inc" -default: -#define DECL(NAME, BASE) -#define DECL_CONTEXT_BASE(NAME) \ - if (DK >= first##NAME && DK <= last##NAME) \ -return static_cast(const_cast(D)); -#include "clang/AST/DeclNodes.inc" - llvm_unreachable("a decl that inherits DeclContext isn't handled"); + default: +llvm_unreachable("a decl that inherits DeclContext isn't handled"); } } @@ -1129,20 +1117,14 @@ DeclContext::DeclContext(Decl::Kind K) { } bool DeclContext::classof(const Decl *D) { - switch (D->getKind()) { + Decl::Kind DK = D->getKind(); + switch (DK) { #define DECL(NAME, BASE) #define DECL_CONTEXT(NAME) case Decl::NAME: -#define DECL_CONTEXT_BASE(NAME) #include "clang/AST/DeclNodes.inc" - return true; -default: -#define DECL(NAME, BASE) -#define DECL_CONTEXT_BASE(NAME) \ - if (D->getKind() >= Decl::first##NAME && \ - D->getKind() <= Decl::last##NAME) \ -return true; -#include "clang/AST/DeclNodes.inc" - return false; +return true; + default: +return false; } } diff --git a/clang/utils/TableGen/ClangASTNodesEmitter.cpp b/clang/utils/TableGen/ClangASTNodesEmitter.cpp index 16a1c74b9d91ad..63220aad50aecd 100644 --- a/clang/utils/TableGen/ClangASTNodesEmitter.cpp +++ b/clang/utils/TableGen/ClangASTNodesEmitter.cpp @@ -33,6 +33,7 @@ class ClangASTNodesEmitter { typedef std::multimap ChildMap; typedef ChildMap::const_iterator ChildIterator; + std::set PrioritizedClasses; RecordKeeper &Records; ASTNode Root; const std::string &NodeClassName; @@ -70,8 +71,15 @@ class ClangASTNodesEmitter { std::pair EmitNode(raw_ostream& OS, ASTNode
[clang] [clang] Optimize castToDeclContext for 2% improvement in build times (PR #76825)
Pol Marcet =?utf-8?q?Sardà?= , Pol Marcet =?utf-8?q?Sardà?= ,Pol M Message-ID: In-Reply-To: Endilll wrote: @Destroyerrrocket We'll merge as soon as you deem it ready and provide commit description. PR description doesn't seem a good fit for a commit description to me. https://github.com/llvm/llvm-project/pull/76825 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Optimize castToDeclContext for 2% improvement in build times (PR #76825)
https://github.com/Destroyerrrocket updated https://github.com/llvm/llvm-project/pull/76825 >From bea08b9dd4c9b3663035656de3ee8899538bbfd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pol=20Marcet=20Sard=C3=A0?= Date: Wed, 3 Jan 2024 16:00:42 +0100 Subject: [PATCH] [clang] Optimize castToDeclContext for 2% improvement in build times castToDeclContext is a heavily used function, and as such, it needs to be kept as slim as feasible to preserve as much performance as possible. To this end, it was observed that the function was generating suboptimal assembly code, and putting the most common execution path in the longest sequence of instructions. This patch addresses this by guiding the compiler towards generating a lookup table of offsets, which can be used to perform an addition on the pointer. This results in a 1-2% improvement on debug builds (and a negligible improvement on release). To achieve this, the switch was simplified to flatten the if statements in the default branch. In order to make the values of the switch more compact, encouraging LLVM to generate a look-up table instead of a jump table, the AST TableGen generator was modified so it can take order priority based on class inheritance. This combination allowed for a more optimal generation of the function. Of note, 2 other functions with an equivalent structure also needed to be modified. Please refer to the issue/PR for exact assembly results: https://github.com/llvm/llvm-project/issues/76824 https://github.com/llvm/llvm-project/pull/76825 Reviewers: Cor3ntin & Endilll comments --- clang/include/clang/AST/DeclCXX.h | 8 ++ clang/lib/AST/DeclBase.cpp| 50 +++-- clang/utils/TableGen/ClangASTNodesEmitter.cpp | 103 +++--- clang/utils/TableGen/TableGen.cpp | 3 +- clang/utils/TableGen/TableGenBackends.h | 10 +- 5 files changed, 97 insertions(+), 77 deletions(-) diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index 432293583576b5..984a4d8bab5e77 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -2044,6 +2044,14 @@ class RequiresExprBodyDecl : public Decl, public DeclContext { // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == RequiresExprBody; } + + static DeclContext *castToDeclContext(const RequiresExprBodyDecl *D) { +return static_cast(const_cast(D)); + } + + static RequiresExprBodyDecl *castFromDeclContext(const DeclContext *DC) { +return static_cast(const_cast(DC)); + } }; /// Represents a static or instance method of a struct/union/class. diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index 5e03f0223d311c..b1733c2d052a65 100644 --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/lib/AST/DeclBase.cpp @@ -930,20 +930,14 @@ const AttrVec &Decl::getAttrs() const { Decl *Decl::castFromDeclContext (const DeclContext *D) { Decl::Kind DK = D->getDeclKind(); - switch(DK) { -#define DECL(NAME, BASE) -#define DECL_CONTEXT(NAME) \ -case Decl::NAME: \ - return static_cast(const_cast(D)); -#define DECL_CONTEXT_BASE(NAME) -#include "clang/AST/DeclNodes.inc" -default: + switch (DK) { #define DECL(NAME, BASE) -#define DECL_CONTEXT_BASE(NAME) \ - if (DK >= first##NAME && DK <= last##NAME) \ -return static_cast(const_cast(D)); +#define DECL_CONTEXT(NAME) \ + case Decl::NAME: \ +return static_cast(const_cast(D)); #include "clang/AST/DeclNodes.inc" - llvm_unreachable("a decl that inherits DeclContext isn't handled"); + default: +llvm_unreachable("a decl that inherits DeclContext isn't handled"); } } @@ -951,18 +945,12 @@ DeclContext *Decl::castToDeclContext(const Decl *D) { Decl::Kind DK = D->getKind(); switch(DK) { #define DECL(NAME, BASE) -#define DECL_CONTEXT(NAME) \ -case Decl::NAME: \ - return static_cast(const_cast(D)); -#define DECL_CONTEXT_BASE(NAME) +#define DECL_CONTEXT(NAME) \ + case Decl::NAME: \ +return static_cast(const_cast(D)); #include "clang/AST/DeclNodes.inc" -default: -#define DECL(NAME, BASE) -#define DECL_CONTEXT_BASE(NAME) \ - if (DK >= first##NAME && DK <= last##NAME) \ -return static_cast(const_cast(D)); -#include "clang/AST/DeclNodes.inc" - llvm_unreachable("a decl that inherits DeclContext isn't handled"); + default: +llvm_unreachable("a decl that inherits DeclContext isn't handled"); } } @@ -1129,20 +1117,14 @@ DeclContext::DeclContext(Decl::Kind K) { } bool DeclContext::classof(const Decl *D) { - switch (D->getKind()) { +
[clang] [clang] Optimize castToDeclContext for 2% improvement in build times (PR #76825)
Destroyerrrocket wrote: Squashed, rebased, and updated the commit message to give more information. You can go ahead and merge! https://github.com/llvm/llvm-project/pull/76825 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Optimize castToDeclContext for 2% improvement in build times (PR #76825)
https://github.com/Destroyerrrocket updated https://github.com/llvm/llvm-project/pull/76825 >From 2afecb35d80df788641c1b45cb74077037ff075f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pol=20Marcet=20Sard=C3=A0?= Date: Wed, 3 Jan 2024 16:00:42 +0100 Subject: [PATCH] [clang] Optimize castToDeclContext for 2% improvement in build times castToDeclContext is a heavily used function, and as such, it needs to be kept as slim as feasible to preserve as much performance as possible. To this end, it was observed that the function was generating suboptimal assembly code, and putting the most common execution path in the longest sequence of instructions. This patch addresses this by guiding the compiler towards generating a lookup table of offsets, which can be used to perform an addition on the pointer. This results in a 1-2% improvement on debug builds (and a negligible improvement on release). To achieve this, the switch was simplified to flatten the if statements in the default branch. In order to make the values of the switch more compact, encouraging LLVM to generate a look-up table instead of a jump table, the AST TableGen generator was modified so it can take order priority based on class inheritance. This combination allowed for a more optimal generation of the function. Of note, 2 other functions with an equivalent structure also needed to be modified. Please refer to the issue/PR for exact assembly results: https://github.com/llvm/llvm-project/issues/76824 https://github.com/llvm/llvm-project/pull/76825 Reviewers: Cor3ntin & Endilll --- clang/include/clang/AST/DeclCXX.h | 8 ++ clang/lib/AST/DeclBase.cpp| 50 +++-- clang/utils/TableGen/ClangASTNodesEmitter.cpp | 103 +++--- clang/utils/TableGen/TableGen.cpp | 3 +- clang/utils/TableGen/TableGenBackends.h | 10 +- 5 files changed, 97 insertions(+), 77 deletions(-) diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index 432293583576b5..984a4d8bab5e77 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -2044,6 +2044,14 @@ class RequiresExprBodyDecl : public Decl, public DeclContext { // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == RequiresExprBody; } + + static DeclContext *castToDeclContext(const RequiresExprBodyDecl *D) { +return static_cast(const_cast(D)); + } + + static RequiresExprBodyDecl *castFromDeclContext(const DeclContext *DC) { +return static_cast(const_cast(DC)); + } }; /// Represents a static or instance method of a struct/union/class. diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index 5e03f0223d311c..b1733c2d052a65 100644 --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/lib/AST/DeclBase.cpp @@ -930,20 +930,14 @@ const AttrVec &Decl::getAttrs() const { Decl *Decl::castFromDeclContext (const DeclContext *D) { Decl::Kind DK = D->getDeclKind(); - switch(DK) { -#define DECL(NAME, BASE) -#define DECL_CONTEXT(NAME) \ -case Decl::NAME: \ - return static_cast(const_cast(D)); -#define DECL_CONTEXT_BASE(NAME) -#include "clang/AST/DeclNodes.inc" -default: + switch (DK) { #define DECL(NAME, BASE) -#define DECL_CONTEXT_BASE(NAME) \ - if (DK >= first##NAME && DK <= last##NAME) \ -return static_cast(const_cast(D)); +#define DECL_CONTEXT(NAME) \ + case Decl::NAME: \ +return static_cast(const_cast(D)); #include "clang/AST/DeclNodes.inc" - llvm_unreachable("a decl that inherits DeclContext isn't handled"); + default: +llvm_unreachable("a decl that inherits DeclContext isn't handled"); } } @@ -951,18 +945,12 @@ DeclContext *Decl::castToDeclContext(const Decl *D) { Decl::Kind DK = D->getKind(); switch(DK) { #define DECL(NAME, BASE) -#define DECL_CONTEXT(NAME) \ -case Decl::NAME: \ - return static_cast(const_cast(D)); -#define DECL_CONTEXT_BASE(NAME) +#define DECL_CONTEXT(NAME) \ + case Decl::NAME: \ +return static_cast(const_cast(D)); #include "clang/AST/DeclNodes.inc" -default: -#define DECL(NAME, BASE) -#define DECL_CONTEXT_BASE(NAME) \ - if (DK >= first##NAME && DK <= last##NAME) \ -return static_cast(const_cast(D)); -#include "clang/AST/DeclNodes.inc" - llvm_unreachable("a decl that inherits DeclContext isn't handled"); + default: +llvm_unreachable("a decl that inherits DeclContext isn't handled"); } } @@ -1129,20 +1117,14 @@ DeclContext::DeclContext(Decl::Kind K) { } bool DeclContext::classof(const Decl *D) { - switch (D->getKind()) { + Decl::Kin
[clang] [clang] Optimize castToDeclContext for 2% improvement in build times (PR #76825)
https://github.com/cor3ntin closed https://github.com/llvm/llvm-project/pull/76825 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits