about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-02-27 04:51:34 +0000
committerbors <bors@rust-lang.org>2020-02-27 04:51:34 +0000
commitd28560e660168b30af3b58167094aeb299bc2b58 (patch)
tree1069e81fa52193fb5b0499c0d07d3f6864ff387a /src
parent0c15adc5308b92919580e98f2fd77cdd448f24a0 (diff)
parentb9445311462549fdc22e5ca0732be60c1b2a5d32 (diff)
downloadrust-d28560e660168b30af3b58167094aeb299bc2b58.tar.gz
rust-d28560e660168b30af3b58167094aeb299bc2b58.zip
Auto merge of #67332 - matthewjasper:drop-in-place-cgus, r=michaelwoerister
Don't instantiate so many copies of drop_in_place

Split out from #66703.

r? @ghost
Diffstat (limited to 'src')
-rw-r--r--src/librustc/ty/instance.rs25
-rw-r--r--src/librustc_mir/monomorphize/partitioning.rs13
-rw-r--r--src/test/codegen-units/partitioning/extern-drop-glue.rs17
-rw-r--r--src/test/codegen-units/partitioning/local-drop-glue.rs39
4 files changed, 54 insertions, 40 deletions
diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs
index 0ec30bc583c..66888cdb552 100644
--- a/src/librustc/ty/instance.rs
+++ b/src/librustc/ty/instance.rs
@@ -53,7 +53,10 @@ pub enum InstanceDef<'tcx> {
         call_once: DefId,
     },
 
