Skip to content

Commit 079e544

Browse files
committed
Auto merge of #109025 - cjgillot:refprop-dbg, r=JakobDegen
Enable MIR reference propagation by default
2 parents 5767cad + f993c6d commit 079e544

File tree

43 files changed

+704
-902
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+704
-902
lines changed

compiler/rustc_mir_transform/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -553,14 +553,14 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
553553
&normalize_array_len::NormalizeArrayLen, // has to run after `slice::len` lowering
554554
&const_goto::ConstGoto,
555555
&remove_unneeded_drops::RemoveUnneededDrops,
556+
&ref_prop::ReferencePropagation,
556557
&sroa::ScalarReplacementOfAggregates,
557558
&match_branches::MatchBranchSimplification,
558559
// inst combine is after MatchBranchSimplification to clean up Ne(_1, false)
559560
&multiple_return_terminators::MultipleReturnTerminators,
560561
&instsimplify::InstSimplify,
561562
&simplify::SimplifyLocals::BeforeConstProp,
562563
&copy_prop::CopyProp,
563-
&ref_prop::ReferencePropagation,
564564
// Perform `SeparateConstSwitch` after SSA-based analyses, as cloning blocks may
565565
// destroy the SSA property. It should still happen before const-propagation, so the
566566
// latter pass will leverage the created opportunities.

compiler/rustc_mir_transform/src/ref_prop.rs

+27-15
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ pub struct ReferencePropagation;
7171

7272
impl<'tcx> MirPass<'tcx> for ReferencePropagation {
7373
fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
74-
sess.mir_opt_level() >= 4
74+
sess.mir_opt_level() >= 2
7575
}
7676

7777
#[instrument(level = "trace", skip(self, tcx, body))]
@@ -355,7 +355,10 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'tcx> {
355355
}
356356

357357
fn visit_var_debug_info(&mut self, debuginfo: &mut VarDebugInfo<'tcx>) {
358-
if let VarDebugInfoContents::Place(ref mut place) = debuginfo.value
358+
// If the debuginfo is a pointer to another place:
359+
// - if it's a reborrow, see through it;
360+
// - if it's a direct borrow, increase `debuginfo.references`.
361+
while let VarDebugInfoContents::Place(ref mut place) = debuginfo.value
359362
&& place.projection.is_empty()
360363
&& let Value::Pointer(target, _) = self.targets[place.local]
361364
&& target.projection.iter().all(|p| p.can_use_in_debuginfo())
@@ -369,28 +372,37 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'tcx> {
369372
debuginfo.references = references;
370373
*place = target;
371374
self.any_replacement = true;
375+
} else {
376+
break
372377
}
373378
}
379+
380+
// Simplify eventual projections left inside `debuginfo`.
381+
self.super_var_debug_info(debuginfo);
374382
}
375383

