-
Notifications
You must be signed in to change notification settings - Fork 14.9k
[clang] AST: fix getAs canonicalization of leaf types #155028
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"Meat and Potatoes" patch looks fine to me. Rest of it is too large to look at beyond scrolling through. Would be nice to have a few other +1s on this, just because of the size.
This changes a bunch of places which use getAs<TagType>, including derived types, just to obtain the tag definition. This is preparation for #155028, offloading all the changes that PR used to introduce which don't depend on any new helpers.
…ends This is a small performance improvement: This helps recover the performance lost in #155028, reversing it into a small positive instead.
fe87fbc
to
26b035d
Compare
@rjmccall done, I have offloaded all of the changes this PR did which didn't need the introduction of a new helper. That halved the size of the patch. The "meat and potatoes" commit still contains the important changes. |
… TagDecls And make use of those. These changes are split from prior PR #155028, in order to decrease the size of that PR and facilitate review.
26b035d
to
745eb0b
Compare
I did another offloading of NFC changes to another patch. This PR is tiny now in comparison. |
…ends This is a small performance improvement: This helps recover the performance lost in #155028, reversing it into a small positive instead.
Before this patch, the application of getAs and castAs on a leaf type would always produce a canonical type, which is undesirable because some of these types can be sugared. The user expectation is that getAs only removes top level sugar nodes, leaving all the type sugar on the returned node, but it had an optimization intended for type nodes with no sugar: for these, we can skip the expensive traversal of the top level sugar with a simple canonicalization followed by dyn_cast. The problem is that the concept of leaf type does not map well to what is correct to apply this optimization to. This patch replaces the concept of leaf types with 'always canonical' types, and only applies the canonicalization strategy on them. In order to avoid the performance regression this would cause, as most current users do not care about type sugar, this patch also replaces all of these uses with alternative cast functions which operate through canonicalization. * Introduces castAs variants to complement the getAsTagDecl and derived variants. * Introduces getAsEnumDecl and castAsEnumDecl, complementing the current set, so that all TagDecls are covered. * Introduces getAsCanonical and castAsCanonical, for faster casting when only the canonical type is desired. The getAsTagDecl and related functions are not provided inline, because of the circular dependencies that would involve. So this patch causes a small overall performance regression: <img width="1461" height="18" alt="image" src="https://github.com/user-attachments/assets/061dfb14-9506-4623-91ec-0f02f585d1dd" /> This will be fixed in a later patch, bringing the whole thing back to a positive performance improvement overall: <img width="1462" height="18" alt="image" src="https://github.com/user-attachments/assets/c237e68f-f696-44f4-acc6-a7c7ba5b0976" />
745eb0b
to
39b9487
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
…ends This is a small performance improvement: This helps recover the performance lost in #155028, reversing it into a small positive instead.
…ends This is a small performance improvement: This helps recover the performance lost in #155028, reversing it into a small positive instead.
…ends (#155051) This is a small performance improvement: This helps recover the performance lost in #155028, reversing it into a small positive instead. <img width="1464" height="20" alt="image" src="https://github.com/user-attachments/assets/3378789e-109d-4211-846e-0d38d6cb190a" />
Heads up, this is breaking modules support in our buildsystem. I'm getting errors now like this:
Note that the "not visible" decl is declared literally 4 lines before the usage. I don't know how to repro this upstream (and, I'd note, we aren't using the upstream modulemap file). My suspicion is that this commit has broken module decl-merging, where multiple copies of the same header are imported. I'll attempt to make a minimal example... |
Minimized test-case:
With a debug build of Clang, this actually results in an assert fail
|
Clang skips parsing a TagDecl definition in case a definition was already parsed in another module. In those cases, an EnumDecl might be left without an IntegerType. Take this into account when getting the underlying type of an enum, look for the integer type in the definition instead in those cases. This patch also changes the implementation so it properly marks those skipped tag definitions as demoted. This fixes a regression reported here: #155028 (comment) Since this regression was never released, there are no release notes.
Before this patch, the application of getAs and castAs on a leaf type would always produce a canonical type, which is undesirable because some of these types can be sugared.
The user expectation is that getAs only removes top level sugar nodes, leaving all the type sugar on the returned node, but it had an optimization intended for type nodes with no sugar: for these, we can skip the expensive traversal of the top level sugar with a simple canonicalization followed by dyn_cast.
The problem is that the concept of leaf type does not map well to what is correct to apply this optimization to.
This patch replaces the concept of leaf types with 'always canonical' types, and only applies the canonicalization strategy on them.
In order to avoid the performance regression this would cause, as most current users do not care about type sugar, this patch also replaces all of these uses with alternative cast functions which operate through canonicalization.
The getAsTagDecl and related functions are not provided inline, because of the circular dependencies that would involve. So this patch causes a small overall performance regression:

This will be fixed in a later patch, bringing the whole thing back to a positive performance improvement overall:

These follow-up patches are: