Introduce MIR optimizations for simplifying x? on Results.

This optimization depends on inlining for the identity
conversions introduced by the lowering of the `?`.
To take advantage of `SimplifyArmIdentity`, `-Z mir-opt-level=2`
is required because that triggers the inlining MIR optimization.
This commit is contained in:
Mazdak Farrokhzad 2019-11-10 10:26:33 +01:00
parent 35ef33a89d
commit 2f00e86cb5
11 changed files with 432 additions and 12 deletions

View file

@ -9,19 +9,21 @@ pub enum E {
// CHECK-LABEL: @exhaustive_match
#[no_mangle]
pub fn exhaustive_match(e: E, unit: ()) {
pub fn exhaustive_match(e: E) -> u8 {
// CHECK: switch{{.*}}, label %[[OTHERWISE:[a-zA-Z0-9_]+]] [
// CHECK-NEXT: i[[TY:[0-9]+]] [[DISCR:[0-9]+]], label %[[A:[a-zA-Z0-9_]+]]
// CHECK-NEXT: i[[TY:[0-9]+]] [[DISCR:[0-9]+]], label %[[B:[a-zA-Z0-9_]+]]
// CHECK-NEXT: ]
// CHECK: [[B]]:
// CHECK-NEXT: store i8 1, i8* %1, align 1
// CHECK-NEXT: br label %[[EXIT:[a-zA-Z0-9_]+]]
// CHECK: [[OTHERWISE]]:
// CHECK-NEXT: unreachable
// CHECK: [[A]]:
// CHECK-NEXT: store i8 0, i8* %1, align 1
// CHECK-NEXT: br label %[[EXIT:[a-zA-Z0-9_]+]]
match e {
E::A => unit,
E::B => unit,
E::A => 0,
E::B => 1,
}
}

View file

@ -0,0 +1,17 @@
// compile-flags: -C no-prepopulate-passes -Z mir-opt-level=2
// Ensure that `x?` has no overhead on `Result<T, E>` due to identity `match`es in lowering.
// This requires inlining to trigger the MIR optimizations in `SimplifyArmIdentity`.
#![crate_type = "lib"]
type R = Result<u64, i32>;
#[no_mangle]
fn try_identity(x: R) -> R {
// CHECK: start:
// CHECK-NOT: br {{.*}}
// CHECK ret void
let y = x?;
Ok(y)
}

View file

@ -0,0 +1,193 @@
fn try_identity(x: Result<u32, i32>) -> Result<u32, i32> {
let y = x?;
Ok(y)
}
fn main() {
let _ = try_identity(Ok(0));
}
// END RUST SOURCE
// START rustc.try_identity.SimplifyArmIdentity.before.mir
// fn try_identity(_1: std::result::Result<u32, i32>) -> std::result::Result<u32, i32> {
// let mut _0: std::result::Result<u32, i32>;
// let _2: u32;
// let mut _3: std::result::Result<u32, i32>;
// let mut _4: std::result::Result<u32, i32>;
// let mut _5: isize;
// let _6: i32;
// let mut _7: !;
// let mut _8: i32;
// let mut _9: i32;
// let _10: u32;
// let mut _11: u32;
// scope 1 {
// }
// scope 2 {
// scope 3 {
// scope 7 {
// }
// scope 8 {
// let mut _12: i32;
// }
// }
// }
// scope 4 {
// scope 5 {
// }
// }
// scope 6 {
// }
// bb0: {
// _5 = discriminant(_1);
// switchInt(move _5) -> [0isize: bb4, 1isize: bb2, otherwise: bb1];
// }
// bb1: {
// unreachable;
// }
// bb2: {
// _6 = ((_1 as Err).0: i32);
// ((_0 as Err).0: i32) = move _6;
// discriminant(_0) = 1;
// goto -> bb3;
// }
// bb3: {
// return;
// }
// bb4: {
// _10 = ((_1 as Ok).0: u32);
// ((_0 as Ok).0: u32) = move _10;
// discriminant(_0) = 0;
// goto -> bb3;
// }
// }
// END rustc.try_identity.SimplifyArmIdentity.before.mir
// START rustc.try_identity.SimplifyArmIdentity.after.mir
// fn try_identity(_1: std::result::Result<u32, i32>) -> std::result::Result<u32, i32> {
// let mut _0: std::result::Result<u32, i32>;
// let _2: u32;
// let mut _3: std::result::Result<u32, i32>;
// let mut _4: std::result::Result<u32, i32>;
// let mut _5: isize;
// let _6: i32;
// let mut _7: !;
// let mut _8: i32;
// let mut _9: i32;
// let _10: u32;
// let mut _11: u32;
// scope 1 {
// }
// scope 2 {
// scope 3 {
// scope 7 {
// }
// scope 8 {
// let mut _12: i32;
// }
// }
// }
// scope 4 {
// scope 5 {
// }
// }
// scope 6 {
// }
// bb0: {
// _5 = discriminant(_1);
// switchInt(move _5) -> [0isize: bb4, 1isize: bb2, otherwise: bb1];
// }
// bb1: {
// unreachable;
// }
// bb2: {
// _0 = move _1;
// nop;
// nop;
// goto -> bb3;
// }
// bb3: {
// return;
// }
// bb4: {
// _0 = move _1;
// nop;
// nop;
// goto -> bb3;
// }
// }
// END rustc.try_identity.SimplifyArmIdentity.after.mir
// START rustc.try_identity.SimplifyBranchSame.after.mir
// fn try_identity(_1: std::result::Result<u32, i32>) -> std::result::Result<u32, i32> {
// let mut _0: std::result::Result<u32, i32>;
// let _2: u32;
// let mut _3: std::result::Result<u32, i32>;
// let mut _4: std::result::Result<u32, i32>;
// let mut _5: isize;
// let _6: i32;
// let mut _7: !;
// let mut _8: i32;
// let mut _9: i32;
// let _10: u32;
// let mut _11: u32;
// scope 1 {
// }
// scope 2 {
// scope 3 {
// scope 7 {
// }
// scope 8 {
// let mut _12: i32;
// }
// }
// }
// scope 4 {
// scope 5 {
// }
// }
// scope 6 {
// }
// bb0: {
// _5 = discriminant(_1);
// goto -> bb2;
// }
// bb1: {
// return;
// }
// bb2: {
// _0 = move _1;
// nop;
// nop;
// goto -> bb1;
// }
// }
// END rustc.try_identity.SimplifyBranchSame.after.mir
// START rustc.try_identity.SimplifyLocals.after.mir
// fn try_identity(_1: std::result::Result<u32, i32>) -> std::result::Result<u32, i32> {
// let mut _0: std::result::Result<u32, i32>;
// let mut _2: isize;
// scope 1 {
// }
// scope 2 {
// scope 3 {
// scope 7 {
// }
// scope 8 {
// }
// }
// }
// scope 4 {
// scope 5 {
// }
// }
// scope 6 {
// }
// bb0: {
// _2 = discriminant(_1);
// _0 = move _1;
// return;
// }
// }
// END rustc.try_identity.SimplifyLocals.after.mir