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

Analyse storage liveness and preserve it during generator transformation #44480

Merged
merged 4 commits into from
Sep 14, 2017

Conversation

Zoxc
Copy link
Contributor

@Zoxc Zoxc commented Sep 10, 2017

This uses a dataflow analysis on StorageLive and StorageDead statements to infer where the storage of locals are live. The result of this analysis is intersected with the regular liveness analysis such that a local is can only be live when its storage is. This fixes #44184. If the storage of a local is live across a suspension point, we'll insert a StorageLive statement for it after the suspension point so storage liveness is preserved. This fixes #44179.

r? @arielb1


for i in 0..(self.mir_local_count) {
let l = Local::new(i);
if liveness.contains(&l) && !self.remap.contains_key(&l) {
Copy link
Contributor

Choose a reason for hiding this comment

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

A function return automatically does a StorageDead of all locals, so there is no need to insert anything here.


let mut ignored = StorageIgnored(IdxSetBuf::new_filled(mir.basic_blocks().len()));
ignored.visit_mir(mir);

let mut set = liveness::LocalSet::new_empty(mir.local_decls.len());
let result = liveness::liveness_of_locals(mir);
Copy link
Contributor

@arielb1 arielb1 Sep 11, 2017

Choose a reason for hiding this comment

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

nit: I would rename this to liveness

let mut storage_liveness = state_for_location(loc, &analysis, &storage_live);

storage_liveness_map.insert(block, storage_liveness.clone());

Copy link
Contributor

@arielb1 arielb1 Sep 11, 2017

Choose a reason for hiding this comment

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

... and also have a let live_locals = storage_liveness; here. It's free to use better names.

}).collect();

cases.insert(0, (0, drop_clean));

// The poisoned state 1 falls through to the default case which is just to return
// The returned state 1 and the poisoned state 2 falls through to
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: double space the poisoned state

}).collect();

cases.insert(0, (0, drop_clean));

// The poisoned state 1 falls through to the default case which is just to return
// The returned state 1 and the poisoned state 2 falls through to
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: double space the poisoned state

@arielb1
Copy link
Contributor

arielb1 commented Sep 11, 2017

Nice! r=me modulo nits.

state: u32,
resume: BasicBlock,
drop: Option<BasicBlock>,
storage_liveness: liveness::LocalSet,
Copy link
Contributor

@arielb1 arielb1 Sep 11, 2017

Choose a reason for hiding this comment

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

I find this rather ugly. Can you have a

fn make_storage_live(..., point: &SuspensionPoint, terminates_to: BasicBlock) {
}

And call it from both collects to avoid the ugly mutation? I think you can.

@@ -781,6 +814,30 @@ impl MirPass for StateTransform {

dump_mir(tcx, None, "generator_post-transform", &0, source, mir);

// Create StorageLive instruction blocks for suspension points
for point in &mut transform.suspension_points {
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 the part that could be extracted to a function)

@carols10cents carols10cents added the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label Sep 11, 2017
@arielb1
Copy link
Contributor

arielb1 commented Sep 11, 2017

@bors r+

@bors
Copy link
Contributor

bors commented Sep 11, 2017

📌 Commit 23d3d9f has been approved by arielb1

@arielb1
Copy link
Contributor

arielb1 commented Sep 11, 2017

I think it's possible to merge the 3 special case states into SuspensionPoint and clean up quite a bit of code, but I can leave that to a further PR.

@bors
Copy link
Contributor

bors commented Sep 12, 2017

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

@arielb1
Copy link
Contributor

arielb1 commented Sep 12, 2017

@bors r+

@bors
Copy link
Contributor

bors commented Sep 12, 2017

📌 Commit b6bbd4f has been approved by arielb1

@bors
Copy link
Contributor

bors commented Sep 13, 2017

⌛ Testing commit b6bbd4f0929d8308c340fe0c71dbf1dfbc9ff226 with merge 81fa6e7db64256e6d7049627669ff64e99176959...

@bors
Copy link
Contributor

bors commented Sep 13, 2017

💔 Test failed - status-travis

@kennytm
Copy link
Member

kennytm commented Sep 13, 2017

i686-gnu-nopt failed, an error index failed, legit.

I think you need to build the error index yourself to find out what is happening at line 11731 😓

[01:34:13] failures:
[01:34:13] 
[01:34:13] ---- /checkout/obj/build/i686-unknown-linux-gnu/test/error-index.md - Rust_Compiler_Error_Index (line 11731) stdout ----
[01:34:13] 	thread 'rustc' panicked at 'assertion failed: `(left == right)`
[01:34:13]   left: `2`,
[01:34:13]  right: `1`', /checkout/src/librustc_data_structures/bitslice.rs:119:4
[01:34:13] thread 'rustc' panicked at 'couldn't compile the test', /checkout/src/librustdoc/test.rs:280:12
[01:34:13] 
[01:34:13] 
[01:34:13] failures:
[01:34:13]     /checkout/obj/build/i686-unknown-linux-gnu/test/error-index.md - Rust_Compiler_Error_Index (line 11731)
[01:34:13] 
[01:34:13] test result: FAILED. 660 passed; 1 failed; 18 ignored; 0 measured; 0 filtered out

@arielb1
Copy link
Contributor

arielb1 commented Sep 14, 2017

@bors r+

@bors
Copy link
Contributor

bors commented Sep 14, 2017

📌 Commit 0e8e659 has been approved by arielb1

@bors
Copy link
Contributor

bors commented Sep 14, 2017

⌛ Testing commit 0e8e659 with merge 5dfc84c...

bors added a commit that referenced this pull request Sep 14, 2017
Analyse storage liveness and preserve it during generator transformation

This uses a dataflow analysis on `StorageLive` and `StorageDead` statements to infer where the storage of locals are live. The result of this analysis is intersected with the regular liveness analysis such that a local is can only be live when its storage is. This fixes #44184. If the storage of a local is live across a suspension point, we'll insert a `StorageLive` statement for it after the suspension point so storage liveness is preserved. This fixes #44179.

r? @arielb1
@bors
Copy link
Contributor

bors commented Sep 14, 2017

☀️ Test successful - status-appveyor, status-travis
Approved by: arielb1
Pushing 5dfc84c to master...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author.
Projects
None yet
5 participants