Auto merge of #106850 - cjgillot:issue-106141, r=oli-obk
Make the inlining destination a Local. Fixes https://github.com/rust-lang/rust/issues/106141
This commit is contained in:
commit
af669c2684
@ -542,6 +542,21 @@ impl<'tcx> Inliner<'tcx> {
|
|||||||
destination
|
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.
|
// Copy the arguments if needed.
|
||||||
let args: Vec<_> = self.make_call_args(args, &callsite, caller_body, &callee_body);
|
let args: Vec<_> = self.make_call_args(args, &callsite, caller_body, &callee_body);
|
||||||
|
|
||||||
@ -560,7 +575,7 @@ impl<'tcx> Inliner<'tcx> {
|
|||||||
new_locals: Local::new(caller_body.local_decls.len())..,
|
new_locals: Local::new(caller_body.local_decls.len())..,
|
||||||
new_scopes: SourceScope::new(caller_body.source_scopes.len())..,
|
new_scopes: SourceScope::new(caller_body.source_scopes.len())..,
|
||||||
new_blocks: BasicBlock::new(caller_body.basic_blocks.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_scope: caller_body.source_scopes[callsite.source_info.scope].clone(),
|
||||||
callsite,
|
callsite,
|
||||||
cleanup_block: cleanup,
|
cleanup_block: cleanup,
|
||||||
@ -591,6 +606,16 @@ impl<'tcx> Inliner<'tcx> {
|
|||||||
// To avoid repeated O(n) insert, push any new statements to the end and rotate
|
// To avoid repeated O(n) insert, push any new statements to the end and rotate
|
||||||
// the slice once.
|
// the slice once.
|
||||||
let mut n = 0;
|
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() {
|
for local in callee_body.vars_and_temps_iter().rev() {
|
||||||
if !callee_body.local_decls[local].internal
|
if !callee_body.local_decls[local].internal
|
||||||
&& integrator.always_live_locals.contains(local)
|
&& integrator.always_live_locals.contains(local)
|
||||||
@ -959,7 +984,7 @@ struct Integrator<'a, 'tcx> {
|
|||||||
new_locals: RangeFrom<Local>,
|
new_locals: RangeFrom<Local>,
|
||||||
new_scopes: RangeFrom<SourceScope>,
|
new_scopes: RangeFrom<SourceScope>,
|
||||||
new_blocks: RangeFrom<BasicBlock>,
|
new_blocks: RangeFrom<BasicBlock>,
|
||||||
destination: Place<'tcx>,
|
destination: Local,
|
||||||
callsite_scope: SourceScopeData<'tcx>,
|
callsite_scope: SourceScopeData<'tcx>,
|
||||||
callsite: &'a CallSite<'tcx>,
|
callsite: &'a CallSite<'tcx>,
|
||||||
cleanup_block: Option<BasicBlock>,
|
cleanup_block: Option<BasicBlock>,
|
||||||
@ -972,7 +997,7 @@ struct Integrator<'a, 'tcx> {
|
|||||||
impl Integrator<'_, '_> {
|
impl Integrator<'_, '_> {
|
||||||
fn map_local(&self, local: Local) -> Local {
|
fn map_local(&self, local: Local) -> Local {
|
||||||
let new = if local == RETURN_PLACE {
|
let new = if local == RETURN_PLACE {
|
||||||
self.destination.local
|
self.destination
|
||||||
} else {
|
} else {
|
||||||
let idx = local.index() - 1;
|
let idx = local.index() - 1;
|
||||||
if idx < self.args.len() {
|
if idx < self.args.len() {
|
||||||
@ -1053,27 +1078,6 @@ impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> {
|
|||||||
*span = span.fresh_expansion(self.expn_data);
|
*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>) {
|
fn visit_basic_block_data(&mut self, block: BasicBlock, data: &mut BasicBlockData<'tcx>) {
|
||||||
self.in_cleanup_block = data.is_cleanup;
|
self.in_cleanup_block = data.is_cleanup;
|
||||||
self.super_basic_block_data(block, data);
|
self.super_basic_block_data(block, data);
|
||||||
|
@ -11,13 +11,14 @@
|
|||||||
let mut _6: (); // in scope 0 at $DIR/inline_into_box_place.rs:+1:42: +1:43
|
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 _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 _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 {
|
scope 1 {
|
||||||
debug _x => _1; // in scope 1 at $DIR/inline_into_box_place.rs:+1:9: +1:11
|
debug _x => _1; // in scope 1 at $DIR/inline_into_box_place.rs:+1:9: +1:11
|
||||||
}
|
}
|
||||||
scope 2 {
|
scope 2 {
|
||||||
}
|
}
|
||||||
+ scope 3 (inlined Vec::<u32>::new) { // at $DIR/inline_into_box_place.rs:8:33: 8:43
|
+ 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: {
|
bb0: {
|
||||||
@ -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
|
- (*_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
|
+ 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
|
+ _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
|
+ StorageLive(_9); // scope 0 at $DIR/inline_into_box_place.rs:+1:33: +1:43
|
||||||
+ _9 = const _; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
+ 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
|
// mir::Constant
|
||||||
- // + span: $DIR/inline_into_box_place.rs:8:33: 8:41
|
- // + span: $DIR/inline_into_box_place.rs:8:33: 8:41
|
||||||
- // + user_ty: UserType(1)
|
- // + user_ty: UserType(1)
|
||||||
@ -49,10 +51,12 @@
|
|||||||
+ // + span: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
+ // + span: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
||||||
+ // + user_ty: UserType(0)
|
+ // + user_ty: UserType(0)
|
||||||
+ // + literal: Const { ty: alloc::raw_vec::RawVec<u32>, val: Unevaluated(alloc::raw_vec::RawVec::<T>::NEW, [u32], None) }
|
+ // + 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
|
+ Deinit(_9); // 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
|
+ (_9.0: alloc::raw_vec::RawVec<u32>) = move _10; // 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
|
+ (_9.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
|
+ 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
|
+ 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
|
_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
|
StorageDead(_5); // scope 0 at $DIR/inline_into_box_place.rs:+1:42: +1:43
|
||||||
|
55
tests/mir-opt/inline/issue_106141.outer.Inline.diff
Normal file
55
tests/mir-opt/inline/issue_106141.outer.Inline.diff
Normal file
@ -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
tests/mir-opt/inline/issue_106141.rs
Normal file
24
tests/mir-opt/inline/issue_106141.rs
Normal file
@ -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
|
Loading…
x
Reference in New Issue
Block a user