about summary refs log tree commit diff
diff options
context:
space:
mode:
authorErik Desjardins <erikdesjardins@users.noreply.github.com>2021-12-29 15:28:31 -0500
committerErik Desjardins <erikdesjardins@users.noreply.github.com>2021-12-29 15:47:49 -0500
commit2b662217e745d88d93dcc6f5f5169bf7a0d9720e (patch)
tree0e471ecb5e4a57ae2f5f3aa70fdfe5895cf99e91
parent7ae550842635dce84811198446fe87e830de500b (diff)
Mark drop calls in landing pads cold instead of noinline
Now that deferred inlining has been disabled in LLVM,
this shouldn't cause catastrophic size blowup.
-rw-r--r--compiler/rustc_codegen_gcc/src/builder.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/builder.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/block.rs7
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/builder.rs2
-rw-r--r--src/test/codegen/unwind-landingpad-cold.rs14
-rw-r--r--src/test/codegen/unwind-landingpad-inline.rs22
6 files changed, 42 insertions, 9 deletions
diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs
index fff2aa6df7c..997213d43e8 100644
--- a/compiler/rustc_codegen_gcc/src/builder.rs
+++ b/compiler/rustc_codegen_gcc/src/builder.rs
@@ -1404,7 +1404,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
         self.cx
     }
 
-    fn do_not_inline(&mut self, _llret: RValue<'gcc>) {
+    fn mark_callsite_cold(&mut self, _llret: RValue<'gcc>) {
         unimplemented!();
     }
 
diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs
index 8c3054b23ff..107300ed304 100644
--- a/compiler/rustc_codegen_llvm/src/builder.rs
+++ b/compiler/rustc_codegen_llvm/src/builder.rs
@@ -1201,8 +1201,8 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         unsafe { llvm::LLVMBuildZExt(self.llbuilder, val, dest_ty, UNNAMED) }
     }
 
-    fn do_not_inline(&mut self, llret: &'ll Value) {
-        llvm::Attribute::NoInline.apply_callsite(llvm::AttributePlace::Function, llret);
+    fn mark_callsite_cold(&mut self, llret: &'ll Value) {
+        llvm::Attribute::Cold.apply_callsite(llvm::AttributePlace::Function, llret);
     }
 }
 
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index e914e493269..8cefd415e28 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -160,11 +160,8 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
             let llret = bx.call(fn_ty, fn_ptr, &llargs, self.funclet(fx));
             bx.apply_attrs_callsite(&fn_abi, llret);
             if fx.mir[self.bb].is_cleanup {
-                // Cleanup is always the cold path. Don't inline
-                // drop glue. Also, when there is a deeply-nested
-                // struct, there are "symmetry" issues that cause
-                // exponential inlining - see issue #41696.
-                bx.do_not_inline(llret);
+                // Cleanup is always the cold path.
+                bx.mark_callsite_cold(llret);
             }
 
             if let Some((ret_dest, target)) = destination {
diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs
index 158e658301e..c1cdff3adda 100644
--- a/compiler/rustc_codegen_ssa/src/traits/builder.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs
@@ -311,5 +311,5 @@ pub trait BuilderMethods<'a, 'tcx>:
     ) -> Self::Value;
     fn zext(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value;
 
-    fn do_not_inline(&mut self, llret: Self::Value);
+    fn mark_callsite_cold(&mut self, llret: Self::Value);
 }
diff --git a/src/test/codegen/unwind-landingpad-cold.rs b/src/test/codegen/unwind-landingpad-cold.rs
new file mode 100644
index 00000000000..0bf2941374a
--- /dev/null
+++ b/src/test/codegen/unwind-landingpad-cold.rs
@@ -0,0 +1,14 @@
+// compile-flags: -Cno-prepopulate-passes
+#![crate_type = "lib"]
+
+// This test checks that drop calls in unwind landing pads
+// get the `cold` attribute.
+
+// CHECK-LABEL: @check_cold
+// CHECK: call void {{.+}}drop_in_place{{.+}} [[ATTRIBUTES:#[0-9]+]]
+// CHECK: attributes [[ATTRIBUTES]] = { cold }
+#[no_mangle]
+pub fn check_cold(f: fn(), x: Box<u32>) {
+    // this may unwind
+    f();
+}
diff --git a/src/test/codegen/unwind-landingpad-inline.rs b/src/test/codegen/unwind-landingpad-inline.rs
new file mode 100644
index 00000000000..d641c908ea9
--- /dev/null
+++ b/src/test/codegen/unwind-landingpad-inline.rs
@@ -0,0 +1,22 @@
+// no-system-llvm: needs patch for Rust alloc/dealloc functions
+// compile-flags: -Copt-level=3
+#![crate_type = "lib"]
+
+// This test checks that we can inline drop_in_place in
+// unwind landing pads. Without this, the box pointers escape,
+// and LLVM will not optimize out the pointer comparison.
+// See https://github.com/rust-lang/rust/issues/46515
+
+// Everything should be optimized out.
+// CHECK-LABEL: @check_no_escape_in_landingpad
+// CHECK: start:
+// CHECK-NEXT: ret void
+#[no_mangle]
+pub fn check_no_escape_in_landingpad(f: fn()) {
+    let x = &*Box::new(0);
+    let y = &*Box::new(0);
+
+    if x as *const _ == y as *const _ {
+        f();
+    }
+}