Skip to content

Prevent pops from sinking in SimplifyLocals #2885

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

Merged
merged 9 commits into from
Jun 3, 2020

Conversation

aheejin
Copy link
Member

@aheejin aheejin commented Jun 1, 2020

This prevents exnref.pops from being sinked and separated from
catch. For example,

(try
  (do)
  (catch
    (local.set $0 (exnref.pop))
    (call $foo
      (i32.const 3)
      (local.get $0)
    )
  )
)

Here, if we sink exnref.pop to remove local.set $0 and
local.get $0, it becomes this:

(try
  (do)
  (catch
    (nop)
    (call $foo
      (i32.const 3)
      (exnref.pop)
    )
  )
)

This move was possible because i32.const 3 does not have any side
effects. But this is incorrect because now exnref.pop does not follow
right after catch.

To prevent this, this patch checks this case in canSink in
SimplifyLocals. When we encountered a similar case in CodeFolding, we
prevented every expression that contains Pop anywhere in it from being
moved, which was too conservative. This adds danglingPop property in
EffectAnalyzer, so that only pops that are not enclosed within a
catch count as 'dangling pops` and we only prevent those pops from
being moved or sinked.

This prevents `exnref.pop`s from being sinked and separated from
`catch`. For example,
```wast
(try
  (do)
  (catch
    (local.set $0 (exnref.pop))
    (call $foo
      (i32.const 3)
      (local.get $0)
    )
  )
)
```
Here, if we sink `exnref.pop` to remove `local.set $0` and
`local.get $0`, it becomes this:
```wast
(try
  (do)
  (catch
    (nop)
    (call $foo
      (i32.const 3)
      (exnref.pop)
    )
  )
)
```
This move was possible because `i32.const 3` does not have any side
effects. But this is incorrect because now `exnref.pop` does not follow
right after `catch`.

To prevent this, this patch checks this case in `canSink` in
SimplifyLocals. When we encountered a similar case in CodeFolding, we
prevented every expression that contains `Pop` anywhere in it from being
moved, which was too conservative. This adds `danglingPop` property in
`EffectAnalyzer`, so that only pops that are not enclosed within a
`catch` count as 'dangling pops` and we only prevent those pops from
being moved or sinked.
@aheejin aheejin requested a review from kripken June 1, 2020 04:10
Copy link
Member

@kripken kripken left a comment

Choose a reason for hiding this comment

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

lgtm with that last comment

@@ -411,6 +411,13 @@ struct SimplifyLocals
if (set->isTee()) {
return false;
}
// We cannot move expressions containing exnref.pops that are not enclosed
// in 'catch', because 'exnref.pop' should follow right after 'catch'.
if (EffectAnalyzer(
Copy link
Member

Choose a reason for hiding this comment

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

how about checking for the exceptions feature here, to avoid computing all side effects when it is disabled?

Copy link
Member Author

Choose a reason for hiding this comment

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

Done

@aheejin aheejin merged commit 501b0a0 into WebAssembly:master Jun 3, 2020
@aheejin aheejin deleted the fix_pop_simplify_locals branch June 3, 2020 07:12
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.

2 participants