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

[WIP][MIR] Generic lattice-based DF framework #33628

Closed
wants to merge 3 commits into from

Conversation

nagisa
Copy link
Member

@nagisa nagisa commented May 14, 2016

This PR at its current state has only the implementation of forward dataflow analysis and a accompanying alias-constant-simplify propagation pass.

The lattice-based dataflow framework is greatly inspired by the Hoopl and its paper. The framework besides just being yet another dataflow engine allows for interleaving transformations and analysis + composition of the passes. These are something the gen-kill-set-based dataflow engines aren’t quite suited for. Those features are showcased by the accompanying ACS pass and without them the ACS pass wouldn‘t be otherwise possible (at least not within 200 lines).

Some notes: this is not yet complete: I expect to expand the framework to gain some more useful combinators (or at least those described in the paper) as well as some more other niceties to simplify production of dataflow-reliant passes and backwards analysis capabilities and so on and on.

Some results:

For following pieces of code this MIR (with dead variables removed by yours truly) gets produced:

fn a(x: (bool, bool)) -> u32{
    let z = x.0;
    let v = x.1;
    let y = if z || v {
        10
    } else {
        20
    };
    y
}
fn a(arg0: (bool, bool)) -> u32 {
    let var0: (bool, bool); // x in Scope(1) at test.rs:1:6: 1:7
    let var1: bool; // z in Scope(3) at test.rs:2:9: 2:10
    let var2: bool; // v in Scope(7) at test.rs:3:9: 3:10
    let var3: u32; // y in Scope(11) at test.rs:4:9: 4:10
    let mut tmp0: bool;
    let mut tmp1: bool;
    let mut tmp2: bool;
    let mut tmp3: bool;
    let mut tmp4: bool;
    let mut tmp5: u32;

    bb0: {
        if((arg0.0: bool)) -> [true: bb1, false: bb3]; // Scope(14) at test.rs:4:16: 4:22
    }

    bb1: {
        goto -> bb4; // Scope(14) at test.rs:4:16: 4:22
    }

    bb2: {
        goto -> bb4; // Scope(14) at test.rs:4:16: 4:22
    }

    bb3: {
        if((arg0.1: bool)) -> [true: bb1, false: bb2]; // Scope(14) at test.rs:4:16: 4:22
    }

    bb4: {
        if(tmp2) -> [true: bb5, false: bb6]; // Scope(13) at test.rs:4:13: 8:6
    }

    bb5: {
        var3 = const 10u32; // Scope(19) at test.rs:5:9: 5:11
        goto -> bb7; // Scope(13) at test.rs:4:13: 8:6
    }

    bb6: {
        var3 = const 20u32; // Scope(23) at test.rs:7:9: 7:11
        goto -> bb7; // Scope(13) at test.rs:4:13: 8:6
    }

    bb7: {
        return = var3; // Scope(24) at test.rs:9:5: 9:6
        goto -> bb8; // Scope(0) at test.rs:1:1: 10:2
    }

    bb8: {
        return; // Scope(0) at test.rs:1:1: 10:2
    }
fn a() -> u32{
    let x = false;
    let z = x;
    let y = if z {
        10
    } else {
        10
    };
    y
}
fn a() -> u32 {
    let var0: bool; // x in Scope(3) at test.rs:2:9: 2:10
    let var1: bool; // z in Scope(6) at test.rs:3:9: 3:10
    let var2: u32; // y in Scope(9) at test.rs:4:9: 4:10
    let mut tmp0: bool;
    let mut tmp1: bool;
    let mut tmp2: u32;

    bb0: {
        goto -> bb2; // Scope(11) at test.rs:4:13: 8:6
    }

    bb1: {
        var2 = const 10u32; // Scope(14) at test.rs:5:9: 5:11
        goto -> bb3; // Scope(11) at test.rs:4:13: 8:6
    }

    bb2: {
        goto -> bb3; // Scope(11) at test.rs:4:13: 8:6
    }

    bb3: {
        return = const 10u32; // Scope(19) at test.rs:9:5: 9:6
        goto -> bb4; // Scope(0) at test.rs:1:1: 10:2
    }

    bb4: {
        return; // Scope(0) at test.rs:1:1: 10:2
    }
}

nagisa added 3 commits May 14, 2016 03:25

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
Only a forward one so far
ACS here stands for Alias-Constant-Simplify. This propagation pass is a composition of three
distinct dataflow passes: alias-propagation, constant-propagation and terminator simplification.

This pass also serves to showcase the features of the framework. Most notably the terseness,
composability and the capability to interleave analysis and transformations.
@rust-highfive
Copy link
Collaborator

r? @Aatch

(rust_highfive has picked a reviewer for you, use r? to override)

@bors
Copy link
Contributor

bors commented May 14, 2016

☔ The latest upstream changes (presumably #33632) made this pull request unmergeable. Please resolve the merge conflicts.

StatementChange::None => StatementChange::Statement(ns),
x => x
},
StatementChange::Statements(nss) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that, in the case of multiple statements, just transforming each statement doesn't work - the fact needs to be transferred across each statement. For example, an (admittedly silly) transformation that takes x = y to newtmp = y; x = newtmp should not mess up constant propogation - if y is constant, it should infer that newtmp is the same constant and fill in the value for x.

In Hoopl, this is solved by having rewrite functions be more like lists of rewrite functions - thenFwdRw doesn't actually run one rewrite after another, instead doing the first rewrite and then scheduling the second rewrite to occur next. Thus, the final transfer and rewrite engine is responsible for running rewrites in sequence, and can transfer facts across newly transformed statements.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that, in the case of multiple statements, just transforming each statement doesn't work - the fact needs to be transferred across each statement.

That’s right, I was thinking about how I would approach it and that’s exactly why I didn’t include a way to replace a statement with a (sub-)graph but replacement with a list of statements fell through the cracks.

@nagisa
Copy link
Member Author

nagisa commented May 15, 2016

Note for everybody looking at this: my exam session begins this week and lasts through the 2nd part of june. I’m pretty sure this PR won’t progress at all before the session ends.

All the reviews are appreciated and I’ll look at and try to respond to them in as timely manner as possible.

@pnkfelix
Copy link
Member

Cc me

@nagisa
Copy link
Member Author

nagisa commented May 16, 2016

Note to self: do not forget about nagisa#1

@nikomatsakis
Copy link
Contributor

cc @rust-lang/compiler (I for one didn't see this due to lack of notification :)

@nikomatsakis
Copy link
Contributor

@nagisa good luck on exams :)

@@ -118,12 +83,11 @@ impl<'tcx> MirPass<'tcx> for SimplifyCfg {
while changed {
pretty::dump_mir(tcx, "simplify_cfg", &counter, src, mir, None);
counter += 1;
changed = self.simplify_branches(mir);
changed |= self.remove_goto_chains(mir);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an endless loop now, as changed is never set to false.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes that's why I commented the pass out.
On May 19, 2016 3:39 PM, "Björn Steinbrink" notifications@github.com
wrote:

In src/librustc_mir/transform/simplify_cfg.rs
#33628 (comment):

@@ -118,12 +83,11 @@ impl<'tcx> MirPass<'tcx> for SimplifyCfg {
while changed {
pretty::dump_mir(tcx, "simplify_cfg", &counter, src, mir, None);
counter += 1;

  •        changed = self.simplify_branches(mir);
         changed |= self.remove_goto_chains(mir);
    

This is an endless loop now, as changed is never set to false.


You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub
https://github.com/rust-lang/rust/pull/33628/files/ee4a7c39e84237756fd453356eaec0921356873f#r63869926

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

9 participants