Skip to content

Commit 336dc18

Browse files
authoredNov 17, 2020
Rollup merge of #79027 - tmiasko:inline-always-live-locals, r=oli-obk
Limit storage duration of inlined always live locals Closes #76375.
2 parents f960f28 + f27d56d commit 336dc18

File tree

7 files changed

+73
-5
lines changed

7 files changed

+73
-5
lines changed
 

‎compiler/rustc_middle/src/mir/mod.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,9 @@ impl<'tcx> Body<'tcx> {
420420
/// Returns an iterator over all user-defined variables and compiler-generated temporaries (all
421421
/// locals that are neither arguments nor the return place).
422422
#[inline]
423-
pub fn vars_and_temps_iter(&self) -> impl Iterator<Item = Local> + ExactSizeIterator {
423+
pub fn vars_and_temps_iter(
424+
&self,
425+
) -> impl DoubleEndedIterator<Item = Local> + ExactSizeIterator {
424426
let arg_count = self.arg_count;
425427
let local_count = self.local_decls.len();
426428
(arg_count + 1..local_count).map(Local::new)

‎compiler/rustc_mir/src/transform/inline.rs

+39
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,7 @@ impl Inliner<'tcx> {
459459
tcx: self.tcx,
460460
callsite_span: callsite.source_info.span,
461461
body_span: callee_body.span,
462+
always_live_locals: BitSet::new_filled(callee_body.local_decls.len()),
462463
};
463464

464465
// Map all `Local`s, `SourceScope`s and `BasicBlock`s to new ones
@@ -490,6 +491,34 @@ impl Inliner<'tcx> {
490491
}
491492
}
492493

