Skip to content

Commit d527afc

Browse files
committed
Add #[rustc_no_ubchecks]
1 parent 18bf9ce commit d527afc

File tree

12 files changed

+52
-11
lines changed

12 files changed

+52
-11
lines changed

compiler/rustc_feature/src/builtin_attrs.rs

+4
Original file line numberDiff line numberDiff line change
@@ -997,6 +997,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
997997
rustc_no_mir_inline, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::Yes,
998998
"#[rustc_no_mir_inline] prevents the MIR inliner from inlining a function while not affecting codegen"
999999
),
1000+
rustc_attr!(
1001+
rustc_no_ubchecks, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::Yes,
1002+
"#[rustc_no_ubchecks] asks the compiler to delete UB checks from a function"
1003+
),
10001004
rustc_attr!(
10011005
rustc_intrinsic_must_be_overridden, Normal, template!(Word), ErrorFollowing, EncodeCrossCrate::Yes,
10021006
"the `#[rustc_intrinsic_must_be_overridden]` attribute is used to declare intrinsics without real bodies",

compiler/rustc_mir_transform/src/instsimplify.rs

+18-5
Original file line numberDiff line numberDiff line change
@@ -37,19 +37,27 @@ impl<'tcx> MirPass<'tcx> for InstSimplify {
3737
}
3838

3939
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
40+
let def_id = body.source.def_id();
4041
let ctx = InstSimplifyContext {
4142
tcx,
4243
local_decls: &body.local_decls,
43-
param_env: tcx.param_env_reveal_all_normalized(body.source.def_id()),
44+
param_env: tcx.param_env_reveal_all_normalized(def_id),
4445
};
4546
let preserve_ub_checks =
4647
attr::contains_name(tcx.hir().krate_attrs(), sym::rustc_preserve_ub_checks);
48+
let remove_ub_checks = tcx.has_attr(def_id, sym::rustc_no_ubchecks);
4749
for block in body.basic_blocks.as_mut() {
4850
for statement in block.statements.iter_mut() {
4951
match statement.kind {
5052
StatementKind::Assign(box (_place, ref mut rvalue)) => {
51-
if !preserve_ub_checks {
52-
ctx.simplify_ub_check(&statement.source_info, rvalue);
53+
if remove_ub_checks {
54+
ctx.simplify_ub_check(&statement.source_info, rvalue, false);
55+
} else if !preserve_ub_checks {
56+
ctx.simplify_ub_check(
57+
&statement.source_info,
58+
rvalue,
59+
tcx.sess.ub_checks(),
60+
);
5361
}
5462
ctx.simplify_bool_cmp(&statement.source_info, rvalue);
5563
ctx.simplify_ref_deref(&statement.source_info, rvalue);
@@ -199,9 +207,14 @@ impl<'tcx> InstSimplifyContext<'tcx, '_> {
199207
}
200208
}
201209

202-
fn simplify_ub_check(&self, source_info: &SourceInfo, rvalue: &mut Rvalue<'tcx>) {
210+
fn simplify_ub_check(
211+
&self,
212+
source_info: &SourceInfo,
213+
rvalue: &mut Rvalue<'tcx>,
214+
ub_checks: bool,
215+
) {
203216
if let Rvalue::NullaryOp(NullOp::UbChecks, _) = *rvalue {
204-
let const_ = Const::from_bool(self.tcx, self.tcx.sess.ub_checks());
217+
let const_ = Const::from_bool(self.tcx, ub_checks);
205218
let constant = ConstOperand { span: source_info.span, const_, user_ty: None };
206219
*rvalue = Rvalue::Use(Operand::Constant(Box::new(constant)));
207220
}

compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1656,6 +1656,7 @@ symbols! {
16561656
rustc_never_returns_null_ptr,
16571657
rustc_never_type_options,
16581658
rustc_no_mir_inline,
1659+
rustc_no_ubchecks,
16591660
rustc_nonnull_optimization_guaranteed,
16601661
rustc_nounwind,
16611662
rustc_object_lifetime_default,

library/alloc/src/boxed.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1222,6 +1222,7 @@ impl<T: ?Sized, A: Allocator> Box<T, A> {
12221222
#[must_use = "losing the pointer will leak memory"]
12231223
#[unstable(feature = "allocator_api", issue = "32838")]
12241224
#[inline]
1225+
#[cfg_attr(not(bootstrap), rustc_no_ubchecks)]
12251226
pub fn into_raw_with_allocator(b: Self) -> (*mut T, A) {
12261227
let mut b = mem::ManuallyDrop::new(b);
12271228
// We carefully get the raw pointer out in a way that Miri's aliasing model understands what

library/core/src/mem/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -859,6 +859,7 @@ pub fn take<T: Default>(dest: &mut T) -> T {
859859
#[must_use = "if you don't need the old value, you can just assign the new value directly"]
860860
#[rustc_const_unstable(feature = "const_replace", issue = "83164")]
861861
#[cfg_attr(not(test), rustc_diagnostic_item = "mem_replace")]
862+
#[cfg_attr(not(bootstrap), rustc_no_ubchecks)]
862863
pub const fn replace<T>(dest: &mut T, src: T) -> T {
863864
// It may be tempting to use `swap` to avoid `unsafe` here. Don't!
864865
// The compiler optimizes the implementation below to two `memcpy`s

library/core/src/ptr/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1195,6 +1195,7 @@ pub const unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) {
11951195
/// `swap_nonoverlapping` tries to use) so no need to manually SIMD it.
11961196
#[inline]
11971197
#[rustc_const_unstable(feature = "const_swap", issue = "83163")]
1198+
#[cfg_attr(not(bootstrap), rustc_no_ubchecks)]
11981199
const unsafe fn swap_nonoverlapping_simple_untyped<T>(x: *mut T, y: *mut T, count: usize) {
11991200
let x = x.cast::<MaybeUninit<T>>();
12001201
let y = y.cast::<MaybeUninit<T>>();

tests/codegen/mem-replace-big-type.rs

-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
// known to be `1` after inlining).
55

66
//@ compile-flags: -C no-prepopulate-passes -Zinline-mir=no
7-
//@ ignore-debug: precondition checks in ptr::read make them a bad candidate for MIR inlining
87

98
#![crate_type = "lib"]
109

tests/codegen/mem-replace-simple-type.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
//@ compile-flags: -O -C no-prepopulate-passes
22
//@ only-x86_64 (to not worry about usize differing)
3-
//@ ignore-debug: precondition checks make mem::replace not a candidate for MIR inlining
43

54
#![crate_type = "lib"]
65

tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.panic-abort.mir

+13-1
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,22 @@ fn mem_replace(_1: &mut u32, _2: u32) -> u32 {
66
let mut _0: u32;
77
scope 1 (inlined std::mem::replace::<u32>) {
88
scope 2 {
9-
scope 4 (inlined std::ptr::write::<u32>) {
9+
scope 7 (inlined std::ptr::write::<u32>) {
10+
scope 8 (inlined core::ub_checks::check_language_ub) {
11+
scope 9 (inlined core::ub_checks::check_language_ub::runtime) {
12+
}
13+
}
14+
scope 10 (inlined align_of::<u32>) {
15+
}
1016
}
1117
}
1218
scope 3 (inlined std::ptr::read::<u32>) {
19+
scope 4 (inlined core::ub_checks::check_language_ub) {
20+
scope 5 (inlined core::ub_checks::check_language_ub::runtime) {
21+
}
22+
}
23+
scope 6 (inlined align_of::<u32>) {
24+
}
1325
}
1426
}
1527

tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.panic-unwind.mir

+13-1
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,22 @@ fn mem_replace(_1: &mut u32, _2: u32) -> u32 {
66
let mut _0: u32;
77
scope 1 (inlined std::mem::replace::<u32>) {
88
scope 2 {
9-
scope 4 (inlined std::ptr::write::<u32>) {
9+
scope 7 (inlined std::ptr::write::<u32>) {
10+
scope 8 (inlined core::ub_checks::check_language_ub) {
11+
scope 9 (inlined core::ub_checks::check_language_ub::runtime) {
12+
}
13+
}
14+
scope 10 (inlined align_of::<u32>) {
15+
}
1016
}
1117
}
1218
scope 3 (inlined std::ptr::read::<u32>) {
19+
scope 4 (inlined core::ub_checks::check_language_ub) {
20+
scope 5 (inlined core::ub_checks::check_language_ub::runtime) {
21+
}
22+
}
23+
scope 6 (inlined align_of::<u32>) {
24+
}
1325
}
1426
}
1527

tests/mir-opt/pre-codegen/mem_replace.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
// skip-filecheck
22
//@ compile-flags: -O -C debuginfo=0 -Zmir-opt-level=2 -Zinline-mir
3-
//@ ignore-debug: precondition checks on ptr::read/write are under cfg(debug_assertions)
43
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
54

65
#![crate_type = "lib"]

tests/mir-opt/pre-codegen/ptr_offset.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
// skip-filecheck
22
//@ compile-flags: -O -C debuginfo=0 -Zmir-opt-level=2 -Zinline-mir
3-
//@ ignore-debug: precondition checks are under cfg(debug_assertions)
43
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
54

65
#![crate_type = "lib"]

0 commit comments

Comments
 (0)