diff options
| author | Yuki Okushi <huyuumi.dev@gmail.com> | 2021-01-12 07:59:08 +0900 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-01-12 07:59:08 +0900 |
| commit | 56504a00f2ea183653beb0a06393343c99cdf6e2 (patch) | |
| tree | 039356279174b4cc8a439391c93563ec66d346cb /compiler/rustc_target | |
| parent | edcfe7b6296aff0cf5c52f0c8bc972b0b156616d (diff) | |
| parent | 4721b6518ce9c8e3a452af07c6dd178fbb83ab16 (diff) | |
| download | rust-56504a00f2ea183653beb0a06393343c99cdf6e2.tar.gz rust-56504a00f2ea183653beb0a06393343c99cdf6e2.zip | |
Rollup merge of #80042 - sivadeilra:cold_bits, r=oli-obk
Split a func into cold/hot parts, reducing binary size I noticed that the Size::bits function is called in many places, and is inlined into them. On x86_64-pc-windows-msvc, this function is inlined 527 times, and compiled separately (non-inlined) 3 times. Each of those inlined calls contains code that panics. This commit moves the `panic!` call into a separate function and marks that function with `#[cold]`. This reduces binary size by 24 KB. Not much, but it's something. Changes like this often reduce pressure on instruction-caches, since it reduces the amount of code that is inlined into hot code paths. Or more precisely, it removes cold code from hot cache lines.
Diffstat (limited to 'compiler/rustc_target')
| -rw-r--r-- | compiler/rustc_target/src/abi/mod.rs | 26 |
1 files changed, 20 insertions, 6 deletions
diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs index 61bfd58533a..93868bed9b9 100644 --- a/compiler/rustc_target/src/abi/mod.rs +++ b/compiler/rustc_target/src/abi/mod.rs @@ -271,22 +271,38 @@ impl ToJson for Endian { #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Encodable, Decodable)] #[derive(HashStable_Generic)] pub struct Size { + // The top 3 bits are ALWAYS zero. raw: u64, } impl Size { pub const ZERO: Size = Size { raw: 0 }; - #[inline] + /// Rounds `bits` up to the next-higher byte boundary, if `bits` is + /// is not aligned. pub fn from_bits(bits: impl TryInto<u64>) -> Size { let bits = bits.try_into().ok().unwrap(); + + #[cold] + fn overflow(bits: u64) -> ! { + panic!("Size::from_bits({}) has overflowed", bits); + } + + // This is the largest value of `bits` that does not cause overflow + // during rounding, and guarantees that the resulting number of bytes + // cannot cause overflow when multiplied by 8. + if bits > 0xffff_ffff_ffff_fff8 { + overflow(bits); + } + // Avoid potential overflow from `bits + 7`. - Size::from_bytes(bits / 8 + ((bits % 8) + 7) / 8) + Size { raw: bits / 8 + ((bits % 8) + 7) / 8 } } #[inline] pub fn from_bytes(bytes: impl TryInto<u64>) -> Size { - Size { raw: bytes.try_into().ok().unwrap() } + let bytes: u64 = bytes.try_into().ok().unwrap(); + Size { raw: bytes } } #[inline] @@ -301,9 +317,7 @@ impl Size { #[inline] pub fn bits(self) -> u64 { - self.bytes().checked_mul(8).unwrap_or_else(|| { - panic!("Size::bits: {} bytes in bits doesn't fit in u64", self.bytes()) - }) + self.raw << 3 } #[inline] |
