Repository: rust-lang/rust
Pull request: Unalign `PackedFingerprint` on all hosts, not just x86 and x86-64

Back in https://github.com/rust-lang/rust/pull/78646, `DepNode` was modified to store an unaligned `PackedFingerprint` instead of an 8-byte-aligned `Fingerprint`. That reduced the size of DepNode from 24 bytes to 17 bytes (nowadays 18 bytes), resulting in considerable memory savings in incremental builds.

See https://github.com/rust-lang/rust/pull/152695#issuecomment-3907091509 for a benchmark demonstrating the impact of *removing* that optimization.

At the time (and today), the unaligning was only performed on x86 and x86-64 hosts, because those CPUs are known to generally have low overhead for unaligned memory accesses. Hosts with other CPU architectures would continue to use an 8-byte-aligned fingerprint and a 24-byte DepNode.

Given the subsequent rise of aarch64 (especially on macOS) and other architectures, it's a shame that some commonly-used builds of rustc don't get those memory-size benefits, based on a decision made several years ago under different circumstances.

We don't have benchmarks to show the actual effect of unaligning DepNode fingerprints on various non-x86 hosts, but it seems very likely to be a good idea on Apple chips, and I have no particular reason to think that it will be catastrophically bad on other hosts. And we don't typically perform this kind of speculative pessimization in other parts of the compiler.

Changed files:
filename: compiler/rustc_data_structures/src/fingerprint.rs
patch: @@ -181,22 +181,24 @@ impl<D: Decoder> Decodable<D> for Fingerprint {
     }
 }
 
-// `PackedFingerprint` wraps a `Fingerprint`. Its purpose is to, on certain
-// architectures, behave like a `Fingerprint` without alignment requirements.
-// This behavior is only enabled on x86 and x86_64, where the impact of
-// unaligned accesses is tolerable in small doses.
-//
-// This may be preferable to use in large collections of structs containing
-// fingerprints, as it can reduce memory consumption by preventing the padding
-// that the more strictly-aligned `Fingerprint` can introduce. An application of
-// this is in the query dependency graph, which contains a large collection of
-// `DepNode`s. As of this writing, the size of a `DepNode` decreases by ~30%
-// (from 24 bytes to 17) by using the packed representation here, which
-// noticeably decreases total memory usage when compiling large crates.
-//
-// The wrapped `Fingerprint` is private to reduce the chance of a client
-// invoking undefined behavior by taking a reference to the packed field.
-#[cfg_attr(any(target_arch = "x86", target_arch = "x86_64"), repr(packed))]
+/// `PackedFingerprint` wraps a `Fingerprint`.
+/// Its purpose is to behave like a `Fingerprint` without alignment requirements.
+///
+/// This may be preferable to use in large collections of structs containing
+/// fingerprints, as it can reduce memory consumption by preventing the padding
+/// that the more strictly-aligned `Fingerprint` can introduce. An application of
+/// this is in the query dependency graph, which contains a large collection of
+/// `DepNode`s. As of this writing, the size of a `DepNode` decreases by 25%
+/// (from 24 bytes to 18) by using the packed representation here, which
+/// noticeably decreases total memory usage when compiling large crates.
+///
+/// (Unalignment was previously restricted to `x86` and `x86_64` hosts, but is
+/// now enabled by default for all host architectures, in the hope that the
+/// memory and cache savings should outweigh any unaligned access penalty.)
+///
+/// The wrapped `Fingerprint` is private to reduce the chance of a client
+/// invoking undefined behavior by taking a reference to the packed field.
+#[repr(packed)]
 #[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Clone, Copy, Hash)]
 pub struct PackedFingerprint(Fingerprint);
 

filename: compiler/rustc_middle/src/dep_graph/dep_node.rs
patch: @@ -412,9 +412,6 @@ mod size_asserts {
     use super::*;
     // tidy-alphabetical-start
     static_assert_size!(DepKind, 2);
-    #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
     static_assert_size!(DepNode, 18);
-    #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
-    static_assert_size!(DepNode, 24);
     // tidy-alphabetical-end
 }