376384
fn visit_place(&mut self, place: &mut Place<'tcx>, ctxt: PlaceContext, loc: Location) {
377-
if place.projection.first() != Some(&PlaceElem::Deref) {
378-
return;
379-
}
380-
381385
loop {
382-
if let Value::Pointer(target, _) = self.targets[place.local] {
383-
let perform_opt = matches!(ctxt, PlaceContext::NonUse(_))
384-
|| self.allowed_replacements.contains(&(target.local, loc));
385-
386-
if perform_opt {
387-
*place = target.project_deeper(&place.projection[1..], self.tcx);
388-
self.any_replacement = true;
389-
continue;
386+
if place.projection.first() != Some(&PlaceElem::Deref) {
387+
return;
388+
}
389+
390+
let Value::Pointer(target, _) = self.targets[place.local] else { return };
391+
392+
let perform_opt = match ctxt {
393+
PlaceContext::NonUse(NonUseContext::VarDebugInfo) => {
394+
target.projection.iter().all(|p| p.can_use_in_debuginfo())
390395
}
396+
PlaceContext::NonUse(_) => true,
397+
_ => self.allowed_replacements.contains(&(target.local, loc)),
398+
};
399+
400+
if !perform_opt {
401+
return;
391402
}
392403

393-
break;
404+
*place = target.project_deeper(&place.projection[1..], self.tcx);
405+
self.any_replacement = true;
394406
}
395407
}
396408

tests/codegen/iter-repeat-n-trivial-drop.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ pub fn iter_repeat_n_next(it: &mut std::iter::RepeatN<NotCopy>) -> Option<NotCop
3333

3434
// CHECK: [[EMPTY]]:
3535
// CHECK-NOT: br
36-
// CHECK: phi i16 [ undef, %start ], [ %[[VAL]], %[[NOT_EMPTY]] ]
36+
// CHECK: phi i16 [ %[[VAL]], %[[NOT_EMPTY]] ], [ undef, %start ]
3737
// CHECK-NOT: br
3838
// CHECK: ret
3939

tests/codegen/slice-init.rs

+10-6
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ pub fn zero_sized_elem() {
88
// CHECK-NOT: br label %repeat_loop_header{{.*}}
99
// CHECK-NOT: call void @llvm.memset.p0
1010
let x = [(); 4];
11-
drop(&x);
11+
opaque(&x);
1212
}
1313

1414
// CHECK-LABEL: @zero_len_array
@@ -17,7 +17,7 @@ pub fn zero_len_array() {
1717
// CHECK-NOT: br label %repeat_loop_header{{.*}}
1818
// CHECK-NOT: call void @llvm.memset.p0
1919
let x = [4; 0];
20-
drop(&x);
20+
opaque(&x);
2121
}
2222

2323
// CHECK-LABEL: @byte_array
@@ -26,7 +26,7 @@ pub fn byte_array() {
2626
// CHECK: call void @llvm.memset.{{.+}}({{i8\*|ptr}} {{.*}}, i8 7, i{{[0-9]+}} 4
2727
// CHECK-NOT: br label %repeat_loop_header{{.*}}
2828
let x = [7u8; 4];
29-
drop(&x);
29+
opaque(&x);
3030
}
3131

3232
#[allow(dead_code)]
@@ -42,7 +42,7 @@ pub fn byte_enum_array() {
4242
// CHECK: call void @llvm.memset.{{.+}}({{i8\*|ptr}} {{.*}}, i8 {{.*}}, i{{[0-9]+}} 4
4343
// CHECK-NOT: br label %repeat_loop_header{{.*}}
4444
let x = [Init::Memset; 4];
45-
drop(&x);
45+
opaque(&x);
4646
}
4747

4848
// CHECK-LABEL: @zeroed_integer_array
@@ -51,7 +51,7 @@ pub fn zeroed_integer_array() {
5151
// CHECK: call void @llvm.memset.{{.+}}({{i8\*|ptr}} {{.*}}, i8 0, i{{[0-9]+}} 16
5252
// CHECK-NOT: br label %repeat_loop_header{{.*}}
5353
let x = [0u32; 4];
54-
drop(&x);
54+
opaque(&x);
5555
}
5656

5757
// CHECK-LABEL: @nonzero_integer_array
@@ -60,5 +60,9 @@ pub fn nonzero_integer_array() {
6060
// CHECK: br label %repeat_loop_header{{.*}}
6161
// CHECK-NOT: call void @llvm.memset.p0
6262
let x = [0x1a_2b_3c_4d_u32; 4];
63-
drop(&x);
63+
opaque(&x);
6464
}
65+
66+
// Use an opaque function to prevent rustc from removing useless drops.
67+
#[inline(never)]
68+
pub fn opaque(_: impl Sized) {}

tests/codegen/slice-ref-equality.rs

+16-16
Original file line numberDiff line numberDiff line change
@@ -44,48 +44,48 @@ pub fn is_zero_array(data: &[u8; 4]) -> bool {
4444
// equality for non-byte types also just emit a `bcmp`, not a loop.
4545

4646
// CHECK-LABEL: @eq_slice_of_nested_u8(
47-
// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %1
48-
// CHECK-SAME: [[USIZE]] noundef %3
47+
// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %x.1
48+
// CHECK-SAME: [[USIZE]] noundef %y.1
4949
#[no_mangle]
5050
fn eq_slice_of_nested_u8(x: &[[u8; 3]], y: &[[u8; 3]]) -> bool {
51-
// CHECK: icmp eq [[USIZE]] %1, %3
52-
// CHECK: %[[BYTES:.+]] = mul nsw [[USIZE]] %1, 3
51+
// CHECK: icmp eq [[USIZE]] %x.1, %y.1
52+
// CHECK: %[[BYTES:.+]] = mul nsw [[USIZE]] %x.1, 3
5353
// CHECK: tail call{{( noundef)?}} i32 @{{bcmp|memcmp}}({{i8\*|ptr}}
5454
// CHECK-SAME: , [[USIZE]]{{( noundef)?}} %[[BYTES]])
5555
x == y
5656
}
5757

5858
// CHECK-LABEL: @eq_slice_of_i32(
59-
// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %1
60-
// CHECK-SAME: [[USIZE]] noundef %3
59+
// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %x.1
60+
// CHECK-SAME: [[USIZE]] noundef %y.1
6161
#[no_mangle]
6262
fn eq_slice_of_i32(x: &[i32], y: &[i32]) -> bool {
63-
// CHECK: icmp eq [[USIZE]] %1, %3
64-
// CHECK: %[[BYTES:.+]] = shl nsw [[USIZE]] %1, 2
63+
// CHECK: icmp eq [[USIZE]] %x.1, %y.1
64+
// CHECK: %[[BYTES:.+]] = shl nsw [[USIZE]] %x.1, 2
6565
// CHECK: tail call{{( noundef)?}} i32 @{{bcmp|memcmp}}({{i32\*|ptr}}
6666
// CHECK-SAME: , [[USIZE]]{{( noundef)?}} %[[BYTES]])
6767
x == y
6868
}
6969

7070
// CHECK-LABEL: @eq_slice_of_nonzero(
71-
// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %1
72-
// CHECK-SAME: [[USIZE]] noundef %3
71+
// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %x.1
72+
// CHECK-SAME: [[USIZE]] noundef %y.1
7373
#[no_mangle]
7474
fn eq_slice_of_nonzero(x: &[NonZeroU32], y: &[NonZeroU32]) -> bool {
75-
// CHECK: icmp eq [[USIZE]] %1, %3
76-
// CHECK: %[[BYTES:.+]] = shl nsw [[USIZE]] %1, 2
75+
// CHECK: icmp eq [[USIZE]] %x.1, %y.1
76+
// CHECK: %[[BYTES:.+]] = shl nsw [[USIZE]] %x.1, 2
7777
// CHECK: tail call{{( noundef)?}} i32 @{{bcmp|memcmp}}({{i32\*|ptr}}
7878
// CHECK-SAME: , [[USIZE]]{{( noundef)?}} %[[BYTES]])
7979
x == y
8080
}
8181

8282
// CHECK-LABEL: @eq_slice_of_option_of_nonzero(
83-
// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %1
84-
// CHECK-SAME: [[USIZE]] noundef %3
83+
// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %x.1
84+
// CHECK-SAME: [[USIZE]] noundef %y.1
8585
#[no_mangle]
8686
fn eq_slice_of_option_of_nonzero(x: &[Option<NonZeroI16>], y: &[Option<NonZeroI16>]) -> bool {
87-
// CHECK: icmp eq [[USIZE]] %1, %3
88-
// CHECK: %[[BYTES:.+]] = shl nsw [[USIZE]] %1, 1
87+
// CHECK: icmp eq [[USIZE]] %x.1, %y.1
88+
// CHECK: %[[BYTES:.+]] = shl nsw [[USIZE]] %x.1, 1
8989
// CHECK: tail call{{( noundef)?}} i32 @{{bcmp|memcmp}}({{i16\*|ptr}}
9090
// CHECK-SAME: , [[USIZE]]{{( noundef)?}} %[[BYTES]])
9191
x == y

tests/incremental/hashes/call_expressions.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ pub fn change_to_ufcs() {
162162
}
163163

164164
#[cfg(not(any(cfail1,cfail4)))]
165-
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
165+
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")]
166166
#[rustc_clean(cfg="cfail3")]
167167
#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
168168
#[rustc_clean(cfg="cfail6")]

tests/mir-opt/casts.redundant.InstSimplify.diff

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
let mut _2: *const &u8;
88
let mut _3: *const &u8;
99
scope 1 (inlined generic_cast::<&u8, &u8>) {
10-
debug x => _3;
10+
debug x => _1;
1111
}
1212

1313
bb0: {

tests/mir-opt/copy-prop/mutate_through_pointer.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// unit-test: CopyProp
2+
//
13
// This attempts to mutate `a` via a pointer derived from `addr_of!(a)`. That is UB
24
// according to Miri. However, the decision to make this UB - and to allow
35
// rustc to rely on that fact for the purpose of optimizations - has not been

tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff

+4-7
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@
77
let mut _2: std::option::Option<T>;
88
+ scope 1 (inlined #[track_caller] Option::<T>::unwrap_unchecked) {
99
+ debug self => _2;
10-
+ let mut _3: &std::option::Option<T>;
11-
+ let mut _4: isize;
10+
+ let mut _3: isize;
1211
+ scope 2 {
1312
+ debug val => _0;
1413
+ }
@@ -21,17 +20,16 @@
2120
+ }
2221
+ }
2322
+ scope 4 (inlined Option::<T>::is_some) {
24-
+ debug self => _3;
23+
+ debug self => &_2;
2524
+ }
2625
+ }
2726

2827
bb0: {
2928
StorageLive(_2);
3029
_2 = move _1;
3130
- _0 = Option::<T>::unwrap_unchecked(move _2) -> [return: bb1, unwind unreachable];
32-
+ StorageLive(_3);
33-
+ _4 = discriminant(_2);
34-
+ switchInt(move _4) -> [1: bb2, otherwise: bb1];
31+
+ _3 = discriminant(_2);
32+
+ switchInt(move _3) -> [1: bb2, otherwise: bb1];
3533
}
3634

3735
bb1: {
@@ -40,7 +38,6 @@
4038
+
4139
+ bb2: {
4240
+ _0 = move ((_2 as Some).0: T);
43-
+ StorageDead(_3);
4441
StorageDead(_2);
4542
return;
4643
}

tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff

+4-7
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@
77
let mut _2: std::option::Option<T>;
88
+ scope 1 (inlined #[track_caller] Option::<T>::unwrap_unchecked) {
99
+ debug self => _2;
10-
+ let mut _3: &std::option::Option<T>;
11-
+ let mut _4: isize;
10+
+ let mut _3: isize;
1211
+ scope 2 {
1312
+ debug val => _0;
1413
+ }
@@ -21,17 +20,16 @@
2120
+ }
2221
+ }
2322
+ scope 4 (inlined Option::<T>::is_some) {
24-
+ debug self => _3;
23+
+ debug self => &_2;
2524
+ }
2625
+ }
2726

2827
bb0: {
2928
StorageLive(_2);
3029
_2 = move _1;
3130
- _0 = Option::<T>::unwrap_unchecked(move _2) -> [return: bb1, unwind: bb2];
32-
+ StorageLive(_3);
33-
+ _4 = discriminant(_2);
34-
+ switchInt(move _4) -> [1: bb2, otherwise: bb1];
31+
+ _3 = discriminant(_2);
32+
+ switchInt(move _3) -> [1: bb2, otherwise: bb1];
3533
}
3634

3735
bb1: {
@@ -44,7 +42,6 @@
4442
- resume;
4543
+ bb2: {
4644
+ _0 = move ((_2 as Some).0: T);
47-
+ StorageDead(_3);
4845
+ StorageDead(_2);
4946
+ return;
5047
}

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

+1-4
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ fn unwrap_unchecked(_1: Option<T>) -> T {
66
scope 1 (inlined #[track_caller] Option::<T>::unwrap_unchecked) {
77
debug self => _1;
88
let mut _2: isize;
9-
let mut _3: &std::option::Option<T>;
109
scope 2 {
1110
debug val => _0;
1211
}
@@ -19,19 +18,17 @@ fn unwrap_unchecked(_1: Option<T>) -> T {
1918
}
2019
}
2120
scope 4 (inlined Option::<T>::is_some) {
22-
debug self => _3;
21+
debug self => &_1;
2322
}
2423
}
2524

2625
bb0: {
27-
StorageLive(_3);
2826
_2 = discriminant(_1);
2927
switchInt(move _2) -> [1: bb1, otherwise: bb2];
3028
}
3129

3230
bb1: {
3331
_0 = move ((_1 as Some).0: T);
34-
StorageDead(_3);
3532
return;
3633
}
3734

tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir

+1-4
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ fn unwrap_unchecked(_1: Option<T>) -> T {
66
scope 1 (inlined #[track_caller] Option::<T>::unwrap_unchecked) {
77
debug self => _1;
88
let mut _2: isize;
9-
let mut _3: &std::option::Option<T>;
109
scope 2 {
1110
debug val => _0;
1211
}
@@ -19,19 +18,17 @@ fn unwrap_unchecked(_1: Option<T>) -> T {
1918
}
2019
}
2120
scope 4 (inlined Option::<T>::is_some) {
22-
debug self => _3;
21+
debug self => &_1;
2322
}
2423
}
2524

2625
bb0: {
27-
StorageLive(_3);
2826
_2 = discriminant(_1);
2927
switchInt(move _2) -> [1: bb1, otherwise: bb2];
3028
}
3129

3230
bb1: {
3331
_0 = move ((_1 as Some).0: T);
34-
StorageDead(_3);
3532
return;
3633
}
3734

0 commit comments

Comments
 (0)