494+
// If there are any locals without storage markers, give them storage only for the
495+
// duration of the call.
496+
for local in callee_body.vars_and_temps_iter() {
497+
if integrator.always_live_locals.contains(local) {
498+
let new_local = integrator.map_local(local);
499+
caller_body[callsite.block].statements.push(Statement {
500+
source_info: callsite.source_info,
501+
kind: StatementKind::StorageLive(new_local),
502+
});
503+
}
504+
}
505+
if let Some(block) = callsite.target {
506+
// To avoid repeated O(n) insert, push any new statements to the end and rotate
507+
// the slice once.
508+
let mut n = 0;
509+
for local in callee_body.vars_and_temps_iter().rev() {
510+
if integrator.always_live_locals.contains(local) {
511+
let new_local = integrator.map_local(local);
512+
caller_body[block].statements.push(Statement {
513+
source_info: callsite.source_info,
514+
kind: StatementKind::StorageDead(new_local),
515+
});
516+
n += 1;
517+
}
518+
}
519+
caller_body[block].statements.rotate_right(n);
520+
}
521+
493522
// Insert all of the (mapped) parts of the callee body into the caller.
494523
caller_body.local_decls.extend(
495524
// FIXME(eddyb) make `Range<Local>` iterable so that we can use
@@ -670,6 +699,7 @@ struct Integrator<'a, 'tcx> {
670699
tcx: TyCtxt<'tcx>,
671700
callsite_span: Span,
672701
body_span: Span,
702+
always_live_locals: BitSet<Local>,
673703
}
674704

675705
impl<'a, 'tcx> Integrator<'a, 'tcx> {
@@ -759,6 +789,15 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> {
759789
}
760790
}
761791

792+
fn visit_statement(&mut self, statement: &mut Statement<'tcx>, location: Location) {
793+
if let StatementKind::StorageLive(local) | StatementKind::StorageDead(local) =
794+
statement.kind
795+
{
796+
self.always_live_locals.remove(local);
797+
}
798+
self.super_statement(statement, location);
799+
}
800+
762801
fn visit_terminator(&mut self, terminator: &mut Terminator<'tcx>, loc: Location) {
763802
// Don't try to modify the implicit `_0` access on return (`return` terminators are
764803
// replaced down below anyways).

‎src/test/mir-opt/inline/inline_diverging.h.Inline.diff

+1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
- // mir::Constant
4141
// + span: $DIR/inline-diverging.rs:22:16: 22:21
4242
// + literal: Const { ty: fn() -> ! {sleep}, val: Value(Scalar(<ZST>)) }
43+
+ StorageLive(_6); // scope 0 at $DIR/inline-diverging.rs:22:5: 22:22
4344
+ StorageLive(_3); // scope 1 at $DIR/inline-diverging.rs:22:5: 22:22
4445
+ StorageLive(_4); // scope 1 at $DIR/inline-diverging.rs:22:5: 22:22
4546
+ _4 = &_2; // scope 1 at $DIR/inline-diverging.rs:22:5: 22:22

‎src/test/mir-opt/inline/inline_generator.main.Inline.diff

+4
Original file line numberDiff line numberDiff line change
@@ -65,12 +65,16 @@
6565
- // + literal: Const { ty: for<'r> fn(std::pin::Pin<&'r mut impl std::ops::Generator<bool>>, bool) -> std::ops::GeneratorState<<impl std::ops::Generator<bool> as std::ops::Generator<bool>>::Yield, <impl std::ops::Generator<bool> as std::ops::Generator<bool>>::Return> {<impl std::ops::Generator<bool> as std::ops::Generator<bool>>::resume}, val: Value(Scalar(<ZST>)) }
6666
+ StorageLive(_7); // scope 0 at $DIR/inline-generator.rs:9:14: 9:46
6767
+ _7 = const false; // scope 0 at $DIR/inline-generator.rs:9:14: 9:46
68+
+ StorageLive(_8); // scope 0 at $DIR/inline-generator.rs:9:14: 9:46
69+
+ StorageLive(_9); // scope 0 at $DIR/inline-generator.rs:9:14: 9:46
6870
+ _9 = discriminant((*(_2.0: &mut [generator@$DIR/inline-generator.rs:15:5: 15:41 {bool, i32}]))); // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
6971
+ switchInt(move _9) -> [0_u32: bb3, 1_u32: bb8, 3_u32: bb7, otherwise: bb9]; // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
7072
}
7173

7274
- bb3: {
7375
+ bb1: {
76+
+ StorageDead(_9); // scope 0 at $DIR/inline-generator.rs:9:14: 9:46
77+
+ StorageDead(_8); // scope 0 at $DIR/inline-generator.rs:9:14: 9:46
7478
+ StorageDead(_7); // scope 0 at $DIR/inline-generator.rs:9:14: 9:46
7579
StorageDead(_2); // scope 0 at $DIR/inline-generator.rs:9:45: 9:46
7680
StorageDead(_4); // scope 0 at $DIR/inline-generator.rs:9:46: 9:47

‎src/test/mir-opt/inline/inline_shims.drop.Inline.diff

+4
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,15 @@
3636
- // mir::Constant
3737
- // + span: $DIR/inline-shims.rs:12:14: 12:37
3838
- // + literal: Const { ty: unsafe fn(*mut std::option::Option<B>) {std::intrinsics::drop_in_place::<std::option::Option<B>>}, val: Value(Scalar(<ZST>)) }
39+
+ StorageLive(_6); // scope 2 at $DIR/inline-shims.rs:12:14: 12:40
40+
+ StorageLive(_7); // scope 2 at $DIR/inline-shims.rs:12:14: 12:40
3941
+ _6 = discriminant((*_5)); // scope 3 at $DIR/inline-shims.rs:12:14: 12:40
4042
+ switchInt(move _6) -> [0_isize: bb2, otherwise: bb3]; // scope 3 at $DIR/inline-shims.rs:12:14: 12:40
4143
}
4244

4345
bb2: {
46+
+ StorageDead(_7); // scope 2 at $DIR/inline-shims.rs:12:14: 12:40
47+
+ StorageDead(_6); // scope 2 at $DIR/inline-shims.rs:12:14: 12:40
4448
StorageDead(_5); // scope 2 at $DIR/inline-shims.rs:12:39: 12:40
4549
return; // scope 0 at $DIR/inline-shims.rs:13:2: 13:2
4650
+ }
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
// edition:2018
2-
// compile-flags: -Z mir-opt-level=2 -Z unsound-mir-opts
2+
// compile-flags: -Z mir-opt-level=2
33

44
#[inline(always)]
5-
pub fn f(s: bool) -> String {
5+
pub fn copy_prop(s: bool) -> String {
66
let a = "Hello world!".to_string();
77
let b = a;
88
let c = b;
@@ -12,3 +12,9 @@ pub fn f(s: bool) -> String {
1212
String::new()
1313
}
1414
}
15+
16+
#[inline(always)]
17+
pub fn dest_prop(x: &[u8]) -> &[u8] {
18+
let y = &x[..x.len()];
19+
y
20+
}

‎src/test/ui/mir/issue-76375.rs

+14-2
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,27 @@
1+
// Regression test for issue #76375.
2+
//
13
// edition:2018
24
// build-pass
3-
// compile-flags: -Z mir-opt-level=2 -L.
5+
// compile-flags: -Z mir-opt-level=2
46
// aux-build:issue_76375_aux.rs
57

68
#![crate_type = "lib"]
79

810
extern crate issue_76375_aux;
911

1012
pub async fn g() {
11-
issue_76375_aux::f(true);
13+
issue_76375_aux::copy_prop(true);
1214
h().await;
1315
}
1416

17+
pub async fn u() {
18+
let b = [0u8; 32];
19+
let mut i = 0;
20+
while i != 10 {
21+
issue_76375_aux::dest_prop(&b);
22+
h().await;
23+
i += 1;
24+
}
25+
}
26+
1527
pub async fn h() {}

0 commit comments

Comments
 (0)
Please sign in to comment.