mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-24 21:53:56 +00:00
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
|
||||
};
|
||||
|
||||
// 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);
|
||||
|
||||
@ -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,
|
||||
@ -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)
|
||||
@ -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>,
|
||||
@ -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() {
|
||||
@ -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);
|
||||
|
@ -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: {
|
||||
@ -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)
|
||||
@ -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
|
||||
|
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…
Reference in New Issue
Block a user