Skip to content

[codegen] assume the tag, not the relative discriminant #144764

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

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

scottmcm
Copy link
Member

@scottmcm scottmcm commented Aug 1, 2025

Address the issue mentioned in llvm/llvm-project#134024 (comment) by changing discriminant calculation to assume on the originally-loaded tag, rather than on cast(tag)-OFFSET.

The previous way does make the purpose of the assume clearer, IMHO, since you see assume(x != 4); if p { x } else { 4 }, but doing it this way instead means that the adds optimize away in LLVM21, which is more important. And this new way is still easily thought of as being like metadata on the load saying specifically which value is impossible.

Demo of the LLVM20 vs LLVM21 difference: https://llvm.godbolt.org/z/n54x5Mq1T

r? @nikic

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Aug 1, 2025
@rustbot
Copy link
Collaborator

rustbot commented Aug 1, 2025

Some changes occurred in compiler/rustc_codegen_ssa

cc @WaffleLapkin

// CHECK: tail call void @llvm.assume(i1 %[[A_NOT_HOLE]])
// CHECK: %[[A_DISCR:.+]] = select i1 %[[A_IS_NICHE]], i64 %[[A_REL_DISCR]], i64 1
// LLVM20: %[[A_DISCR:.+]] = select i1 %[[A_IS_NICHE]], i64 %[[A_REL_DISCR]], i64 1
// LLVM21: %[[A_MODIFIED_TAG:.+]] = select i1 %[[A_IS_NICHE]], i64 %[[A_TRUNC]], i64 6
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't this select be at the bottom for LLVM 21?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, I completely missed that! Thanks.

@nikic
Copy link
Contributor

nikic commented Aug 1, 2025

This looks like a reasonable thing to do to me, but I'm probably the wrong person to check whether the logic is correct. The surrounding niche/discriminant logic looks kinda tricky.

@scottmcm scottmcm force-pushed the tweak-impossible-discriminant-assume branch from 6eb273e to b90e0fb Compare August 1, 2025 18:01
@scottmcm
Copy link
Member Author

scottmcm commented Aug 1, 2025

r? codegen

@rustbot rustbot assigned dianqk and unassigned nikic Aug 1, 2025
if niche_variants.contains(&untagged_variant)
&& bx.cx().sess().opts.optimize != OptLevel::No
{
let ne = bx.icmp(IntPredicate::IntNE, tagged_discr, untagged_variant_const);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In case this helps review, here's how you can see this just from the diff, rather than from https://doc.rust-lang.org/nightly/nightly-rustc/rustc_abi/enum.TagEncoding.html#variant.Niche:

Previously we were doing tagged_discr != untagged_variant here.

But

relative_discr = tag - niche_start
delta = niche_variants.start()
tagged_discr  = relative_discr + delta

so

   tagged_discr != untagged_variant
=> relative_discr + delta != untagged_variant
=> (tag - niche_start) + niche_variants.start() != untagged_variant
=> tag != niche_start  + untagged_variant - niche_variants.start() 

which is the calculation on line 522.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants