-
Notifications
You must be signed in to change notification settings - Fork 12.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Avoid quadratic growth of functions due to cleanups
If a new cleanup is added to a cleanup scope, the cached exits for that scope are cleared, so all previous cleanups have to be translated again. In the worst case this means that we get N distinct landing pads where the last one has N cleanups, then N-1 and so on. As new cleanups are to be executed before older ones, we can instead cache the number of already translated cleanups in addition to the block that contains them, and then only translate new ones, if any and then jump to the cached ones, getting away with linear growth instead. For the crate in #31381 this reduces the compile time for an optimized build from >20 minutes (I cancelled the build at that point) to about 11 seconds. Testing a few crates that come with rustc show compile time improvements somewhere between 1 and 8%. The "big" winner being rustc_platform_intrinsics which features code similar to that in #31381. Fixes #31381
- Loading branch information
Showing
2 changed files
with
71 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT | ||
// file at the top-level directory of this distribution and at | ||
// http://rust-lang.org/COPYRIGHT. | ||
// | ||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | ||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | ||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | ||
// option. This file may not be copied, modified, or distributed | ||
// except according to those terms. | ||
|
||
// compile-flags: -C no-prepopulate-passes | ||
|
||
#![crate_type = "lib"] | ||
|
||
struct SomeUniqueName; | ||
|
||
impl Drop for SomeUniqueName { | ||
fn drop(&mut self) { | ||
} | ||
} | ||
|
||
pub fn possibly_unwinding() { | ||
} | ||
|
||
// CHECK-LABEL: @droppy | ||
#[no_mangle] | ||
pub fn droppy() { | ||
// Check that there are exactly 6 drop calls. The cleanups for the unwinding should be reused, so | ||
// that's one new drop call per call to possibly_unwinding(), and finally 3 drop calls for the | ||
// regular function exit. We used to have problems with quadratic growths of drop calls in such | ||
// functions. | ||
// CHECK: call{{.*}}SomeUniqueName{{.*}}drop | ||
// CHECK: call{{.*}}SomeUniqueName{{.*}}drop | ||
// CHECK: call{{.*}}SomeUniqueName{{.*}}drop | ||
// CHECK: call{{.*}}SomeUniqueName{{.*}}drop | ||
// CHECK: call{{.*}}SomeUniqueName{{.*}}drop | ||
// CHECK: call{{.*}}SomeUniqueName{{.*}}drop | ||
// CHECK-NOT: call{{.*}}SomeUniqueName{{.*}}drop | ||
// The next line checks for the } that ends the function definition | ||
// CHECK-LABEL: {{^[}]}} | ||
let _s = SomeUniqueName; | ||
possibly_unwinding(); | ||
let _s = SomeUniqueName; | ||
possibly_unwinding(); | ||
let _s = SomeUniqueName; | ||
possibly_unwinding(); | ||
} |