forked from rust-lang/rust
-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Auto merge of rust-lang#121421 - saethlin:smarter-mono, r=oli-obk
Avoid lowering code under dead SwitchInt targets The objective of this PR is to detect and eliminate code which is guarded by an `if false`, even if that `false` is a constant which is not known until monomorphization, or is `intrinsics::debug_assertions()`. The effect of this is that we generate no LLVM IR the standard library's unsafe preconditions, when they are compiled in a build where they should be immediately optimized out. This mono-time optimization ensures that builds which disable debug assertions do not grow a linkage requirement against `core`, which compiler-builtins currently needs: rust-lang#121552 This revives the codegen side of rust-lang#91222 as planned in rust-lang#120848.
- Loading branch information
Showing
6 changed files
with
214 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,3 @@ | ||
use rustc_index::bit_set::BitSet; | ||
|
||
use super::*; | ||
|
||
/// Preorder traversal of a graph. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
//@ compile-flags: -Cno-prepopulate-passes -Copt-level=0 -Cdebug-assertions=no | ||
|
||
// This test ensures that in a debug build which turns off debug assertions, we do not monomorphize | ||
// any of the standard library's unsafe precondition checks. | ||
// The naive codegen of those checks contains the actual check underneath an `if false`, which | ||
// could be optimized out if optimizations are enabled. But if we rely on optimizations to remove | ||
// panic branches, then we can't link compiler_builtins without optimizing it, which means that | ||
// -Zbuild-std doesn't work with -Copt-level=0. | ||
// | ||
// In other words, this tests for a mandatory optimization. | ||
|
||
#![crate_type = "lib"] | ||
|
||
use std::ptr::NonNull; | ||
|
||
// CHECK-LABEL: ; core::ptr::non_null::NonNull<T>::new_unchecked | ||
// CHECK-NOT: call | ||
// CHECK: } | ||
|
||
// CHECK-LABEL: @nonnull_new | ||
#[no_mangle] | ||
pub unsafe fn nonnull_new(ptr: *mut u8) -> NonNull<u8> { | ||
// CHECK: ; call core::ptr::non_null::NonNull<T>::new_unchecked | ||
unsafe { | ||
NonNull::new_unchecked(ptr) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
//@ compile-flags: -Cno-prepopulate-passes -Copt-level=0 | ||
|
||
#![crate_type = "lib"] | ||
|
||
#[no_mangle] | ||
pub fn demo_for_i32() { | ||
generic_impl::<i32>(); | ||
} | ||
|
||
// Two important things here: | ||
// - We replace the "then" block with `unreachable` to avoid linking problems | ||
// - We neither declare nor define the `big_impl` that said block "calls". | ||
|
||
// CHECK-LABEL: ; skip_mono_inside_if_false::generic_impl | ||
// CHECK: start: | ||
// CHECK-NEXT: br label %[[ELSE_BRANCH:bb[0-9]+]] | ||
// CHECK: [[ELSE_BRANCH]]: | ||
// CHECK-NEXT: call skip_mono_inside_if_false::small_impl | ||
// CHECK: bb{{[0-9]+}}: | ||
// CHECK-NEXT: ret void | ||
// CHECK: bb{{[0-9+]}}: | ||
// CHECK-NEXT: unreachable | ||
|
||
fn generic_impl<T>() { | ||
trait MagicTrait { | ||
const IS_BIG: bool; | ||
} | ||
impl<T> MagicTrait for T { | ||
const IS_BIG: bool = std::mem::size_of::<T>() > 10; | ||
} | ||
if T::IS_BIG { | ||
big_impl::<T>(); | ||
} else { | ||
small_impl::<T>(); | ||
} | ||
} | ||
|
||
#[inline(never)] | ||
fn small_impl<T>() {} | ||
#[inline(never)] | ||
fn big_impl<T>() {} |