Skip to content

Commit c542469

Browse files
Auto merge of #142508 - Mark-Simulacrum:skip-noop-drop-glue, r=<try>
Skip no-op drop glue Since #122662 this no longer gets used in vtables, so we're safe to fully drop generating these empty functions. Those are eventually cleaned up by LLVM, but it's wasteful to produce them in the first place. This doesn't appear to be a significant win (and shows some slight regressions) but seems like the right thing to do. At minimum it reduces noise in the LLVM IR we generate, which seems like a good thing. try-job: x86_64-gnu-aux try-job: dist-x86_64-linux
2 parents d4e1159 + dcac9c3 commit c542469

File tree

6 files changed

+85
-17
lines changed

6 files changed

+85
-17
lines changed

compiler/rustc_monomorphize/src/collector.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -949,6 +949,9 @@ fn visit_instance_use<'tcx>(
949949
}
950950
ty::InstanceKind::DropGlue(_, None) => {
951951
// Don't need to emit noop drop glue if we are calling directly.
952+
//
953+
// Note that we also optimize away the call to visit_instance_use in vtable construction
954+
// (see create_mono_items_for_vtable_methods).
952955
if !is_direct_call {
953956
output.push(create_fn_mono_item(tcx, instance, source));
954957
}
@@ -1177,8 +1180,13 @@ fn create_mono_items_for_vtable_methods<'tcx>(
11771180
output.extend(methods);
11781181
}
11791182

1180-
// Also add the destructor.
1181-
visit_drop_use(tcx, impl_ty, false, source, output);
1183+
// Also add the destructor, if it's necessary.
1184+
//
1185+
// This matches the check in vtable_allocation_provider in middle/ty/vtable.rs,
1186+
// if we don't need drop we're not adding an actual pointer to the vtable.
1187+
if impl_ty.needs_drop(tcx, ty::TypingEnv::fully_monomorphized()) {
1188+
visit_drop_use(tcx, impl_ty, false, source, output);
1189+
}
11821190
}
11831191

11841192
/// Scans the CTFE alloc in order to find function pointers and statics that must be monomorphized.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//@ compile-flags:-Clink-dead-code -Zmir-opt-level=0
2+
3+
#![deny(dead_code)]
4+
#![crate_type = "lib"]
5+
6+
//~ MONO_ITEM fn start
7+
#[no_mangle]
8+
pub fn start(_: isize, _: *const *const u8) -> isize {
9+
// No item produced for this, it's a no-op drop and so is removed.
10+
unsafe {
11+
std::ptr::drop_in_place::<u32>(&mut 0);
12+
}
13+
14+
// No choice but to codegen for indirect drop as a function pointer, since we have to produce a
15+
// function with the right signature. In vtables we can avoid that (tested in
16+
// instantiation-through-vtable.rs) because we special case null pointer for drop glue since
17+
// #122662.
18+
//
19+
//~ MONO_ITEM fn std::ptr::drop_in_place::<u64> - shim(None) @@ drop_glue_noop-cgu.0[External]
20+
std::ptr::drop_in_place::<u64> as unsafe fn(*mut u64);
21+
22+
0
23+
}