-    /// `drop_in_place::<T>; None` for empty drop glue.
+    /// `core::ptr::drop_in_place::<T>`.
+    /// The `DefId` is for `core::ptr::drop_in_place`.
+    /// The `Option<Ty<'tcx>>` is either `Some(T)`, or `None` for empty drop
+    /// glue.
     DropGlue(DefId, Option<Ty<'tcx>>),
 
     ///`<T as Clone>::clone` shim.
@@ -176,11 +179,25 @@ impl<'tcx> InstanceDef<'tcx> {
         if self.requires_inline(tcx) {
             return true;
         }
-        if let ty::InstanceDef::DropGlue(..) = *self {
-            // Drop glue wants to be instantiated at every codegen
+        if let ty::InstanceDef::DropGlue(.., Some(ty)) = *self {
+            // Drop glue generally wants to be instantiated at every codegen
             // unit, but without an #[inline] hint. We should make this
             // available to normal end-users.
-            return true;
+            if tcx.sess.opts.incremental.is_none() {
+                return true;
+            }
+            // When compiling with incremental, we can generate a *lot* of
+            // codegen units. Including drop glue into all of them has a
+            // considerable compile time cost.
+            //
+            // We include enums without destructors to allow, say, optimizing
+            // drops of `Option::None` before LTO. We also respect the intent of
+            // `#[inline]` on `Drop::drop` implementations.
+            return ty.ty_adt_def().map_or(true, |adt_def| {
+                adt_def.destructor(tcx).map_or(adt_def.is_enum(), |dtor| {
+                    tcx.codegen_fn_attrs(dtor.did).requests_inline()
+                })
+            });
         }
         tcx.codegen_fn_attrs(self.def_id()).requests_inline()
     }
diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs
index de45808a481..9b81d69ce69 100644
--- a/src/librustc_mir/monomorphize/partitioning.rs
+++ b/src/librustc_mir/monomorphize/partitioning.rs
@@ -680,13 +680,20 @@ fn characteristic_def_id_of_mono_item<'tcx>(
 
             if tcx.trait_of_item(def_id).is_some() {
                 let self_ty = instance.substs.type_at(0);
-                // This is an implementation of a trait method.
+                // This is a default implementation of a trait method.
                 return characteristic_def_id_of_type(self_ty).or(Some(def_id));
             }
 
             if let Some(impl_def_id) = tcx.impl_of_method(def_id) {
-                // This is a method within an inherent impl, find out what the
-                // self-type is:
+                if tcx.sess.opts.incremental.is_some()
+                    && tcx.trait_id_of_impl(impl_def_id) == tcx.lang_items().drop_trait()
+                {
+                    // Put `Drop::drop` into the same cgu as `drop_in_place`
+                    // since `drop_in_place` is the only thing that can
+                    // call it.
+                    return None;
+                }
+                // This is a method within an impl, find out what the self-type is:
                 let impl_self_ty = tcx.subst_and_normalize_erasing_regions(
                     instance.substs,
                     ty::ParamEnv::reveal_all(),
diff --git a/src/test/codegen-units/partitioning/extern-drop-glue.rs b/src/test/codegen-units/partitioning/extern-drop-glue.rs
index f85ae0c0774..662519067d7 100644
--- a/src/test/codegen-units/partitioning/extern-drop-glue.rs
+++ b/src/test/codegen-units/partitioning/extern-drop-glue.rs
@@ -2,23 +2,23 @@
 
 // We specify -Z incremental here because we want to test the partitioning for
 // incremental compilation
+// We specify opt-level=0 because `drop_in_place` is `Internal` when optimizing
 // compile-flags:-Zprint-mono-items=lazy -Zincremental=tmp/partitioning-tests/extern-drop-glue
-// compile-flags:-Zinline-in-all-cgus
+// compile-flags:-Zinline-in-all-cgus -Copt-level=0
 
 #![allow(dead_code)]
-#![crate_type="rlib"]
+#![crate_type = "rlib"]
 
 // aux-build:cgu_extern_drop_glue.rs
 extern crate cgu_extern_drop_glue;
 
-//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<cgu_extern_drop_glue::Struct[0]> @@ extern_drop_glue[Internal] extern_drop_glue-mod1[Internal]
+//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<cgu_extern_drop_glue::Struct[0]> @@ extern_drop_glue-fallback.cgu[External]
 
 struct LocalStruct(cgu_extern_drop_glue::Struct);
 
 //~ MONO_ITEM fn extern_drop_glue::user[0] @@ extern_drop_glue[External]
-pub fn user()
-{
-    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<extern_drop_glue::LocalStruct[0]> @@ extern_drop_glue[Internal]
+pub fn user() {
+    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<extern_drop_glue::LocalStruct[0]> @@ extern_drop_glue-fallback.cgu[External]
     let _ = LocalStruct(cgu_extern_drop_glue::Struct(0));
 }
 
@@ -28,9 +28,8 @@ pub mod mod1 {
     struct LocalStruct(cgu_extern_drop_glue::Struct);
 
     //~ MONO_ITEM fn extern_drop_glue::mod1[0]::user[0] @@ extern_drop_glue-mod1[External]
-    pub fn user()
-    {
-        //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<extern_drop_glue::mod1[0]::LocalStruct[0]> @@ extern_drop_glue-mod1[Internal]
+    pub fn user() {
+        //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<extern_drop_glue::mod1[0]::LocalStruct[0]> @@ extern_drop_glue-fallback.cgu[External]
         let _ = LocalStruct(cgu_extern_drop_glue::Struct(0));
     }
 }
diff --git a/src/test/codegen-units/partitioning/local-drop-glue.rs b/src/test/codegen-units/partitioning/local-drop-glue.rs
index 366af4d4c38..14a50bf5798 100644
--- a/src/test/codegen-units/partitioning/local-drop-glue.rs
+++ b/src/test/codegen-units/partitioning/local-drop-glue.rs
@@ -1,54 +1,45 @@
 // ignore-tidy-linelength
 // We specify -Z incremental here because we want to test the partitioning for
 // incremental compilation
+// We specify opt-level=0 because `drop_in_place` is `Internal` when optimizing
 // compile-flags:-Zprint-mono-items=lazy -Zincremental=tmp/partitioning-tests/local-drop-glue
-// compile-flags:-Zinline-in-all-cgus
+// compile-flags:-Zinline-in-all-cgus -Copt-level=0
 
 #![allow(dead_code)]
-#![crate_type="rlib"]
+#![crate_type = "rlib"]
 
-//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<local_drop_glue::Struct[0]> @@ local_drop_glue[Internal] local_drop_glue-mod1[Internal]
+//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<local_drop_glue::Struct[0]> @@ local_drop_glue-fallback.cgu[External]
 struct Struct {
-    _a: u32
+    _a: u32,
 }
 
 impl Drop for Struct {
-    //~ MONO_ITEM fn local_drop_glue::{{impl}}[0]::drop[0] @@ local_drop_glue[External]
+    //~ MONO_ITEM fn local_drop_glue::{{impl}}[0]::drop[0] @@ local_drop_glue-fallback.cgu[External]
     fn drop(&mut self) {}
 }
 
-//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<local_drop_glue::Outer[0]> @@ local_drop_glue[Internal]
+//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<local_drop_glue::Outer[0]> @@ local_drop_glue-fallback.cgu[External]
 struct Outer {
-    _a: Struct
+    _a: Struct,
 }
 
 //~ MONO_ITEM fn local_drop_glue::user[0] @@ local_drop_glue[External]
-pub fn user()
-{
-    let _ = Outer {
-        _a: Struct {
-            _a: 0
-        }
-    };
+pub fn user() {
+    let _ = Outer { _a: Struct { _a: 0 } };
 }
 
-pub mod mod1
-{
+pub mod mod1 {
     use super::Struct;
 
-    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<local_drop_glue::mod1[0]::Struct2[0]> @@ local_drop_glue-mod1[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<local_drop_glue::mod1[0]::Struct2[0]> @@ local_drop_glue-fallback.cgu[External]
     struct Struct2 {
         _a: Struct,
-        //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<(u32, local_drop_glue::Struct[0])> @@ local_drop_glue-mod1[Internal]
+        //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<(u32, local_drop_glue::Struct[0])> @@ local_drop_glue-fallback.cgu[Internal]
         _b: (u32, Struct),
     }
 
     //~ MONO_ITEM fn local_drop_glue::mod1[0]::user[0] @@ local_drop_glue-mod1[External]
-    pub fn user()
-    {
-        let _ = Struct2 {
-            _a: Struct { _a: 0 },
-            _b: (0, Struct { _a: 0 }),
-        };
+    pub fn user() {
+        let _ = Struct2 { _a: Struct { _a: 0 }, _b: (0, Struct { _a: 0 }) };
     }
 }