rust/tests/mir-opt/inline/indirect_destination.rs
Tomasz Miąsko 1be1c2ebcf Fix insertion of statements to be executed along return edge in inlining
Inlining creates additional statements to be executed along the return
edge: an assignment to the destination, storage end for temporaries.

Previously those statements where inserted directly into a call target,
but this is incorrect when the target has other predecessors.

Avoid the issue by creating a new dedicated block for those statements.
When the block happens to be redundant it will be removed by CFG
simplification that follows inlining.

Fixes #117355
2023-11-20 09:27:30 +01:00

43 lines
956 B
Rust

// Test for inlining with an indirect destination place.
//
// unit-test: Inline
// edition: 2021
// needs-unwind
#![crate_type = "lib"]
#![feature(custom_mir, core_intrinsics)]
use core::intrinsics::mir::*;
#[custom_mir(dialect = "runtime", phase = "initial")]
// CHECK-LABEL: fn f(
// CHECK: bb1: {
// CHECK-NEXT: StorageLive([[A:.*]]);
// CHECK-NEXT: [[A]] = &mut (*_1);
// CHECK-NEXT: StorageLive([[B:.*]]);
// CHECK-NEXT: [[B]] = const 42_u8;
// CHECK-NEXT: (*[[A]]) = move [[B]];
// CHECK-NEXT: StorageDead([[B]]);
// CHECK-NEXT: StorageDead([[A]]);
// CHECK-NEXT: goto -> bb1;
// CHECK-NEXT: }
pub fn f(a: *mut u8) {
mir! {
{
Goto(bb1)
}
bb1 = {
Call(*a = g(), bb1, UnwindUnreachable())
}
}
}
#[custom_mir(dialect = "runtime", phase = "initial")]
#[inline(always)]
fn g() -> u8 {
mir! {
{
RET = 42;
Return()
}
}
}