tests/codegen-units/item-collection/instantiation-through-vtable.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,13 @@ impl<T> Trait for Struct<T> {
2424
pub fn start(_: isize, _: *const *const u8) -> isize {
2525
let s1 = Struct { _a: 0u32 };
2626

27-
//~ MONO_ITEM fn std::ptr::drop_in_place::<Struct<u32>> - shim(None) @@ instantiation_through_vtable-cgu.0[External]
2827
//~ MONO_ITEM fn <Struct<u32> as Trait>::foo
2928
//~ MONO_ITEM fn <Struct<u32> as Trait>::bar
3029
let r1 = &s1 as &Trait;
3130
r1.foo();
3231
r1.bar();
3332

3433
let s1 = Struct { _a: 0u64 };
35-
//~ MONO_ITEM fn std::ptr::drop_in_place::<Struct<u64>> - shim(None) @@ instantiation_through_vtable-cgu.0[External]
3634
//~ MONO_ITEM fn <Struct<u64> as Trait>::foo
3735
//~ MONO_ITEM fn <Struct<u64> as Trait>::bar
3836
let _ = &s1 as &Trait;

tests/codegen-units/item-collection/non-generic-closures.rs

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//@ compile-flags:-Clink-dead-code -Zinline-mir=no
1+
//@ compile-flags:-Clink-dead-code -Zinline-mir=no -Zhuman-readable-cgu-names
22

33
#![deny(dead_code)]
44
#![crate_type = "lib"]
@@ -22,9 +22,8 @@ fn assigned_to_variable_but_not_executed() {
2222
//~ MONO_ITEM fn assigned_to_variable_executed_indirectly @@ non_generic_closures-cgu.0[External]
2323
fn assigned_to_variable_executed_indirectly() {
2424
//~ MONO_ITEM fn assigned_to_variable_executed_indirectly::{closure#0} @@ non_generic_closures-cgu.0[External]
25-
//~ MONO_ITEM fn <{closure@TEST_PATH:28:13: 28:21} as std::ops::FnOnce<(i32,)>>::call_once - shim @@ non_generic_closures-cgu.0[External]
26-
//~ MONO_ITEM fn <{closure@TEST_PATH:28:13: 28:21} as std::ops::FnOnce<(i32,)>>::call_once - shim(vtable) @@ non_generic_closures-cgu.0[External]
27-
//~ MONO_ITEM fn std::ptr::drop_in_place::<{closure@TEST_PATH:28:13: 28:21}> - shim(None) @@ non_generic_closures-cgu.0[External]
25+
//~ MONO_ITEM fn <{closure@TEST_PATH:27:13: 27:21} as std::ops::FnOnce<(i32,)>>::call_once - shim @@ non_generic_closures-cgu.0[External]
26+
//~ MONO_ITEM fn <{closure@TEST_PATH:27:13: 27:21} as std::ops::FnOnce<(i32,)>>::call_once - shim(vtable) @@ non_generic_closures-cgu.0[External]
2827
let f = |a: i32| {
2928
let _ = a + 2;
3029
};
@@ -40,13 +39,28 @@ fn assigned_to_variable_executed_directly() {
4039
f(4);
4140
}
4241

42+
// Make sure we generate mono items for stateful closures that need dropping
43+
//~ MONO_ITEM fn with_drop @@ non_generic_closures-cgu.0[External]
44+
fn with_drop(v: PresentDrop) {
45+
//~ MONO_ITEM fn with_drop::{closure#0} @@ non_generic_closures-cgu.0[External]
46+
//~ MONO_ITEM fn std::ptr::drop_in_place::<PresentDrop> - shim(Some(PresentDrop)) @@ non_generic_closures-cgu.0[Internal]
47+
//~ MONO_ITEM fn std::ptr::drop_in_place::<{closure@TEST_PATH:49:14: 49:24}> - shim(Some({closure@TEST_PATH:49:14: 49:24})) @@ non_generic_closures-cgu.0[Internal]
48+
49+
let _f = |a: usize| {
50+
let _ = a + 2;
51+
//~ MONO_ITEM fn std::mem::drop::<PresentDrop> @@ non_generic_closures-cgu.0[External]
52+
drop(v);
53+
};
54+
}
55+
4356
//~ MONO_ITEM fn start @@ non_generic_closures-cgu.0[External]
4457
#[no_mangle]
4558
pub fn start(_: isize, _: *const *const u8) -> isize {
4659
temporary();
4760
assigned_to_variable_but_not_executed();
4861
assigned_to_variable_executed_directly();
4962
assigned_to_variable_executed_indirectly();
63+
with_drop(PresentDrop);
5064

5165
0
5266
}
@@ -55,3 +69,10 @@ pub fn start(_: isize, _: *const *const u8) -> isize {
5569
fn run_closure(f: &Fn(i32)) {
5670
f(3);
5771
}
72+
73+
struct PresentDrop;
74+
75+
impl Drop for PresentDrop {
76+
//~ MONO_ITEM fn <PresentDrop as std::ops::Drop>::drop @@ non_generic_closures-cgu.0[External]
77+
fn drop(&mut self) {}
78+
}

tests/codegen-units/item-collection/unsizing.rs

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,33 +42,47 @@ struct Wrapper<T: ?Sized>(#[allow(dead_code)] *const T);
4242

4343
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Wrapper<U>> for Wrapper<T> {}
4444

45+
struct PresentDrop;
46+
47+
impl Drop for PresentDrop {
48+
fn drop(&mut self) {}
49+
}
50+
51+
// Custom Coercion Case
52+
impl Trait for PresentDrop {
53+
fn foo(&self) {}
54+
}
55+
4556
//~ MONO_ITEM fn start
4657
#[no_mangle]
4758
pub fn start(_: isize, _: *const *const u8) -> isize {
4859
// simple case
4960
let bool_sized = &true;
50-
//~ MONO_ITEM fn std::ptr::drop_in_place::<bool> - shim(None) @@ unsizing-cgu.0[Internal]
5161
//~ MONO_ITEM fn <bool as Trait>::foo
5262
let _bool_unsized = bool_sized as &Trait;
5363

5464
let char_sized = &'a';
5565

56-
//~ MONO_ITEM fn std::ptr::drop_in_place::<char> - shim(None) @@ unsizing-cgu.0[Internal]
5766
//~ MONO_ITEM fn <char as Trait>::foo
5867
let _char_unsized = char_sized as &Trait;
5968

6069
// struct field
6170
let struct_sized = &Struct { _a: 1, _b: 2, _c: 3.0f64 };
62-
//~ MONO_ITEM fn std::ptr::drop_in_place::<f64> - shim(None) @@ unsizing-cgu.0[Internal]
6371
//~ MONO_ITEM fn <f64 as Trait>::foo
6472
let _struct_unsized = struct_sized as &Struct<Trait>;
6573

6674
// custom coercion
6775
let wrapper_sized = Wrapper(&0u32);
68-
//~ MONO_ITEM fn std::ptr::drop_in_place::<u32> - shim(None) @@ unsizing-cgu.0[Internal]
6976
//~ MONO_ITEM fn <u32 as Trait>::foo
7077
let _wrapper_sized = wrapper_sized as Wrapper<Trait>;
7178

79+
// with drop
80+
let droppable = &PresentDrop;
81+
//~ MONO_ITEM fn <PresentDrop as std::ops::Drop>::drop @@ unsizing-cgu.0[Internal]
82+
//~ MONO_ITEM fn std::ptr::drop_in_place::<PresentDrop> - shim(Some(PresentDrop)) @@ unsizing-cgu.0[Internal]
83+
//~ MONO_ITEM fn <PresentDrop as Trait>::foo
84+
let droppable = droppable as &dyn Trait;
85+
7286
false.foo();
7387

7488
0
Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
// Verifies that type metadata identifiers for drop functions are emitted correctly.
22
//
3+
// Non needs_drop drop glue isn't codegen'd at all, so we don't try to check the IDs there. But we
4+
// do check it's not emitted which should help catch bugs if we do start generating it again in the
5+
// future.
6+
//
37
//@ needs-sanitizer-cfi
48
//@ compile-flags: -Clto -Cno-prepopulate-passes -Copt-level=0 -Zsanitizer=cfi -Ctarget-feature=-crt-static
59

@@ -10,18 +14,18 @@
1014
// CHECK: call i1 @llvm.type.test(ptr {{%.+}}, metadata !"_ZTSFvPu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops4drop4Dropu6regionEE")
1115

1216
struct EmptyDrop;
13-
// CHECK: define{{.*}}4core3ptr{{[0-9]+}}drop_in_place$LT${{.*}}EmptyDrop$GT${{.*}}!type ![[TYPE1]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
17+
// CHECK-NOT: define{{.*}}4core3ptr{{[0-9]+}}drop_in_place$LT${{.*}}EmptyDrop$GT${{.*}}!type ![[TYPE1]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
1418

15-
struct NonEmptyDrop;
19+
struct PresentDrop;
1620

17-
impl Drop for NonEmptyDrop {
21+
impl Drop for PresentDrop {
1822
fn drop(&mut self) {}
19-
// CHECK: define{{.*}}4core3ptr{{[0-9]+}}drop_in_place$LT${{.*}}NonEmptyDrop$GT${{.*}}!type ![[TYPE1]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
23+
// CHECK: define{{.*}}4core3ptr{{[0-9]+}}drop_in_place$LT${{.*}}PresentDrop$GT${{.*}}!type ![[TYPE1]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
2024
}
2125

2226
pub fn foo() {
2327
let _ = Box::new(EmptyDrop) as Box<dyn Send>;
24-
let _ = Box::new(NonEmptyDrop) as Box<dyn Send>;
28+
let _ = Box::new(PresentDrop) as Box<dyn Send>;
2529
}
2630

2731
// CHECK: ![[TYPE1]] = !{i64 0, !"_ZTSFvPu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops4drop4Dropu6regionEE"}

0 commit comments

Comments
 (0)