This is an archive of the discontinued LLVM Phabricator instance.

[AST] Remove unnecessary indirections in DeclarationNameTable
ClosedPublic

Authored by bricci on Aug 3 2018, 9:37 AM.

Details

Summary

DeclarationNameTable currently hold 3 void * to
FoldingSet<CXXSpecialName>, FoldingSet<CXXLiteralOperatorIdName>
and FoldingSet<CXXDeductionGuideNameExtra>.

CXXSpecialName, CXXLiteralOperatorIdName and
CXXDeductionGuideNameExtra are private classes holding extra
information about a "special" declaration name and are in the DeclarationName.cpp
The original intent seems to have been to keep these class private and only expose
DeclarationNameExtra and DeclarationName (the code dates from 2008 and
has not been significantly changed since).

However this make the code less straightforward than necessary because of
the need to have void* in DeclarationNameTable (with 1 of 3 comments wrong)
and to manually allocate/deallocate the FoldingSets.

Moreover removing the extra indirections reduce the run-time of an fsyntax-only on
all of Boost by 2.3% which is not totally unexpected given how frequently this
data structure is used.

Comments:

  • For now I just moved the classes which were in DeclarationName.cpp to DeclarationName.h. We could find a way to hide them if desired, eg by stuffing them into a namespace detail or something...
  • This requires including Type.h...

Diff Detail

Repository
rL LLVM

Event Timeline

bricci created this revision.Aug 3 2018, 9:37 AM

On the face, this seems to be a nice patch. Removing extra allocations and replacing them with the stack is a good thing IMO. This is clearly an example of PIMPL, which while it has its advantages, performance is typically a hit. My 2 concerns with this are:

1- The increased size of DeclarationNameTable will cause a performance regression in the case where these folding sets are used rarely. Copies (which are obviously deleted, unless memcpy'ed somewhere)/moves of DeclarationNameTable are now more expensive. Based on your analysis, it seems that this is a 'net win', but I'd like to see if we can disallow 'move' as well.

2- The advantage of PIMPL is a reduction in compile time. Now, every file that uses DeclarationName.h (an extensive list of .cpp files, but more importantly, Decl.h, DeclBase.h, and Sema.h). Could you perhaps do a clean build both before/after this change with 'time' (http://man7.org/linux/man-pages/man1/time.1.html) and show the results? I hope it ends up being a small enough change to be acceptable, but it would be nice to have an informed decision here.

include/clang/AST/DeclarationName.h
450 ↗(On Diff #159025)

DeclarationNameTable should definitely have the move operators dealt with here. I suspect/hope the answer is 'deleted', but I don't think it matters generally.

Additionally, I'd like to see the destructor line left and set to 'default', since those 2 would complete the 'rule of 5'.

It seems to me that the increased size of DeclarationNameTable is irrelevant since it is
only used as a member in ASTContext and never copied nor moved from. Also,
at least for C++ it seems to me that this structure is never "rarely used" since it is
used for every overloaded op/ctor/dtor (but I admit that I am not familiar with Sema)

I will do a comparison of the build time this evening. If this is a problem we can try to
find a way to avoid the QualType in CXXSpecialName (which is the reason why we need
Type.h) by replacing it by uintptr_t and doing some casts.

Additionally I have taken a quick look at the headers which includes DeclarationName.h
and it seems that most of them already include Type.h (with the exception of DeclBase.h)

If so then the build time shouldn't change much but I will report if there is any significient difference.

It seems to me that the increased size of DeclarationNameTable is irrelevant since it is
only used as a member in ASTContext and never copied nor moved from. Also,
at least for C++ it seems to me that this structure is never "rarely used" since it is
used for every overloaded op/ctor/dtor (but I admit that I am not familiar with Sema)

In that case, adding the move ctor/move-operator = delete would make me happy here.

I will do a comparison of the build time this evening. If this is a problem we can try to
find a way to avoid the QualType in CXXSpecialName (which is the reason why we need
Type.h) by replacing it by uintptr_t and doing some casts.

I'm hoping the answer you come back with is more "its only a 2% build time increase" and that we wont have to do things like that.

bricci updated this revision to Diff 159044.Aug 3 2018, 10:52 AM
bricci marked an inline comment as done.

Added the deleted move ctors. (I think that they were already not declared because
of the user-provided copy ctor/assignment)

Will report the result about the build time but this will take some time :)

bricci added a comment.Aug 4 2018, 3:50 AM

I did both a clean build and an incremental build with and without this patch and was not able to see any
meaningful difference in the build time. Suspiciously the build time *with* the patch in both cases is a little
less (~0.1% ) than without the patch but this is well within the noise. At least I was not able to observe
a significant increase in the build time.

erichkeane accepted this revision.Aug 6 2018, 6:00 AM
This revision is now accepted and ready to land.Aug 6 2018, 6:00 AM
This revision was automatically updated to reflect the committed changes.
rnk added a comment.Aug 6 2018, 11:14 AM

Neat, thanks for the optimization. My only concern would be to find a way to avoid including Type.h, but it's already a very popular and very necessary header, so I don't think there is any issue here.

Yes it would be nice indeed. IIRC it is only needed for
QualType in one of the moved class.

This patch is especially nice since it both cleanup the code and
speed up clang :)