From 4a8ba05a8361b5db3d8fd0907efd993be4d4d5b5 Mon Sep 17 00:00:00 2001 From: Raoul Strackx Date: Thu, 9 Nov 2023 17:24:19 +0100 Subject: [PATCH 01/12] Making `User` and `User<[T]>` `Send` --- library/std/src/sys/sgx/abi/usercalls/alloc.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/library/std/src/sys/sgx/abi/usercalls/alloc.rs b/library/std/src/sys/sgx/abi/usercalls/alloc.rs index 817c33b660370..f99cea360f1f4 100644 --- a/library/std/src/sys/sgx/abi/usercalls/alloc.rs +++ b/library/std/src/sys/sgx/abi/usercalls/alloc.rs @@ -185,6 +185,12 @@ pub struct UserRef(UnsafeCell); #[unstable(feature = "sgx_platform", issue = "56975")] pub struct User(NonNull>); +#[unstable(feature = "sgx_platform", issue = "56975")] +unsafe impl Send for User {} + +#[unstable(feature = "sgx_platform", issue = "56975")] +unsafe impl Send for User<[T]> {} + trait NewUserRef { unsafe fn new_userref(v: T) -> Self; } From bc6a5c71b635a9a5ea52c0b5f4ff297b0f611ac7 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Fri, 8 Dec 2023 15:26:16 +0000 Subject: [PATCH 02/12] std: getrandom simplification for freebsd. it is in the libcs' crate too now. --- library/std/src/sys/unix/rand.rs | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/library/std/src/sys/unix/rand.rs b/library/std/src/sys/unix/rand.rs index 2825d16774272..cf0fe0f47c53f 100644 --- a/library/std/src/sys/unix/rand.rs +++ b/library/std/src/sys/unix/rand.rs @@ -64,17 +64,7 @@ mod imp { #[cfg(any(target_os = "espidf", target_os = "horizon", target_os = "freebsd"))] fn getrandom(buf: &mut [u8]) -> libc::ssize_t { - #[cfg(not(target_os = "freebsd"))] - use libc::getrandom; - #[cfg(target_os = "freebsd")] - extern "C" { - fn getrandom( - buf: *mut libc::c_void, - buflen: libc::size_t, - flags: libc::c_uint, - ) -> libc::ssize_t; - } - unsafe { getrandom(buf.as_mut_ptr().cast(), buf.len(), 0) } + unsafe { libc::getrandom(buf.as_mut_ptr().cast(), buf.len(), 0) } } #[cfg(not(any( From a6942cef323519c994a7b15c3361f3194010ca4f Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Sun, 29 Oct 2023 23:08:49 +0000 Subject: [PATCH 03/12] Update stdarch submodule --- library/std/src/lib.rs | 5 +++++ library/stdarch | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 95ee6a9b29c9c..897c2854dd8ba 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -365,6 +365,11 @@ #![feature(panic_unwind)] // tidy-alphabetical-end // +// Library features (std_detect): +// tidy-alphabetical-start +#![feature(stdarch_internal)] +// tidy-alphabetical-end +// // Only for re-exporting: // tidy-alphabetical-start #![feature(assert_matches)] diff --git a/library/stdarch b/library/stdarch index f4528dd6e85d9..5ef6eb42bdcfe 160000 --- a/library/stdarch +++ b/library/stdarch @@ -1 +1 @@ -Subproject commit f4528dd6e85d97bb802240d7cd048b6e1bf72540 +Subproject commit 5ef6eb42bdcfef6891517a6e4c77a89c18722f18 From 53ac39c5f4ae9527810e6052075d8876187cd1c7 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Tue, 31 Oct 2023 23:06:00 +0000 Subject: [PATCH 04/12] Update feature names for new stdarch --- library/core/src/lib.rs | 4 ---- library/std/src/lib.rs | 14 ++++++++------ library/std/tests/run-time-detect.rs | 16 ++++++++++------ .../miri/tests/pass/intrinsics-x86-aes-vaes.rs | 2 +- .../miri/tests/pass/intrinsics-x86-avx512.rs | 2 +- tests/ui/asm/aarch64/type-check-3.rs | 2 +- tests/ui/asm/aarch64/type-check-4.rs | 2 +- 7 files changed, 22 insertions(+), 20 deletions(-) diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 07720f235989b..c75849cab918b 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -425,10 +425,6 @@ pub mod primitive; deprecated_in_future )] #[allow(rustdoc::bare_urls)] -// FIXME: This annotation should be moved into rust-lang/stdarch after clashing_extern_declarations is -// merged. It currently cannot because bootstrap fails as the lint hasn't been defined yet. -#[allow(clashing_extern_declarations)] -#[unstable(feature = "stdsimd", issue = "48556")] mod core_arch; #[stable(feature = "simd_arch", since = "1.27.0")] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 897c2854dd8ba..757419f73b524 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -386,7 +386,6 @@ #![feature(get_many_mut)] #![feature(lazy_cell)] #![feature(log_syntax)] -#![feature(stdsimd)] #![feature(test)] #![feature(trace_macros)] // tidy-alphabetical-end @@ -625,13 +624,16 @@ pub mod arch { #[stable(feature = "simd_aarch64", since = "1.60.0")] pub use std_detect::is_aarch64_feature_detected; + #[unstable(feature = "stdarch_arm_feature_detection", issue = "111190")] + pub use std_detect::is_arm_feature_detected; + #[unstable(feature = "is_riscv_feature_detected", issue = "111192")] + pub use std_detect::is_riscv_feature_detected; #[stable(feature = "simd_x86", since = "1.27.0")] pub use std_detect::is_x86_feature_detected; - #[unstable(feature = "stdsimd", issue = "48556")] - pub use std_detect::{ - is_arm_feature_detected, is_mips64_feature_detected, is_mips_feature_detected, - is_powerpc64_feature_detected, is_powerpc_feature_detected, is_riscv_feature_detected, - }; + #[unstable(feature = "stdarch_mips_feature_detection", issue = "111188")] + pub use std_detect::{is_mips64_feature_detected, is_mips_feature_detected}; + #[unstable(feature = "stdarch_powerpc_feature_detection", issue = "111191")] + pub use std_detect::{is_powerpc64_feature_detected, is_powerpc_feature_detected}; } // This was stabilized in the crate root so we have to keep it there. diff --git a/library/std/tests/run-time-detect.rs b/library/std/tests/run-time-detect.rs index 9ce29a33df6e6..c9b9c54e3d49c 100644 --- a/library/std/tests/run-time-detect.rs +++ b/library/std/tests/run-time-detect.rs @@ -1,12 +1,16 @@ //! These tests just check that the macros are available in std. #![cfg_attr( - any( - all(target_arch = "arm", any(target_os = "linux", target_os = "android")), - all(target_arch = "powerpc", target_os = "linux"), - all(target_arch = "powerpc64", target_os = "linux"), - ), - feature(stdsimd) + all(target_arch = "arm", any(target_os = "linux", target_os = "android")), + feature(stdarch_arm_feature_detection) +)] +#![cfg_attr( + all(target_arch = "powerpc", target_os = "linux"), + feature(stdarch_powerpc_feature_detection) +)] +#![cfg_attr( + all(target_arch = "powerpc64", target_os = "linux"), + feature(stdarch_powerpc_feature_detection) )] #[test] diff --git a/src/tools/miri/tests/pass/intrinsics-x86-aes-vaes.rs b/src/tools/miri/tests/pass/intrinsics-x86-aes-vaes.rs index 55d1bacdf4578..7363c75361779 100644 --- a/src/tools/miri/tests/pass/intrinsics-x86-aes-vaes.rs +++ b/src/tools/miri/tests/pass/intrinsics-x86-aes-vaes.rs @@ -9,7 +9,7 @@ //@ignore-target-wasm32 //@compile-flags: -C target-feature=+aes,+vaes,+avx512f -#![feature(avx512_target_feature, stdsimd)] +#![feature(avx512_target_feature, stdarch_x86_avx512)] use core::mem::transmute; #[cfg(target_arch = "x86")] diff --git a/src/tools/miri/tests/pass/intrinsics-x86-avx512.rs b/src/tools/miri/tests/pass/intrinsics-x86-avx512.rs index 394412a235432..66bfcb20f1c99 100644 --- a/src/tools/miri/tests/pass/intrinsics-x86-avx512.rs +++ b/src/tools/miri/tests/pass/intrinsics-x86-avx512.rs @@ -10,7 +10,7 @@ //@compile-flags: -C target-feature=+avx512f,+avx512vl,+avx512bitalg,+avx512vpopcntdq #![feature(avx512_target_feature)] -#![feature(stdsimd)] +#![feature(stdarch_x86_avx512)] #[cfg(target_arch = "x86")] use std::arch::x86::*; diff --git a/tests/ui/asm/aarch64/type-check-3.rs b/tests/ui/asm/aarch64/type-check-3.rs index 623f6593d79ba..77524ba7aa5e4 100644 --- a/tests/ui/asm/aarch64/type-check-3.rs +++ b/tests/ui/asm/aarch64/type-check-3.rs @@ -1,7 +1,7 @@ // only-aarch64 // compile-flags: -C target-feature=+neon -#![feature(repr_simd, stdsimd, asm_const)] +#![feature(repr_simd, asm_const)] use std::arch::aarch64::float64x2_t; use std::arch::{asm, global_asm}; diff --git a/tests/ui/asm/aarch64/type-check-4.rs b/tests/ui/asm/aarch64/type-check-4.rs index bd23755c02316..5dec60a2138d9 100644 --- a/tests/ui/asm/aarch64/type-check-4.rs +++ b/tests/ui/asm/aarch64/type-check-4.rs @@ -1,7 +1,7 @@ // only-aarch64 // compile-flags: -C target-feature=+neon -#![feature(repr_simd, stdsimd, asm_const)] +#![feature(repr_simd, asm_const)] use std::arch::aarch64::float64x2_t; use std::arch::{asm, global_asm}; From 2426b6242b924a14c702c88ce66328e2c960bb16 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Tue, 2 Jan 2024 19:42:47 +0100 Subject: [PATCH 05/12] Update ahash dependency to 0.8.7 --- Cargo.lock | 12 ++--- compiler/rustc_codegen_cranelift/Cargo.lock | 60 ++++++++++++++++++++- 2 files changed, 64 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b8192e333fe91..f04cd22f598c1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -37,9 +37,9 @@ dependencies = [ [[package]] name = "ahash" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a" +checksum = "77c3a9648d43b9cd48db467b3f87fdd6e146bcc88ab0180006cef2179fe11d01" dependencies = [ "cfg-if", "once_cell", @@ -6363,18 +6363,18 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.7.28" +version = "0.7.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d6f15f7ade05d2a4935e34a457b936c23dc70a05cc1d97133dc99e7a3fe0f0e" +checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.28" +version = "0.7.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbbad221e3f78500350ecbd7dfa4e63ef945c05f4c61cb7f4d3f84cd0bba649b" +checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", diff --git a/compiler/rustc_codegen_cranelift/Cargo.lock b/compiler/rustc_codegen_cranelift/Cargo.lock index 74e7afee7bcb2..b9e6f7b1571a8 100644 --- a/compiler/rustc_codegen_cranelift/Cargo.lock +++ b/compiler/rustc_codegen_cranelift/Cargo.lock @@ -4,13 +4,14 @@ version = 3 [[package]] name = "ahash" -version = "0.8.3" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" +checksum = "77c3a9648d43b9cd48db467b3f87fdd6e146bcc88ab0180006cef2179fe11d01" dependencies = [ "cfg-if", "once_cell", "version_check", + "zerocopy", ] [[package]] @@ -293,6 +294,24 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +[[package]] +name = "proc-macro2" +version = "1.0.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "907a61bd0f64c2f29cd1cf1dc34d05176426a3f504a78010f08416ddb7b13708" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +dependencies = [ + "proc-macro2", +] + [[package]] name = "regalloc2" version = "0.9.3" @@ -360,12 +379,29 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +[[package]] +name = "syn" +version = "2.0.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1726efe18f42ae774cc644f330953a5e7b3c3003d3edcecf18850fe9d4dd9afb" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "target-lexicon" version = "0.12.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14c39fd04924ca3a864207c66fc2cd7d22d7c016007f9ce846cbb9326331930a" +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + [[package]] name = "version_check" version = "0.9.4" @@ -470,3 +506,23 @@ name = "windows_x86_64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "zerocopy" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] From 7e7fedd775da9cf6e062c504d6a7de501ba8ae4a Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Thu, 4 Jan 2024 08:34:02 +0000 Subject: [PATCH 06/12] Update allowed depdendencies for cranelift --- src/tools/tidy/src/deps.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 3c00027b9fdc9..1aa7907e00829 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -460,13 +460,17 @@ const PERMITTED_CRANELIFT_DEPENDENCIES: &[&str] = &[ "mach", "memchr", "object", + "proc-macro2", + "quote", "regalloc2", "region", "rustc-hash", "slice-group-by", "smallvec", "stable_deref_trait", + "syn", "target-lexicon", + "unicode-ident", "version_check", "wasmtime-jit-icache-coherence", "winapi", @@ -481,6 +485,8 @@ const PERMITTED_CRANELIFT_DEPENDENCIES: &[&str] = &[ "windows_x86_64_gnu", "windows_x86_64_gnullvm", "windows_x86_64_msvc", + "zerocopy", + "zerocopy-derive", // tidy-alphabetical-end ]; From 56173611d65bae5eacef80d15799ba89161cd38b Mon Sep 17 00:00:00 2001 From: klensy Date: Tue, 2 Jan 2024 22:36:01 +0300 Subject: [PATCH 07/12] don't reexport atomic::ordering via rustc_data_structures, use std import --- compiler/rustc_data_structures/src/sync.rs | 7 ++----- compiler/rustc_driver_impl/src/lib.rs | 3 +-- compiler/rustc_query_impl/src/plumbing.rs | 2 +- compiler/rustc_query_system/src/dep_graph/graph.rs | 14 +++++++------- compiler/rustc_session/src/session.rs | 6 ++---- 5 files changed, 13 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs index 43221d70e21cf..48edfba8da082 100644 --- a/compiler/rustc_data_structures/src/sync.rs +++ b/compiler/rustc_data_structures/src/sync.rs @@ -56,9 +56,6 @@ mod parallel; pub use parallel::scope; pub use parallel::{join, par_for_each_in, par_map, parallel_guard, try_par_for_each_in}; -pub use std::sync::atomic::Ordering; -pub use std::sync::atomic::Ordering::SeqCst; - pub use vec::{AppendOnlyIndexVec, AppendOnlyVec}; mod vec; @@ -67,8 +64,7 @@ mod freeze; pub use freeze::{FreezeLock, FreezeReadGuard, FreezeWriteGuard}; mod mode { - use super::Ordering; - use std::sync::atomic::AtomicU8; + use std::sync::atomic::{AtomicU8, Ordering}; const UNINITIALIZED: u8 = 0; const DYN_NOT_THREAD_SAFE: u8 = 1; @@ -113,6 +109,7 @@ cfg_match! { cfg(not(parallel_compiler)) => { use std::ops::Add; use std::cell::Cell; + use std::sync::atomic::Ordering; pub unsafe auto trait Send {} pub unsafe auto trait Sync {} diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index fd925b62702af..3add7e3c643ee 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -25,7 +25,6 @@ use rustc_codegen_ssa::{traits::CodegenBackend, CodegenErrors, CodegenResults}; use rustc_data_structures::profiling::{ get_resident_set_size, print_time_passes_entry, TimePassesFormat, }; -use rustc_data_structures::sync::SeqCst; use rustc_errors::registry::{InvalidErrorCode, Registry}; use rustc_errors::{markdown, ColorConfig}; use rustc_errors::{DiagCtxt, ErrorGuaranteed, PResult}; @@ -476,7 +475,7 @@ fn run_compiler( eprintln!( "Fuel used by {}: {}", sess.opts.unstable_opts.print_fuel.as_ref().unwrap(), - sess.print_fuel.load(SeqCst) + sess.print_fuel.load(Ordering::SeqCst) ); } diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index f131a0f759320..fd7f1669ba456 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -69,7 +69,7 @@ impl QueryContext for QueryCtxt<'_> { fn next_job_id(self) -> QueryJobId { QueryJobId( NonZeroU64::new( - self.query_system.jobs.fetch_add(1, rustc_data_structures::sync::Ordering::Relaxed), + self.query_system.jobs.fetch_add(1, std::sync::atomic::Ordering::Relaxed), ) .unwrap(), ) diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index 9b06823dfbafb..1f09de0ed70c7 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -4,7 +4,7 @@ use rustc_data_structures::profiling::{EventId, QueryInvocationId, SelfProfilerR use rustc_data_structures::sharded::{self, Sharded}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::steal::Steal; -use rustc_data_structures::sync::{AtomicU32, AtomicU64, Lock, Lrc, Ordering}; +use rustc_data_structures::sync::{AtomicU32, AtomicU64, Lock, Lrc}; use rustc_data_structures::unord::UnordMap; use rustc_index::IndexVec; use rustc_serialize::opaque::{FileEncodeResult, FileEncoder}; @@ -13,7 +13,7 @@ use std::collections::hash_map::Entry; use std::fmt::Debug; use std::hash::Hash; use std::marker::PhantomData; -use std::sync::atomic::Ordering::Relaxed; +use std::sync::atomic::Ordering; use super::query::DepGraphQuery; use super::serialized::{GraphEncoder, SerializedDepGraph, SerializedDepNodeIndex}; @@ -476,7 +476,7 @@ impl DepGraph { let task_deps = &mut *task_deps; if cfg!(debug_assertions) { - data.current.total_read_count.fetch_add(1, Relaxed); + data.current.total_read_count.fetch_add(1, Ordering::Relaxed); } // As long as we only have a low number of reads we can avoid doing a hash @@ -506,7 +506,7 @@ impl DepGraph { } } } else if cfg!(debug_assertions) { - data.current.total_duplicate_read_count.fetch_add(1, Relaxed); + data.current.total_duplicate_read_count.fetch_add(1, Ordering::Relaxed); } }) } @@ -976,8 +976,8 @@ impl DepGraph { pub fn print_incremental_info(&self) { if let Some(data) = &self.data { data.current.encoder.borrow().print_incremental_info( - data.current.total_read_count.load(Relaxed), - data.current.total_duplicate_read_count.load(Relaxed), + data.current.total_read_count.load(Ordering::Relaxed), + data.current.total_duplicate_read_count.load(Ordering::Relaxed), ) } } @@ -992,7 +992,7 @@ impl DepGraph { pub(crate) fn next_virtual_depnode_index(&self) -> DepNodeIndex { debug_assert!(self.data.is_none()); - let index = self.virtual_dep_node_index.fetch_add(1, Relaxed); + let index = self.virtual_dep_node_index.fetch_add(1, Ordering::Relaxed); DepNodeIndex::from_u32(index) } } diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index ce166ae352fd7..0ada48986349e 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -14,9 +14,7 @@ use rustc_data_structures::flock; use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; use rustc_data_structures::jobserver::{self, Client}; use rustc_data_structures::profiling::{SelfProfiler, SelfProfilerRef}; -use rustc_data_structures::sync::{ - AtomicU64, DynSend, DynSync, Lock, Lrc, OneThread, Ordering::SeqCst, -}; +use rustc_data_structures::sync::{AtomicU64, DynSend, DynSync, Lock, Lrc, OneThread}; use rustc_errors::annotate_snippet_emitter_writer::AnnotateSnippetEmitter; use rustc_errors::emitter::{DynEmitter, HumanEmitter, HumanReadableErrorType}; use rustc_errors::json::JsonEmitter; @@ -44,7 +42,7 @@ use std::fmt; use std::ops::{Div, Mul}; use std::path::{Path, PathBuf}; use std::str::FromStr; -use std::sync::{atomic::AtomicBool, Arc}; +use std::sync::{atomic::AtomicBool, atomic::Ordering::SeqCst, Arc}; struct OptimizationFuel { /// If `-zfuel=crate=n` is specified, initially set to `n`, otherwise `0`. From 4071572cb416a1740e5530130b0454f9ce2db869 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 7 Jan 2024 14:59:59 +0000 Subject: [PATCH 08/12] Merge dead bb pruning and unreachable bb deduplication. --- compiler/rustc_middle/src/mir/mod.rs | 1 + .../rustc_mir_transform/src/const_goto.rs | 2 +- .../src/deduplicate_blocks.rs | 2 +- .../src/early_otherwise_branch.rs | 2 +- compiler/rustc_mir_transform/src/inline.rs | 5 +- .../rustc_mir_transform/src/match_branches.rs | 2 +- .../src/remove_unneeded_drops.rs | 2 +- .../src/separate_const_switch.rs | 4 +- compiler/rustc_mir_transform/src/simplify.rs | 92 ++++++++----------- ...await.b-{closure#0}.coroutine_resume.0.mir | 6 +- ...ng.identity.JumpThreading.panic-abort.diff | 10 +- ...g.identity.JumpThreading.panic-unwind.diff | 10 +- tests/mir-opt/jump_threading.rs | 8 +- ...d_constant.main.GVN.32bit.panic-abort.diff | 24 ++--- ..._constant.main.GVN.32bit.panic-unwind.diff | 18 ++-- ...d_constant.main.GVN.64bit.panic-abort.diff | 24 ++--- ..._constant.main.GVN.64bit.panic-unwind.diff | 18 ++-- ...t_switch.identity.SeparateConstSwitch.diff | 22 ++--- ...witch.too_complex.SeparateConstSwitch.diff | 28 +++--- 19 files changed, 124 insertions(+), 156 deletions(-) diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index d426f6d8969ac..36f5ba161d5f1 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -1316,6 +1316,7 @@ impl<'tcx> BasicBlockData<'tcx> { } /// Does the block have no statements and an unreachable terminator? + #[inline] pub fn is_empty_unreachable(&self) -> bool { self.statements.is_empty() && matches!(self.terminator().kind, TerminatorKind::Unreachable) } diff --git a/compiler/rustc_mir_transform/src/const_goto.rs b/compiler/rustc_mir_transform/src/const_goto.rs index 3884346076eea..cb5b66b314d69 100644 --- a/compiler/rustc_mir_transform/src/const_goto.rs +++ b/compiler/rustc_mir_transform/src/const_goto.rs @@ -51,7 +51,7 @@ impl<'tcx> MirPass<'tcx> for ConstGoto { // if we applied optimizations, we potentially have some cfg to cleanup to // make it easier for further passes if should_simplify { - simplify_cfg(tcx, body); + simplify_cfg(body); simplify_locals(body, tcx); } } diff --git a/compiler/rustc_mir_transform/src/deduplicate_blocks.rs b/compiler/rustc_mir_transform/src/deduplicate_blocks.rs index b40b2ec8bfdc4..824974970bb3f 100644 --- a/compiler/rustc_mir_transform/src/deduplicate_blocks.rs +++ b/compiler/rustc_mir_transform/src/deduplicate_blocks.rs @@ -25,7 +25,7 @@ impl<'tcx> MirPass<'tcx> for DeduplicateBlocks { if has_opts_to_apply { let mut opt_applier = OptApplier { tcx, duplicates }; opt_applier.visit_body(body); - simplify_cfg(tcx, body); + simplify_cfg(body); } } } diff --git a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs index 6eb6cb069fec0..0d600f0f937de 100644 --- a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs +++ b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs @@ -212,7 +212,7 @@ impl<'tcx> MirPass<'tcx> for EarlyOtherwiseBranch { // Since this optimization adds new basic blocks and invalidates others, // clean up the cfg to make it nicer for other passes if should_cleanup { - simplify_cfg(tcx, body); + simplify_cfg(body); } } } diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 8ad804bf3e7aa..ebefc3b47cc4f 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -15,7 +15,7 @@ use rustc_target::abi::FieldIdx; use rustc_target::spec::abi::Abi; use crate::cost_checker::CostChecker; -use crate::simplify::{remove_dead_blocks, CfgSimplifier}; +use crate::simplify::simplify_cfg; use crate::util; use std::iter; use std::ops::{Range, RangeFrom}; @@ -56,8 +56,7 @@ impl<'tcx> MirPass<'tcx> for Inline { let _guard = span.enter(); if inline(tcx, body) { debug!("running simplify cfg on {:?}", body.source); - CfgSimplifier::new(body).simplify(); - remove_dead_blocks(body); + simplify_cfg(body); deref_finder(tcx, body); } } diff --git a/compiler/rustc_mir_transform/src/match_branches.rs b/compiler/rustc_mir_transform/src/match_branches.rs index 1c4aa37d57ff5..6d4332793af31 100644 --- a/compiler/rustc_mir_transform/src/match_branches.rs +++ b/compiler/rustc_mir_transform/src/match_branches.rs @@ -174,7 +174,7 @@ impl<'tcx> MirPass<'tcx> for MatchBranchSimplification { } if should_cleanup { - simplify_cfg(tcx, body); + simplify_cfg(body); } } } diff --git a/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs b/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs index 5d528bed35647..2778d91e17b99 100644 --- a/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs +++ b/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs @@ -38,7 +38,7 @@ impl<'tcx> MirPass<'tcx> for RemoveUnneededDrops { // if we applied optimizations, we potentially have some cfg to cleanup to // make it easier for further passes if should_simplify { - simplify_cfg(tcx, body); + simplify_cfg(body); } } } diff --git a/compiler/rustc_mir_transform/src/separate_const_switch.rs b/compiler/rustc_mir_transform/src/separate_const_switch.rs index 6e22690d8dad5..7120ef7214271 100644 --- a/compiler/rustc_mir_transform/src/separate_const_switch.rs +++ b/compiler/rustc_mir_transform/src/separate_const_switch.rs @@ -50,11 +50,11 @@ impl<'tcx> MirPass<'tcx> for SeparateConstSwitch { sess.mir_opt_level() >= 2 && sess.opts.unstable_opts.unsound_mir_opts } - fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + fn run_pass(&self, _: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // If execution did something, applying a simplification layer // helps later passes optimize the copy away. if separate_const_switch(body) > 0 { - super::simplify::simplify_cfg(tcx, body); + super::simplify::simplify_cfg(body); } } } diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs index 856a0f227714d..8c8818bd68e6f 100644 --- a/compiler/rustc_mir_transform/src/simplify.rs +++ b/compiler/rustc_mir_transform/src/simplify.rs @@ -27,7 +27,6 @@ //! naively generate still contains the `_a = ()` write in the unreachable block "after" the //! return. -use rustc_data_structures::fx::FxIndexSet; use rustc_index::{Idx, IndexSlice, IndexVec}; use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; @@ -62,9 +61,8 @@ impl SimplifyCfg { } } -pub fn simplify_cfg<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { +pub(crate) fn simplify_cfg(body: &mut Body<'_>) { CfgSimplifier::new(body).simplify(); - remove_duplicate_unreachable_blocks(tcx, body); remove_dead_blocks(body); // FIXME: Should probably be moved into some kind of pass manager @@ -76,9 +74,9 @@ impl<'tcx> MirPass<'tcx> for SimplifyCfg { self.name() } - fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + fn run_pass(&self, _: TyCtxt<'tcx>, body: &mut Body<'tcx>) { debug!("SimplifyCfg({:?}) - simplifying {:?}", self.name(), body.source); - simplify_cfg(tcx, body); + simplify_cfg(body); } } @@ -289,55 +287,25 @@ pub fn simplify_duplicate_switch_targets(terminator: &mut Terminator<'_>) { } } -pub fn remove_duplicate_unreachable_blocks<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - struct OptApplier<'tcx> { - tcx: TyCtxt<'tcx>, - duplicates: FxIndexSet, - } - - impl<'tcx> MutVisitor<'tcx> for OptApplier<'tcx> { - fn tcx(&self) -> TyCtxt<'tcx> { - self.tcx - } - - fn visit_terminator(&mut self, terminator: &mut Terminator<'tcx>, location: Location) { - for target in terminator.successors_mut() { - // We don't have to check whether `target` is a cleanup block, because have - // entirely excluded cleanup blocks in building the set of duplicates. - if self.duplicates.contains(target) { - *target = self.duplicates[0]; - } - } - - simplify_duplicate_switch_targets(terminator); - - self.super_terminator(terminator, location); - } - } +pub(crate) fn remove_dead_blocks(body: &mut Body<'_>) { + let should_deduplicate_unreachable = |bbdata: &BasicBlockData<'_>| { + // CfgSimplifier::simplify leaves behind some unreachable basic blocks without a + // terminator. Those blocks will be deleted by remove_dead_blocks, but we run just + // before then so we need to handle missing terminators. + // We also need to prevent confusing cleanup and non-cleanup blocks. In practice we + // don't emit empty unreachable cleanup blocks, so this simple check suffices. + bbdata.terminator.is_some() && bbdata.is_empty_unreachable() && !bbdata.is_cleanup + }; - let unreachable_blocks = body + let reachable = traversal::reachable_as_bitset(body); + let empty_unreachable_blocks = body .basic_blocks .iter_enumerated() - .filter(|(_, bb)| { - // CfgSimplifier::simplify leaves behind some unreachable basic blocks without a - // terminator. Those blocks will be deleted by remove_dead_blocks, but we run just - // before then so we need to handle missing terminators. - // We also need to prevent confusing cleanup and non-cleanup blocks. In practice we - // don't emit empty unreachable cleanup blocks, so this simple check suffices. - bb.terminator.is_some() && bb.is_empty_unreachable() && !bb.is_cleanup - }) - .map(|(block, _)| block) - .collect::>(); - - if unreachable_blocks.len() > 1 { - OptApplier { tcx, duplicates: unreachable_blocks }.visit_body(body); - } -} + .filter(|(bb, bbdata)| should_deduplicate_unreachable(bbdata) && reachable.contains(*bb)) + .count(); -pub fn remove_dead_blocks(body: &mut Body<'_>) { - let reachable = traversal::reachable_as_bitset(body); let num_blocks = body.basic_blocks.len(); - if num_blocks == reachable.count() { + if num_blocks == reachable.count() && empty_unreachable_blocks <= 1 { return; } @@ -346,14 +314,28 @@ pub fn remove_dead_blocks(body: &mut Body<'_>) { let mut replacements: Vec<_> = (0..num_blocks).map(BasicBlock::new).collect(); let mut orig_index = 0; let mut used_index = 0; - basic_blocks.raw.retain(|_| { - let keep = reachable.contains(BasicBlock::new(orig_index)); - if keep { - replacements[orig_index] = BasicBlock::new(used_index); - used_index += 1; + let mut kept_unreachable = None; + basic_blocks.raw.retain(|bbdata| { + let orig_bb = BasicBlock::new(orig_index); + if !reachable.contains(orig_bb) { + orig_index += 1; + return false; + } + + let used_bb = BasicBlock::new(used_index); + if should_deduplicate_unreachable(bbdata) { + let kept_unreachable = *kept_unreachable.get_or_insert(used_bb); + if kept_unreachable != used_bb { + replacements[orig_index] = kept_unreachable; + orig_index += 1; + return false; + } } + + replacements[orig_index] = used_bb; + used_index += 1; orig_index += 1; - keep + true }); for block in basic_blocks { diff --git a/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir b/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir index 3a9c80caa1e64..3c0d4008c9018 100644 --- a/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir +++ b/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir @@ -108,7 +108,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:15:18: 18:2}>, bb0: { _39 = discriminant((*(_1.0: &mut {async fn body@$DIR/async_await.rs:15:18: 18:2}))); - switchInt(move _39) -> [0: bb1, 1: bb29, 3: bb27, 4: bb28, otherwise: bb30]; + switchInt(move _39) -> [0: bb1, 1: bb29, 3: bb27, 4: bb28, otherwise: bb9]; } bb1: { @@ -345,8 +345,4 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:15:18: 18:2}>, bb29: { assert(const false, "`async fn` resumed after completion") -> [success: bb29, unwind unreachable]; } - - bb30: { - unreachable; - } } diff --git a/tests/mir-opt/jump_threading.identity.JumpThreading.panic-abort.diff b/tests/mir-opt/jump_threading.identity.JumpThreading.panic-abort.diff index f50603a66a56f..f04ca72dd6d97 100644 --- a/tests/mir-opt/jump_threading.identity.JumpThreading.panic-abort.diff +++ b/tests/mir-opt/jump_threading.identity.JumpThreading.panic-abort.diff @@ -56,7 +56,7 @@ StorageLive(_11); StorageLive(_12); _10 = discriminant(_4); - switchInt(move _10) -> [0: bb8, 1: bb6, otherwise: bb7]; + switchInt(move _10) -> [0: bb7, 1: bb6, otherwise: bb2]; } bb1: { @@ -114,20 +114,16 @@ _3 = ControlFlow::, i32>::Break(move _13); StorageDead(_13); - goto -> bb5; -+ goto -> bb9; ++ goto -> bb8; } bb7: { - unreachable; - } - - bb8: { _11 = move ((_4 as Ok).0: i32); _3 = ControlFlow::, i32>::Continue(move _11); goto -> bb5; + } + -+ bb9: { ++ bb8: { + StorageDead(_12); + StorageDead(_11); + StorageDead(_10); diff --git a/tests/mir-opt/jump_threading.identity.JumpThreading.panic-unwind.diff b/tests/mir-opt/jump_threading.identity.JumpThreading.panic-unwind.diff index f50603a66a56f..f04ca72dd6d97 100644 --- a/tests/mir-opt/jump_threading.identity.JumpThreading.panic-unwind.diff +++ b/tests/mir-opt/jump_threading.identity.JumpThreading.panic-unwind.diff @@ -56,7 +56,7 @@ StorageLive(_11); StorageLive(_12); _10 = discriminant(_4); - switchInt(move _10) -> [0: bb8, 1: bb6, otherwise: bb7]; + switchInt(move _10) -> [0: bb7, 1: bb6, otherwise: bb2]; } bb1: { @@ -114,20 +114,16 @@ _3 = ControlFlow::, i32>::Break(move _13); StorageDead(_13); - goto -> bb5; -+ goto -> bb9; ++ goto -> bb8; } bb7: { - unreachable; - } - - bb8: { _11 = move ((_4 as Ok).0: i32); _3 = ControlFlow::, i32>::Continue(move _11); goto -> bb5; + } + -+ bb9: { ++ bb8: { + StorageDead(_12); + StorageDead(_11); + StorageDead(_10); diff --git a/tests/mir-opt/jump_threading.rs b/tests/mir-opt/jump_threading.rs index 66e5c5d3c11cb..0cbdaa085bc97 100644 --- a/tests/mir-opt/jump_threading.rs +++ b/tests/mir-opt/jump_threading.rs @@ -50,7 +50,7 @@ fn identity(x: Result) -> Result { // CHECK-LABEL: fn identity( // CHECK: bb0: { // CHECK: [[x:_.*]] = _1; - // CHECK: switchInt(move {{_.*}}) -> [0: bb8, 1: bb6, otherwise: bb7]; + // CHECK: switchInt(move {{_.*}}) -> [0: bb7, 1: bb6, otherwise: bb2]; // CHECK: bb1: { // CHECK: {{_.*}} = (([[controlflow:_.*]] as Continue).0: i32); // CHECK: _0 = Result::::Ok( @@ -68,14 +68,12 @@ fn identity(x: Result) -> Result { // CHECK: bb6: { // CHECK: {{_.*}} = move (([[x]] as Err).0: i32); // CHECK: [[controlflow]] = ControlFlow::, i32>::Break( - // CHECK: goto -> bb9; + // CHECK: goto -> bb8; // CHECK: bb7: { - // CHECK: unreachable; - // CHECK: bb8: { // CHECK: {{_.*}} = move (([[x]] as Ok).0: i32); // CHECK: [[controlflow]] = ControlFlow::, i32>::Continue( // CHECK: goto -> bb5; - // CHECK: bb9: { + // CHECK: bb8: { // CHECK: goto -> bb3; Ok(x?) } diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff index 5cb528c0d5f9d..47e0d402347d3 100644 --- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff @@ -56,9 +56,9 @@ + _2 = const Option::::None; StorageLive(_10); - _10 = discriminant(_2); -- switchInt(move _10) -> [0: bb1, 1: bb3, otherwise: bb2]; +- switchInt(move _10) -> [0: bb1, 1: bb2, otherwise: bb6]; + _10 = const 0_isize; -+ switchInt(const 0_isize) -> [0: bb1, 1: bb3, otherwise: bb2]; ++ switchInt(const 0_isize) -> [0: bb1, 1: bb2, otherwise: bb6]; } bb1: { @@ -66,10 +66,6 @@ } bb2: { - unreachable; - } - - bb3: { - _1 = move ((_2 as Some).0: std::alloc::Layout); + _1 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum32) }}; StorageDead(_10); @@ -79,18 +75,18 @@ StorageLive(_5); StorageLive(_6); _9 = const _; -- _6 = std::alloc::Global::alloc_impl(_9, _1, const false) -> [return: bb4, unwind unreachable]; -+ _6 = std::alloc::Global::alloc_impl(const {ALLOC1: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum32) }}, const false) -> [return: bb4, unwind unreachable]; +- _6 = std::alloc::Global::alloc_impl(_9, _1, const false) -> [return: bb3, unwind unreachable]; ++ _6 = std::alloc::Global::alloc_impl(const {ALLOC1: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum32) }}, const false) -> [return: bb3, unwind unreachable]; } - bb4: { + bb3: { StorageLive(_12); StorageLive(_15); _12 = discriminant(_6); - switchInt(move _12) -> [0: bb6, 1: bb5, otherwise: bb2]; + switchInt(move _12) -> [0: bb5, 1: bb4, otherwise: bb6]; } - bb5: { + bb4: { _15 = const "called `Result::unwrap()` on an `Err` value"; StorageLive(_16); StorageLive(_17); @@ -100,7 +96,7 @@ _14 = result::unwrap_failed(move _15, move _16) -> unwind unreachable; } - bb6: { + bb5: { _5 = move ((_6 as Ok).0: std::ptr::NonNull<[u8]>); StorageDead(_15); StorageDead(_12); @@ -115,6 +111,10 @@ StorageDead(_3); return; } + + bb6: { + unreachable; + } } + + ALLOC0 (size: 8, align: 4) { diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff index 1e1585f20aefa..dee57ce6c27bb 100644 --- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff @@ -41,9 +41,9 @@ + _2 = const Option::::None; StorageLive(_10); - _10 = discriminant(_2); -- switchInt(move _10) -> [0: bb2, 1: bb4, otherwise: bb3]; +- switchInt(move _10) -> [0: bb2, 1: bb3, otherwise: bb5]; + _10 = const 0_isize; -+ switchInt(const 0_isize) -> [0: bb2, 1: bb4, otherwise: bb3]; ++ switchInt(const 0_isize) -> [0: bb2, 1: bb3, otherwise: bb5]; } bb1: { @@ -64,10 +64,6 @@ } bb3: { - unreachable; - } - - bb4: { - _1 = move ((_2 as Some).0: std::alloc::Layout); + _1 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum32) }}; StorageDead(_10); @@ -77,13 +73,17 @@ StorageLive(_5); StorageLive(_6); _9 = const _; -- _6 = std::alloc::Global::alloc_impl(_9, _1, const false) -> [return: bb5, unwind continue]; -+ _6 = std::alloc::Global::alloc_impl(const {ALLOC1: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum32) }}, const false) -> [return: bb5, unwind continue]; +- _6 = std::alloc::Global::alloc_impl(_9, _1, const false) -> [return: bb4, unwind continue]; ++ _6 = std::alloc::Global::alloc_impl(const {ALLOC1: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum32) }}, const false) -> [return: bb4, unwind continue]; } - bb5: { + bb4: { _5 = Result::, std::alloc::AllocError>::unwrap(move _6) -> [return: bb1, unwind continue]; } + + bb5: { + unreachable; + } } + + ALLOC0 (size: 8, align: 4) { diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff index e655af559a18a..a255b15920cba 100644 --- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff @@ -56,9 +56,9 @@ + _2 = const Option::::None; StorageLive(_10); - _10 = discriminant(_2); -- switchInt(move _10) -> [0: bb1, 1: bb3, otherwise: bb2]; +- switchInt(move _10) -> [0: bb1, 1: bb2, otherwise: bb6]; + _10 = const 0_isize; -+ switchInt(const 0_isize) -> [0: bb1, 1: bb3, otherwise: bb2]; ++ switchInt(const 0_isize) -> [0: bb1, 1: bb2, otherwise: bb6]; } bb1: { @@ -66,10 +66,6 @@ } bb2: { - unreachable; - } - - bb3: { - _1 = move ((_2 as Some).0: std::alloc::Layout); + _1 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum64) }}; StorageDead(_10); @@ -79,18 +75,18 @@ StorageLive(_5); StorageLive(_6); _9 = const _; -- _6 = std::alloc::Global::alloc_impl(_9, _1, const false) -> [return: bb4, unwind unreachable]; -+ _6 = std::alloc::Global::alloc_impl(const {ALLOC1: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum64) }}, const false) -> [return: bb4, unwind unreachable]; +- _6 = std::alloc::Global::alloc_impl(_9, _1, const false) -> [return: bb3, unwind unreachable]; ++ _6 = std::alloc::Global::alloc_impl(const {ALLOC1: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum64) }}, const false) -> [return: bb3, unwind unreachable]; } - bb4: { + bb3: { StorageLive(_12); StorageLive(_15); _12 = discriminant(_6); - switchInt(move _12) -> [0: bb6, 1: bb5, otherwise: bb2]; + switchInt(move _12) -> [0: bb5, 1: bb4, otherwise: bb6]; } - bb5: { + bb4: { _15 = const "called `Result::unwrap()` on an `Err` value"; StorageLive(_16); StorageLive(_17); @@ -100,7 +96,7 @@ _14 = result::unwrap_failed(move _15, move _16) -> unwind unreachable; } - bb6: { + bb5: { _5 = move ((_6 as Ok).0: std::ptr::NonNull<[u8]>); StorageDead(_15); StorageDead(_12); @@ -115,6 +111,10 @@ StorageDead(_3); return; } + + bb6: { + unreachable; + } } + + ALLOC0 (size: 16, align: 8) { diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff index a6658713a026b..192ffea259157 100644 --- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff @@ -41,9 +41,9 @@ + _2 = const Option::::None; StorageLive(_10); - _10 = discriminant(_2); -- switchInt(move _10) -> [0: bb2, 1: bb4, otherwise: bb3]; +- switchInt(move _10) -> [0: bb2, 1: bb3, otherwise: bb5]; + _10 = const 0_isize; -+ switchInt(const 0_isize) -> [0: bb2, 1: bb4, otherwise: bb3]; ++ switchInt(const 0_isize) -> [0: bb2, 1: bb3, otherwise: bb5]; } bb1: { @@ -64,10 +64,6 @@ } bb3: { - unreachable; - } - - bb4: { - _1 = move ((_2 as Some).0: std::alloc::Layout); + _1 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum64) }}; StorageDead(_10); @@ -77,13 +73,17 @@ StorageLive(_5); StorageLive(_6); _9 = const _; -- _6 = std::alloc::Global::alloc_impl(_9, _1, const false) -> [return: bb5, unwind continue]; -+ _6 = std::alloc::Global::alloc_impl(const {ALLOC1: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum64) }}, const false) -> [return: bb5, unwind continue]; +- _6 = std::alloc::Global::alloc_impl(_9, _1, const false) -> [return: bb4, unwind continue]; ++ _6 = std::alloc::Global::alloc_impl(const {ALLOC1: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum64) }}, const false) -> [return: bb4, unwind continue]; } - bb5: { + bb4: { _5 = Result::, std::alloc::AllocError>::unwrap(move _6) -> [return: bb1, unwind continue]; } + + bb5: { + unreachable; + } } + + ALLOC0 (size: 16, align: 8) { diff --git a/tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff b/tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff index d287b20c4ead0..a12db0a730c57 100644 --- a/tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff +++ b/tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff @@ -52,7 +52,7 @@ StorageLive(_10); StorageLive(_11); _9 = discriminant(_1); - switchInt(move _9) -> [0: bb6, 1: bb5, otherwise: bb2]; + switchInt(move _9) -> [0: bb5, 1: bb4, otherwise: bb6]; } bb1: { @@ -63,10 +63,6 @@ } bb2: { - unreachable; - } - - bb3: { _6 = ((_3 as Break).0: std::result::Result); _13 = ((_6 as Err).0: i32); _0 = Result::::Err(move _13); @@ -74,27 +70,31 @@ return; } - bb4: { + bb3: { StorageDead(_11); StorageDead(_10); StorageDead(_9); _5 = discriminant(_3); - switchInt(move _5) -> [0: bb1, 1: bb3, otherwise: bb2]; + switchInt(move _5) -> [0: bb1, 1: bb2, otherwise: bb6]; } - bb5: { + bb4: { _11 = ((_1 as Err).0: i32); StorageLive(_12); _12 = Result::::Err(move _11); _3 = ControlFlow::, i32>::Break(move _12); StorageDead(_12); - goto -> bb4; + goto -> bb3; } - bb6: { + bb5: { _10 = ((_1 as Ok).0: i32); _3 = ControlFlow::, i32>::Continue(move _10); - goto -> bb4; + goto -> bb3; + } + + bb6: { + unreachable; } } diff --git a/tests/mir-opt/separate_const_switch.too_complex.SeparateConstSwitch.diff b/tests/mir-opt/separate_const_switch.too_complex.SeparateConstSwitch.diff index e2bf33f7fbcc0..80f40b86919eb 100644 --- a/tests/mir-opt/separate_const_switch.too_complex.SeparateConstSwitch.diff +++ b/tests/mir-opt/separate_const_switch.too_complex.SeparateConstSwitch.diff @@ -30,47 +30,47 @@ bb0: { StorageLive(_2); _3 = discriminant(_1); - switchInt(move _3) -> [0: bb3, 1: bb1, otherwise: bb2]; + switchInt(move _3) -> [0: bb2, 1: bb1, otherwise: bb7]; } bb1: { _6 = ((_1 as Err).0: usize); _2 = ControlFlow::::Break(_6); - goto -> bb4; + goto -> bb3; } bb2: { - unreachable; - } - - bb3: { _4 = ((_1 as Ok).0: i32); _2 = ControlFlow::::Continue(_4); - goto -> bb4; + goto -> bb3; } - bb4: { + bb3: { _8 = discriminant(_2); - switchInt(move _8) -> [0: bb6, 1: bb5, otherwise: bb2]; + switchInt(move _8) -> [0: bb5, 1: bb4, otherwise: bb7]; } - bb5: { + bb4: { StorageLive(_11); _11 = ((_2 as Break).0: usize); _0 = Option::::None; StorageDead(_11); - goto -> bb7; + goto -> bb6; } - bb6: { + bb5: { _9 = ((_2 as Continue).0: i32); _0 = Option::::Some(_9); - goto -> bb7; + goto -> bb6; } - bb7: { + bb6: { StorageDead(_2); return; } + + bb7: { + unreachable; + } } From c949dbdab1be3fab38acb166c4b0028190e6f46d Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Mon, 8 Jan 2024 13:36:05 +0000 Subject: [PATCH 09/12] Add stdarch_wasm_atomic_wait feature in std --- library/std/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 757419f73b524..8ec3101b3c278 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -262,6 +262,7 @@ )] #![cfg_attr(any(windows, target_os = "uefi"), feature(round_char_boundary))] #![cfg_attr(target_os = "xous", feature(slice_ptr_len))] +#![cfg_attr(target_family = "wasm", feature(stdarch_wasm_atomic_wait))] // // Language features: // tidy-alphabetical-start From e61be1bfae982b991828d3edd64a0eaea8bc2d55 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Mon, 8 Jan 2024 12:00:40 -0700 Subject: [PATCH 10/12] rustdoc-search: reuse empty map/array in function signatures Map is implemented as a pointer to a mutable object. Rustdoc never mutates function signatures after constructing them, but the JS engine doesn't know that. To save a bunch of memory, use a single immutable map for every decoded type object with no bindings or generics. --- src/librustdoc/html/static/js/search.js | 26 ++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index a5e2bc1c7afd0..5bd375a86a787 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -2717,9 +2717,25 @@ ${item.displayPath}${name}\ * @return {Array} */ function buildItemSearchTypeAll(types, lowercasePaths) { - return types.map(type => buildItemSearchType(type, lowercasePaths)); + return types.length > 0 ? + types.map(type => buildItemSearchType(type, lowercasePaths)) : + EMPTY_GENERICS_ARRAY; } + /** + * Empty, immutable map used in item search types with no bindings. + * + * @type {Map>} + */ + const EMPTY_BINDINGS_MAP = new Map(); + + /** + * Empty, immutable map used in item search types with no bindings. + * + * @type {Array} + */ + const EMPTY_GENERICS_ARRAY = []; + /** * Converts a single type. * @@ -2732,15 +2748,15 @@ ${item.displayPath}${name}\ let pathIndex, generics, bindings; if (typeof type === "number") { pathIndex = type; - generics = []; - bindings = new Map(); + generics = EMPTY_GENERICS_ARRAY; + bindings = EMPTY_BINDINGS_MAP; } else { pathIndex = type[PATH_INDEX_DATA]; generics = buildItemSearchTypeAll( type[GENERICS_DATA], lowercasePaths ); - if (type.length > BINDINGS_DATA) { + if (type.length > BINDINGS_DATA && type[BINDINGS_DATA].length > 0) { bindings = new Map(type[BINDINGS_DATA].map(binding => { const [assocType, constraints] = binding; // Associated type constructors are represented sloppily in rustdoc's @@ -2759,7 +2775,7 @@ ${item.displayPath}${name}\ ]; })); } else { - bindings = new Map(); + bindings = EMPTY_BINDINGS_MAP; } } if (pathIndex < 0) { From a2b765fc37e2de38502912aea051d3fdde42357c Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 8 Jan 2024 09:43:58 +1100 Subject: [PATCH 11/12] Remove `-Zdont-buffer-diagnostics`. It was added in #54232. It seems like it was aimed at NLL development, which is well in the past. Also, it looks like `-Ztreat-err-as-bug` can be used to achieve the same effect. So it doesn't seem necessary. --- compiler/rustc_errors/src/diagnostic_builder.rs | 3 +-- compiler/rustc_errors/src/lib.rs | 3 --- compiler/rustc_interface/src/tests.rs | 1 - compiler/rustc_session/src/config.rs | 1 - compiler/rustc_session/src/options.rs | 3 --- 5 files changed, 1 insertion(+), 10 deletions(-) diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index e72791d89a292..3789cdaf354aa 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -266,8 +266,7 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { /// Converts the builder to a `Diagnostic` for later emission, /// unless dcx has disabled such buffering. pub fn into_diagnostic(mut self) -> Option<(Diagnostic, &'a DiagCtxt)> { - let flags = self.dcx.inner.lock().flags; - if flags.dont_buffer_diagnostics || flags.treat_err_as_bug.is_some() { + if self.dcx.inner.lock().flags.treat_err_as_bug.is_some() { self.emit(); return None; } diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index b97ec02675a60..76b7e0d79a98c 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -524,9 +524,6 @@ pub struct DiagCtxtFlags { /// If Some, the Nth error-level diagnostic is upgraded to bug-level. /// (rustc: see `-Z treat-err-as-bug`) pub treat_err_as_bug: Option, - /// If true, immediately emit diagnostics that would otherwise be buffered. - /// (rustc: see `-Z dont-buffer-diagnostics` and `-Z treat-err-as-bug`) - pub dont_buffer_diagnostics: bool, /// Show macro backtraces. /// (rustc: see `-Z macro-backtrace`) pub macro_backtrace: bool, diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index f3f59b05682db..444e3700cf772 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -659,7 +659,6 @@ fn test_unstable_options_tracking_hash() { // tidy-alphabetical-start untracked!(assert_incr_state, Some(String::from("loaded"))); untracked!(deduplicate_diagnostics, false); - untracked!(dont_buffer_diagnostics, true); untracked!(dump_dep_graph, true); untracked!(dump_mir, Some(String::from("abc"))); untracked!(dump_mir_dataflow, true); diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 12d8293ecd2f6..61796d7a6cafc 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -1146,7 +1146,6 @@ impl UnstableOptions { DiagCtxtFlags { can_emit_warnings, treat_err_as_bug: self.treat_err_as_bug, - dont_buffer_diagnostics: self.dont_buffer_diagnostics, macro_backtrace: self.macro_backtrace, deduplicate_diagnostics: self.deduplicate_diagnostics, track_diagnostics: self.track_diagnostics, diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 842bf1d60f66d..6d96ec4d6f67d 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1553,9 +1553,6 @@ options! { dep_info_omit_d_target: bool = (false, parse_bool, [TRACKED], "in dep-info output, omit targets for tracking dependencies of the dep-info files \ themselves (default: no)"), - dont_buffer_diagnostics: bool = (false, parse_bool, [UNTRACKED], - "emit diagnostics rather than buffering (breaks NLL error downgrading, sorting) \ - (default: no)"), dual_proc_macros: bool = (false, parse_bool, [TRACKED], "load proc macros for both target and host, but only link to the target (default: no)"), dump_dep_graph: bool = (false, parse_bool, [UNTRACKED], From c3cd657210403b9b8b0e8557bc1604d1890e6821 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Mon, 8 Jan 2024 14:29:55 -0700 Subject: [PATCH 12/12] rustdoc-search: intern function search types This takes advantage of more reuse opportunities. Along with the empty object commit, they bringing memory usage down about 20% over the original. --- src/librustdoc/html/static/js/search.js | 89 ++++++++++++++++++++----- 1 file changed, 72 insertions(+), 17 deletions(-) diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 5bd375a86a787..7995a33f09f9b 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -2725,17 +2725,25 @@ ${item.displayPath}${name}\ /** * Empty, immutable map used in item search types with no bindings. * - * @type {Map>} + * @type {Map>} */ const EMPTY_BINDINGS_MAP = new Map(); /** * Empty, immutable map used in item search types with no bindings. * - * @type {Array} + * @type {Array} */ const EMPTY_GENERICS_ARRAY = []; + /** + * Object pool for function types with no bindings or generics. + * This is reset after loading the index. + * + * @type {Map} + */ + let TYPES_POOL = new Map(); + /** * Converts a single type. * @@ -2778,35 +2786,80 @@ ${item.displayPath}${name}\ bindings = EMPTY_BINDINGS_MAP; } } + /** + * @type {FunctionType} + */ + let result; if (pathIndex < 0) { // types less than 0 are generic parameters // the actual names of generic parameters aren't stored, since they aren't API - return { + result = { id: pathIndex, ty: TY_GENERIC, path: null, generics, bindings, }; - } - if (pathIndex === 0) { + } else if (pathIndex === 0) { // `0` is used as a sentinel because it's fewer bytes than `null` - return { + result = { id: null, ty: null, path: null, generics, bindings, }; + } else { + const item = lowercasePaths[pathIndex - 1]; + result = { + id: buildTypeMapIndex(item.name, isAssocType), + ty: item.ty, + path: item.path, + generics, + bindings, + }; } - const item = lowercasePaths[pathIndex - 1]; - return { - id: buildTypeMapIndex(item.name, isAssocType), - ty: item.ty, - path: item.path, - generics, - bindings, - }; + const cr = TYPES_POOL.get(result.id); + if (cr) { + // Shallow equality check. Since this function is used + // to construct every type object, this should be mostly + // equivalent to a deep equality check, except if there's + // a conflict, we don't keep the old one around, so it's + // not a fully precise implementation of hashcons. + if (cr.generics.length === result.generics.length && + cr.generics !== result.generics && + cr.generics.every((x, i) => result.generics[i] === x) + ) { + result.generics = cr.generics; + } + if (cr.bindings.size === result.bindings.size && cr.bindings !== result.bindings) { + let ok = true; + for (const [k, v] of cr.bindings.entries()) { + const v2 = result.bindings.get(v); + if (!v2) { + ok = false; + break; + } + if (v !== v2 && v.length === v2.length && v.every((x, i) => v2[i] === x)) { + result.bindings.set(k, v); + } else if (v !== v2) { + ok = false; + break; + } + } + if (ok) { + result.bindings = cr.bindings; + } + } + if (cr.ty === result.ty && cr.path === result.path + && cr.bindings === result.bindings && cr.generics === result.generics + && cr.ty === result.ty + ) { + return cr; + } + } + TYPES_POOL.set(result.id, result); + return result; } /** @@ -2817,7 +2870,7 @@ ${item.displayPath}${name}\ * object-based encoding so that the actual search code is more readable and easier to debug. * * The raw function search type format is generated using serde in - * librustdoc/html/render/mod.rs: impl Serialize for IndexItemFunctionType + * librustdoc/html/render/mod.rs: IndexItemFunctionType::write_to_string * * @param {{ * string: string, @@ -2986,8 +3039,8 @@ ${item.displayPath}${name}\ const fb = { id: null, ty: 0, - generics: [], - bindings: new Map(), + generics: EMPTY_GENERICS_ARRAY, + bindings: EMPTY_BINDINGS_MAP, }; for (const [k, v] of type.bindings.entries()) { fb.id = k; @@ -3215,6 +3268,8 @@ ${item.displayPath}${name}\ } currentIndex += itemTypes.length; } + // Drop the (rather large) hash table used for reusing function items + TYPES_POOL = new Map(); } /**