-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Anonymous allocations in statics get duplicated for multiple codegen units #79738
Comments
IIUC #116564 is an attempt to fix this. |
But I also don't think I understand this example. This is all in the same crate. We could evaluate the static |
Oh neat you found a single crate repro. The issue is just that llvm treats alloc ids without a name as codegen unit local and thus generates one per unit. We need to give them a name, but we only want to give those a name that come from a static. |
I didn't find it, you did. 😂 |
That example fails even with |
I think this happens because the codegen backend does not cache allocations. There is a function that codegens an allocation, and if the same |
Ah good point. That won't help us cross crate tho |
Yea, the modules are not needed: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=a447edb36a144bd8863b11f743a37937 |
Yeah, adding such a cache does not replace your planned "named inner allocations". |
Is there an example of this that doesn't need |
yea, the issues are the same with |
lol no, not even with unleash mode. Our interning-time checks are too solid: https://rust.godbolt.org/z/65o9PnvPq |
Ah right, But as far as pointer identity goes, we don't need mutability to make this an example, do we? The cross-crate version of this should also trigger the problem? pub static FOO: &[i32] = &[42];
pub static BAR: &[i32] = &*FOO;
fn main() {
assert_eq!(FOO.as_ptr(), BAR.as_ptr());
} |
Always evaluate free constants and statics, even if previous errors occurred work towards rust-lang#79738 We will need to evaluate static items before the `definitions.freeze()` below, as we will start creating new `DefId`s (for nested allocations) within the `eval_static_initializer` query. But even without that motivation, this is a good change. Hard errors should always be reported and not silenced if other errors happened earlier.
Always evaluate free constants and statics, even if previous errors occurred work towards rust-lang/rust#79738 We will need to evaluate static items before the `definitions.freeze()` below, as we will start creating new `DefId`s (for nested allocations) within the `eval_static_initializer` query. But even without that motivation, this is a good change. Hard errors should always be reported and not silenced if other errors happened earlier.
Ensure nested allocations in statics do not get deduplicated This PR generates new `DefId`s for nested allocations in static items and feeds all the right queries to make the compiler believe these are regular `static` items. I chose this design, because all other designs are fragile and make the compiler horribly complex for such a niche use case. At present this wrecks incremental compilation performance *in case nested allocations exist* (because any query creating a `DefId` will be recomputed and never loaded from the cache). This will be resolved later in rust-lang#115613 . All other statics are unaffected by this change and will not have performance implications (heh, famous last words) This PR contains various smaller refactorings that can be pulled out into separate PRs. It is best reviewed commit-by-commit. The last commit is where the actual magic happens. r? `@RalfJung` on the const interner and engine changes fixes rust-lang#79738
Ensure nested allocations in statics do not get deduplicated This PR generates new `DefId`s for nested allocations in static items and feeds all the right queries to make the compiler believe these are regular `static` items. I chose this design, because all other designs are fragile and make the compiler horribly complex for such a niche use case. At present this wrecks incremental compilation performance *in case nested allocations exist* (because any query creating a `DefId` will be recomputed and never loaded from the cache). This will be resolved later in rust-lang#115613 . All other statics are unaffected by this change and will not have performance regressions (heh, famous last words) This PR contains various smaller refactorings that can be pulled out into separate PRs. It is best reviewed commit-by-commit. The last commit is where the actual magic happens. r? `@RalfJung` on the const interner and engine changes fixes rust-lang#79738
@cjgillot I seem to recall this issue coming up in the GVN pass... now that this is fixed, is there cleanup that could be done in GVN? |
Always evaluate free constants and statics, even if previous errors occurred work towards rust-lang/rust#79738 We will need to evaluate static items before the `definitions.freeze()` below, as we will start creating new `DefId`s (for nested allocations) within the `eval_static_initializer` query. But even without that motivation, this is a good change. Hard errors should always be reported and not silenced if other errors happened earlier.
Function pointer AllocIds have the same duplication behaviour, and that's by design. |
Vtables are duplicated too. They have to for the same reason functions are duplicated and statics can't be generic. cg_clif duplicates vtables for each cgu and I believe cg_ssa does too. |
I am not convinced GVN needs to treat them nearly as carefully as it currently does, but I also don't fully understand the current situation. Let's discuss in a new issue: #123670. |
Always evaluate free constants and statics, even if previous errors occurred work towards rust-lang/rust#79738 We will need to evaluate static items before the `definitions.freeze()` below, as we will start creating new `DefId`s (for nested allocations) within the `eval_static_initializer` query. But even without that motivation, this is a good change. Hard errors should always be reported and not silenced if other errors happened earlier.
According to analysis performed by @bjorn3, this code actually leads to two allocations containing
42
, i.e.,FOO
andBAR
point to different things. The linker later merges the two, so the issue is currently not directly observable. However, it becomes observable when things are mutable.I think this is a bug. When a static is defined as
pub static BAR: &i32 = crate::a::FOO;
, IMO we should guarantee thatBAR
andFOO
have the same value. I see no lee-way here for duplicating the memory they both point to.Cc @oli-obk
The text was updated successfully, but these errors were encountered: