Skip to content

Commit

Permalink
Auto merge of rust-lang#106850 - cjgillot:issue-106141, r=oli-obk
Browse files Browse the repository at this point in the history
Make the inlining destination a Local.

Fixes rust-lang#106141
  • Loading branch information
bors committed Jan 16, 2023
2 parents a5bfc25 + 389d52c commit af669c2
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 31 deletions.
52 changes: 28 additions & 24 deletions compiler/rustc_mir_transform/src/inline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,21 @@ impl<'tcx> Inliner<'tcx> {
destination
};

// Always create a local to hold the destination, as `RETURN_PLACE` may appear
// where a full `Place` is not allowed.
let (remap_destination, destination_local) = if let Some(d) = dest.as_local() {
(false, d)
} else {
(
true,
self.new_call_temp(
caller_body,
&callsite,
destination.ty(caller_body, self.tcx).ty,
),
)
};

// Copy the arguments if needed.
let args: Vec<_> = self.make_call_args(args, &callsite, caller_body, &callee_body);

Expand All @@ -560,7 +575,7 @@ impl<'tcx> Inliner<'tcx> {
new_locals: Local::new(caller_body.local_decls.len())..,
new_scopes: SourceScope::new(caller_body.source_scopes.len())..,
new_blocks: BasicBlock::new(caller_body.basic_blocks.len())..,
destination: dest,
destination: destination_local,
callsite_scope: caller_body.source_scopes[callsite.source_info.scope].clone(),
callsite,
cleanup_block: cleanup,
Expand Down Expand Up @@ -591,6 +606,16 @@ impl<'tcx> Inliner<'tcx> {
// To avoid repeated O(n) insert, push any new statements to the end and rotate
// the slice once.
let mut n = 0;
if remap_destination {
caller_body[block].statements.push(Statement {
source_info: callsite.source_info,
kind: StatementKind::Assign(Box::new((
dest,
Rvalue::Use(Operand::Move(destination_local.into())),
))),
});
n += 1;
}
for local in callee_body.vars_and_temps_iter().rev() {
if !callee_body.local_decls[local].internal
&& integrator.always_live_locals.contains(local)
Expand Down Expand Up @@ -959,7 +984,7 @@ struct Integrator<'a, 'tcx> {
new_locals: RangeFrom<Local>,
new_scopes: RangeFrom<SourceScope>,
new_blocks: RangeFrom<BasicBlock>,
destination: Place<'tcx>,
destination: Local,
callsite_scope: SourceScopeData<'tcx>,
callsite: &'a CallSite<'tcx>,
cleanup_block: Option<BasicBlock>,
Expand All @@ -972,7 +997,7 @@ struct Integrator<'a, 'tcx> {
impl Integrator<'_, '_> {
fn map_local(&self, local: Local) -> Local {
let new = if local == RETURN_PLACE {
self.destination.local
self.destination
} else {
let idx = local.index() - 1;
if idx < self.args.len() {
Expand Down Expand Up @@ -1053,27 +1078,6 @@ impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> {
*span = span.fresh_expansion(self.expn_data);
}

fn visit_place(&mut self, place: &mut Place<'tcx>, context: PlaceContext, location: Location) {
for elem in place.projection {
// FIXME: Make sure that return place is not used in an indexing projection, since it
// won't be rebased as it is supposed to be.
assert_ne!(ProjectionElem::Index(RETURN_PLACE), elem);
}

// If this is the `RETURN_PLACE`, we need to rebase any projections onto it.
let dest_proj_len = self.destination.projection.len();
if place.local == RETURN_PLACE && dest_proj_len > 0 {
let mut projs = Vec::with_capacity(dest_proj_len + place.projection.len());
projs.extend(self.destination.projection);
projs.extend(place.projection);

place.projection = self.tcx.intern_place_elems(&*projs);
}
// Handles integrating any locals that occur in the base
// or projections
self.super_place(place, context, location)
}

fn visit_basic_block_data(&mut self, block: BasicBlock, data: &mut BasicBlockData<'tcx>) {
self.in_cleanup_block = data.is_cleanup;
self.super_basic_block_data(block, data);
Expand Down
18 changes: 11 additions & 7 deletions tests/mir-opt/inline/inline_into_box_place.main.Inline.diff
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@
let mut _6: (); // in scope 0 at $DIR/inline_into_box_place.rs:+1:42: +1:43
let mut _7: *const std::vec::Vec<u32>; // in scope 0 at $DIR/inline_into_box_place.rs:+1:29: +1:43
+ let mut _8: &mut std::vec::Vec<u32>; // in scope 0 at $DIR/inline_into_box_place.rs:+1:33: +1:43
+ let mut _9: std::vec::Vec<u32>; // in scope 0 at $DIR/inline_into_box_place.rs:+1:33: +1:43
scope 1 {
debug _x => _1; // in scope 1 at $DIR/inline_into_box_place.rs:+1:9: +1:11
}
scope 2 {
}
+ scope 3 (inlined Vec::<u32>::new) { // at $DIR/inline_into_box_place.rs:8:33: 8:43
+ let mut _9: alloc::raw_vec::RawVec<u32>; // in scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
+ let mut _10: alloc::raw_vec::RawVec<u32>; // in scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
+ }

bb0: {
Expand All @@ -37,8 +38,9 @@
- (*_7) = Vec::<u32>::new() -> [return: bb2, unwind: bb5]; // scope 0 at $DIR/inline_into_box_place.rs:+1:33: +1:43
+ StorageLive(_8); // scope 0 at $DIR/inline_into_box_place.rs:+1:33: +1:43
+ _8 = &mut (*_7); // scope 0 at $DIR/inline_into_box_place.rs:+1:33: +1:43
+ StorageLive(_9); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
+ _9 = const _; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
+ StorageLive(_9); // scope 0 at $DIR/inline_into_box_place.rs:+1:33: +1:43
+ StorageLive(_10); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
+ _10 = const _; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
// mir::Constant
- // + span: $DIR/inline_into_box_place.rs:8:33: 8:41
- // + user_ty: UserType(1)
Expand All @@ -49,10 +51,12 @@
+ // + span: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
+ // + user_ty: UserType(0)
+ // + literal: Const { ty: alloc::raw_vec::RawVec<u32>, val: Unevaluated(alloc::raw_vec::RawVec::<T>::NEW, [u32], None) }
+ Deinit((*_8)); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
+ ((*_8).0: alloc::raw_vec::RawVec<u32>) = move _9; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
+ ((*_8).1: usize) = const 0_usize; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
+ StorageDead(_9); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
+ Deinit(_9); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
+ (_9.0: alloc::raw_vec::RawVec<u32>) = move _10; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
+ (_9.1: usize) = const 0_usize; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
+ StorageDead(_10); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
+ (*_8) = move _9; // scope 0 at $DIR/inline_into_box_place.rs:+1:33: +1:43
+ StorageDead(_9); // scope 0 at $DIR/inline_into_box_place.rs:+1:33: +1:43
+ StorageDead(_8); // scope 0 at $DIR/inline_into_box_place.rs:+1:33: +1:43
_1 = move _5; // scope 0 at $DIR/inline_into_box_place.rs:+1:29: +1:43
StorageDead(_5); // scope 0 at $DIR/inline_into_box_place.rs:+1:42: +1:43
Expand Down
55 changes: 55 additions & 0 deletions tests/mir-opt/inline/issue_106141.outer.Inline.diff
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
- // MIR for `outer` before Inline
+ // MIR for `outer` after Inline

fn outer() -> usize {
let mut _0: usize; // return place in scope 0 at $DIR/issue_106141.rs:+0:19: +0:24
+ scope 1 (inlined inner) { // at $DIR/issue_106141.rs:2:5: 2:12
+ let mut _1: bool; // in scope 1 at $DIR/issue_106141.rs:13:8: 13:21
+ let mut _2: bool; // in scope 1 at $DIR/issue_106141.rs:13:8: 13:21
+ let mut _3: &[bool; 1]; // in scope 1 at $DIR/issue_106141.rs:11:18: 11:25
+ scope 2 {
+ debug buffer => _3; // in scope 2 at $DIR/issue_106141.rs:11:9: 11:15
+ scope 3 {
+ debug index => _0; // in scope 3 at $DIR/issue_106141.rs:12:9: 12:14
+ }
+ }
+ }

bb0: {
- _0 = inner() -> bb1; // scope 0 at $DIR/issue_106141.rs:+1:5: +1:12
+ StorageLive(_3); // scope 0 at $DIR/issue_106141.rs:+1:5: +1:12
+ _3 = const _; // scope 1 at $DIR/issue_106141.rs:11:18: 11:25
// mir::Constant
- // + span: $DIR/issue_106141.rs:2:5: 2:10
- // + literal: Const { ty: fn() -> usize {inner}, val: Value(<ZST>) }
+ // + span: $DIR/issue_106141.rs:11:18: 11:25
+ // + literal: Const { ty: &[bool; 1], val: Unevaluated(inner, [], Some(promoted[0])) }
+ _0 = index() -> bb1; // scope 2 at $DIR/issue_106141.rs:12:17: 12:24
+ // mir::Constant
+ // + span: $DIR/issue_106141.rs:12:17: 12:22
+ // + literal: Const { ty: fn() -> usize {index}, val: Value(<ZST>) }
}

bb1: {
+ StorageLive(_1); // scope 3 at $DIR/issue_106141.rs:13:8: 13:21
+ _2 = Lt(_0, const 1_usize); // scope 3 at $DIR/issue_106141.rs:13:8: 13:21
+ assert(move _2, "index out of bounds: the length is {} but the index is {}", const 1_usize, _0) -> bb2; // scope 3 at $DIR/issue_106141.rs:13:8: 13:21
+ }
+
+ bb2: {
+ _1 = (*_3)[_0]; // scope 3 at $DIR/issue_106141.rs:13:8: 13:21
+ switchInt(move _1) -> [0: bb3, otherwise: bb4]; // scope 3 at $DIR/issue_106141.rs:13:8: 13:21
+ }
+
+ bb3: {
+ _0 = const 0_usize; // scope 3 at $DIR/issue_106141.rs:16:9: 16:10
+ goto -> bb4; // scope 3 at $DIR/issue_106141.rs:13:5: 17:6
+ }
+
+ bb4: {
+ StorageDead(_1); // scope 3 at $DIR/issue_106141.rs:17:5: 17:6
+ StorageDead(_3); // scope 0 at $DIR/issue_106141.rs:+1:5: +1:12
return; // scope 0 at $DIR/issue_106141.rs:+2:2: +2:2
}
}

24 changes: 24 additions & 0 deletions tests/mir-opt/inline/issue_106141.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
pub fn outer() -> usize {
inner()
}

fn index() -> usize {
loop {}
}

#[inline]
fn inner() -> usize {
let buffer = &[true];
let index = index();
if buffer[index] {
index
} else {
0
}
}

fn main() {
outer();
}

// EMIT_MIR issue_106141.outer.Inline.diff

0 comments on commit af669c2

Please sign in to comment.