Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MIR building for match $c { true => $i, _ => $e } is slow #60571

Closed
Tracked by #53667
Centril opened this issue May 6, 2019 · 5 comments
Closed
Tracked by #53667

MIR building for match $c { true => $i, _ => $e } is slow #60571

Centril opened this issue May 6, 2019 · 5 comments
Labels
A-mir Area: Mid-level IR (MIR) - https://blog.rust-lang.org/2016/04/19/MIR.html C-enhancement Category: An issue proposing an enhancement or a PR with one. F-let_chains `#![feature(let_chains)]` I-compiletime Issue: Problems and improvements with respect to compile times. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@Centril
Copy link
Contributor

Centril commented May 6, 2019

At the time of writing, if $c { $i } else { $e } builds MIR that is simpler and therefore is ~1-3% better in terms of compile times than match $c { $i } else { $e }. However, after the early-opt MIR optimization, they are basically the same.

In #59288 we start desugaring if expressions to match and so if we optimize for the special case of two match arms we can potentially improve compiles times.

cc @oli-obk

@Centril Centril added I-compiletime Issue: Problems and improvements with respect to compile times. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. A-mir Area: Mid-level IR (MIR) - https://blog.rust-lang.org/2016/04/19/MIR.html labels May 6, 2019
@jonas-schievink jonas-schievink added the C-enhancement Category: An issue proposing an enhancement or a PR with one. label May 6, 2019
@estebank
Copy link
Contributor

CC #7462

bors added a commit that referenced this issue May 11, 2019
Optimize matches

Attempt to fix or improve #60571

This is breaking some diagnostics because the MIR for match arms isn't in source order any more.

cc @Centril
bors added a commit that referenced this issue May 26, 2019
Optimize matches

Attempt to fix or improve #60571

This is breaking some diagnostics because the MIR for match arms isn't in source order any more.

cc @Centril
bors added a commit that referenced this issue Jun 16, 2019
Optimize matches

Attempt to fix or improve #60571

This is breaking some diagnostics because the MIR for match arms isn't in source order any more.

cc @Centril
@Centril Centril added the F-let_chains `#![feature(let_chains)]` label Oct 10, 2019
@danii
Copy link
Contributor

danii commented Jul 9, 2021

May I volunteer in fixing? And can anyone help in pointing to the main file where match MIR is generated?

@oli-obk
Copy link
Contributor

oli-obk commented Jul 10, 2021

hir::ExprKind::If(cond, then, else_opt) => ExprKind::If {
cond: self.mirror_expr(cond),
then: self.mirror_expr(then),
else_opt: else_opt.map(|el| self.mirror_expr(el)),
},
hir::ExprKind::Match(ref discr, ref arms, _) => ExprKind::Match {
scrutinee: self.mirror_expr(discr),
arms: arms.iter().map(|a| self.convert_arm(a)).collect(),
},
is the entry point for if and match. we could check whether the discr is of bool type and whether both match arms are plain bool literals without a guard.

@c410-f3r
Copy link
Contributor

let chains are now de-sugared into ifs instead of matchs

@Mark-Simulacrum
Copy link
Member

It looks like today the match-generated MIR is basically the same "complexity" at least based on a visual inspection, so I'm going to go ahead and close this -- we can circle back if there's concrete results today that show otherwise.

For

pub fn foo_if(foo: bool) -> u32 {
    if foo {
        1
    } else {
        2
    }
}

pub fn foo_match(foo: bool) -> u32 {
    match foo {
        true => 1,
        false => 2,
    }
}

we get:

$ rustc +nightly t.rs '-Zdump-mir=foo_if|foo_match' --crate-type=lib
$ cat mir_dump/t.foo_if.000-000.SimplifyCfg-initial.before.mir
// MIR for `foo_if` before SimplifyCfg-initial

fn foo_if(_1: bool) -> u32 {
    debug foo => _1;                     // in scope 0 at t.rs:1:15: 1:18
    let mut _0: u32;                     // return place in scope 0 at t.rs:1:29: 1:32
    let mut _2: bool;                    // in scope 0 at t.rs:2:8: 2:11

    bb0: {
        StorageLive(_2);                 // scope 0 at t.rs:2:8: 2:11
        _2 = _1;                         // scope 0 at t.rs:2:8: 2:11
        switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at t.rs:2:8: 2:11
    }

    bb1: {
        _0 = const 1_u32;                // scope 0 at t.rs:3:9: 3:10
        goto -> bb4;                     // scope 0 at t.rs:2:5: 6:6
    }

    bb2: {
        goto -> bb3;                     // scope 0 at t.rs:2:8: 2:11
    }

    bb3: {
        _0 = const 2_u32;                // scope 0 at t.rs:5:9: 5:10
        goto -> bb4;                     // scope 0 at t.rs:2:5: 6:6
    }

    bb4: {
        StorageDead(_2);                 // scope 0 at t.rs:6:5: 6:6
        return;                          // scope 0 at t.rs:7:2: 7:2
    }
}
$ cat mir_dump/t.foo_match.000-000.SimplifyCfg-initial.before.mir
// MIR for `foo_match` before SimplifyCfg-initial

fn foo_match(_1: bool) -> u32 {
    debug foo => _1;                     // in scope 0 at t.rs:9:18: 9:21
    let mut _0: u32;                     // return place in scope 0 at t.rs:9:32: 9:35

    bb0: {
        FakeRead(ForMatchedPlace(None), _1); // scope 0 at t.rs:10:11: 10:14
        switchInt(_1) -> [false: bb2, otherwise: bb1]; // scope 0 at t.rs:10:5: 10:14
    }

    bb1: {
        falseEdge -> [real: bb3, imaginary: bb2]; // scope 0 at t.rs:11:9: 11:13
    }

    bb2: {
        _0 = const 2_u32;                // scope 0 at t.rs:12:18: 12:19
        goto -> bb4;                     // scope 0 at t.rs:12:18: 12:19
    }

    bb3: {
        _0 = const 1_u32;                // scope 0 at t.rs:11:17: 11:18
        goto -> bb4;                     // scope 0 at t.rs:11:17: 11:18
    }

    bb4: {
        return;                          // scope 0 at t.rs:14:2: 14:2
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-mir Area: Mid-level IR (MIR) - https://blog.rust-lang.org/2016/04/19/MIR.html C-enhancement Category: An issue proposing an enhancement or a PR with one. F-let_chains `#![feature(let_chains)]` I-compiletime Issue: Problems and improvements with respect to compile times. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

7 participants