Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 760e567

Browse files
committed
Auto merge of rust-lang#122975 - DianQK:simplify_ub_check, r=saethlin
Eliminate `UbChecks` for non-standard libraries The purpose of this PR is to allow other passes to treat `UbChecks` as constants in MIR for optimization after rust-lang#122629. r? RalfJung
2 parents db2f975 + 47ed73a commit 760e567

File tree

14 files changed

+119
-46
lines changed

14 files changed

+119
-46
lines changed

‎compiler/rustc_feature/src/builtin_attrs.rs‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -821,6 +821,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
821821
rustc_allow_incoherent_impl, AttributeType::Normal, template!(Word), ErrorFollowing, EncodeCrossCrate::No,
822822
"#[rustc_allow_incoherent_impl] has to be added to all impl items of an incoherent inherent impl."
823823
),
824+
rustc_attr!(
825+
rustc_preserve_ub_checks, AttributeType::CrateLevel, template!(Word), ErrorFollowing, EncodeCrossCrate::No,
826+
"`#![rustc_preserve_ub_checks]` prevents the designated crate from evaluating whether UB checks are enabled when optimizing MIR",
827+
),
824828
rustc_attr!(
825829
rustc_deny_explicit_impl,
826830
AttributeType::Normal,

‎compiler/rustc_middle/src/mir/syntax.rs‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1361,8 +1361,8 @@ pub enum NullOp<'tcx> {
13611361
AlignOf,
13621362
/// Returns the offset of a field
13631363
OffsetOf(&'tcx List<(VariantIdx, FieldIdx)>),
1364-
/// Returns whether we want to check for UB.
1365-
/// This returns the value of `cfg!(debug_assertions)` at monomorphization time.
1364+
/// Returns whether we should perform some UB-checking at runtime.
1365+
/// See the `ub_checks` intrinsic docs for details.
13661366
UbChecks,
13671367
}
13681368

‎compiler/rustc_mir_transform/src/instsimplify.rs‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
//! Performs various peephole optimizations.
22
33
use crate::simplify::simplify_duplicate_switch_targets;
4+
use rustc_ast::attr;
45
use rustc_middle::mir::*;
56
use rustc_middle::ty::layout;
67
use rustc_middle::ty::layout::ValidityRequirement;
78
use rustc_middle::ty::{self, GenericArgsRef, ParamEnv, Ty, TyCtxt};
9+
use rustc_span::sym;
810
use rustc_span::symbol::Symbol;
911
use rustc_target::abi::FieldIdx;
1012
use rustc_target::spec::abi::Abi;
@@ -22,10 +24,15 @@ impl<'tcx> MirPass<'tcx> for InstSimplify {
2224
local_decls: &body.local_decls,
2325
param_env: tcx.param_env_reveal_all_normalized(body.source.def_id()),
2426
};
27+
let preserve_ub_checks =
28+
attr::contains_name(tcx.hir().krate_attrs(), sym::rustc_preserve_ub_checks);
2529
for block in body.basic_blocks.as_mut() {
2630
for statement in block.statements.iter_mut() {
2731
match statement.kind {
2832
StatementKind::Assign(box (_place, ref mut rvalue)) => {
33+
if !preserve_ub_checks {
34+
ctx.simplify_ub_check(&statement.source_info, rvalue);
35+
}
2936
ctx.simplify_bool_cmp(&statement.source_info, rvalue);
3037
ctx.simplify_ref_deref(&statement.source_info, rvalue);
3138
ctx.simplify_len(&statement.source_info, rvalue);
@@ -140,6 +147,14 @@ impl<'tcx> InstSimplifyContext<'tcx, '_> {
140147
}
141148
}
142149

150+
fn simplify_ub_check(&self, source_info: &SourceInfo, rvalue: &mut Rvalue<'tcx>) {
151+
if let Rvalue::NullaryOp(NullOp::UbChecks, _) = *rvalue {
152+
let const_ = Const::from_bool(self.tcx, self.tcx.sess.opts.debug_assertions);
153+
let constant = ConstOperand { span: source_info.span, const_, user_ty: None };
154+
*rvalue = Rvalue::Use(Operand::Constant(Box::new(constant)));
155+
}
156+
}
157+
143158
fn simplify_cast(&self, rvalue: &mut Rvalue<'tcx>) {
144159
if let Rvalue::Cast(kind, operand, cast_ty) = rvalue {
145160
let operand_ty = operand.ty(self.local_decls, self.tcx);

‎compiler/rustc_span/src/symbol.rs‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1590,6 +1590,7 @@ symbols! {
15901590
rustc_peek_maybe_init,
15911591
rustc_peek_maybe_uninit,
15921592
rustc_polymorphize_error,
1593+
rustc_preserve_ub_checks,
15931594
rustc_private,
15941595
rustc_proc_macro_decls,
15951596
rustc_promotable,

‎library/alloc/src/lib.rs‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@
176176
// Language features:
177177
// tidy-alphabetical-start
178178
#![cfg_attr(bootstrap, feature(associated_type_bounds))]
179+
#![cfg_attr(not(bootstrap), rustc_preserve_ub_checks)]
179180
#![cfg_attr(not(test), feature(coroutine_trait))]
180181
#![cfg_attr(test, feature(panic_update_hook))]
181182
#![cfg_attr(test, feature(test))]

‎library/core/src/intrinsics.rs‎

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2686,12 +2686,14 @@ pub const unsafe fn typed_swap<T>(x: *mut T, y: *mut T) {
26862686
unsafe { ptr::swap_nonoverlapping(x, y, 1) };
26872687
}
26882688

2689-
/// Returns whether we should perform some UB-checking at runtime. This evaluate to the value of
2690-
/// `cfg!(debug_assertions)` during monomorphization.
2691-
///
2692-
/// This intrinsic is evaluated after monomorphization, which is relevant when mixing crates
2693-
/// compiled with and without debug_assertions. The common case here is a user program built with
2694-
/// debug_assertions linked against the distributed sysroot which is built without debug_assertions.
2689+
/// Returns whether we should perform some UB-checking at runtime. This eventually evaluates to
2690+
/// `cfg!(debug_assertions)`, but behaves different from `cfg!` when mixing crates built with different
2691+
/// flags: if the crate has debug assertions enabled or carries the `#[rustc_preserve_ub_checks]`
2692+
/// attribute, evaluation is delayed until monomorphization (or until the call gets inlined into
2693+
/// a crate that does not delay evaluation further); otherwise it can happen any time.
2694+
///
2695+
/// The common case here is a user program built with debug_assertions linked against the distributed
2696+
/// sysroot which is built without debug_assertions but with `#[rustc_preserve_ub_checks]`.
26952697
/// For code that gets monomorphized in the user crate (i.e., generic functions and functions with
26962698
/// `#[inline]`), gating assertions on `ub_checks()` rather than `cfg!(debug_assertions)` means that
26972699
/// assertions are enabled whenever the *user crate* has debug assertions enabled. However if the

‎library/core/src/lib.rs‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@
9494
))]
9595
#![no_core]
9696
#![rustc_coherence_is_core]
97+
#![cfg_attr(not(bootstrap), rustc_preserve_ub_checks)]
9798
//
9899
// Lints:
99100
#![deny(rust_2021_incompatible_or_patterns)]

‎library/std/src/lib.rs‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@
221221
//
222222
#![cfg_attr(not(feature = "restricted-std"), stable(feature = "rust1", since = "1.0.0"))]
223223
#![cfg_attr(feature = "restricted-std", unstable(feature = "restricted_std", issue = "none"))]
224+
#![cfg_attr(not(bootstrap), rustc_preserve_ub_checks)]
224225
#![doc(
225226
html_playground_url = "https://play.rust-lang.org/",
226227
issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/",

‎tests/coverage/unreachable.cov-map‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
1-
Function name: unreachable::UNREACHABLE_CLOSURE::{closure#0}
2-
Raw bytes (9): 0x[01, 01, 00, 01, 01, 0f, 27, 00, 47]
1+
Function name: unreachable::UNREACHABLE_CLOSURE::{closure#0} (unused)
2+
Raw bytes (9): 0x[01, 01, 00, 01, 00, 0f, 27, 00, 47]
33
Number of files: 1
44
- file 0 => global file 1
55
Number of expressions: 0
66
Number of file 0 mappings: 1
7-
- Code(Counter(0)) at (prev + 15, 39) to (start + 0, 71)
7+
- Code(Zero) at (prev + 15, 39) to (start + 0, 71)
88

9-
Function name: unreachable::unreachable_function
10-
Raw bytes (9): 0x[01, 01, 00, 01, 01, 11, 01, 01, 25]
9+
Function name: unreachable::unreachable_function (unused)
10+
Raw bytes (9): 0x[01, 01, 00, 01, 00, 11, 01, 01, 25]
1111
Number of files: 1
1212
- file 0 => global file 1
1313
Number of expressions: 0
1414
Number of file 0 mappings: 1
15-
- Code(Counter(0)) at (prev + 17, 1) to (start + 1, 37)
15+
- Code(Zero) at (prev + 17, 1) to (start + 1, 37)
1616

1717
Function name: unreachable::unreachable_intrinsic (unused)
1818
Raw bytes (9): 0x[01, 01, 00, 01, 00, 16, 01, 01, 2c]

‎tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir‎

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ fn unwrap_unchecked(_1: Option<T>) -> T {
1111
}
1212
scope 3 {
1313
scope 4 (inlined unreachable_unchecked) {
14-
let mut _3: bool;
15-
let _4: ();
1614
scope 5 {
1715
}
1816
scope 6 (inlined core::ub_checks::check_language_ub) {
@@ -26,23 +24,16 @@ fn unwrap_unchecked(_1: Option<T>) -> T {
2624
bb0: {
2725
StorageLive(_2);
2826
_2 = discriminant(_1);
29-
switchInt(move _2) -> [0: bb1, 1: bb2, otherwise: bb3];
27+
switchInt(move _2) -> [0: bb2, 1: bb1, otherwise: bb2];
3028
}
3129

3230
bb1: {
33-
StorageLive(_3);
34-
_3 = UbChecks();
35-
assume(_3);
36-
_4 = unreachable_unchecked::precondition_check() -> [return: bb3, unwind unreachable];
37-
}
38-
39-
bb2: {
4031
_0 = ((_1 as Some).0: T);
4132
StorageDead(_2);
4233
return;
4334
}
4435

45-
bb3: {
36+
bb2: {
4637
unreachable;
4738
}
4839
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /