This is an archive of the discontinued LLVM Phabricator instance.

[WebAssembly] Use entry block only for initializations in EmSjLj
ClosedPublic

Authored by aheejin on Aug 25 2021, 2:24 PM.

Details

Summary

Emscripten SjLj transformation is done in four steps. This will be
mostly the same for the soon-to-be-added Wasm SjLj; the step 1, 3, and 4
will be shared and there will be separate way of doing step 2.

  1. Initialize setjmpTable and setjmpTableSize in the entry BB
  2. Handle setjmp callsites
  3. Handle longjmp callsites
  4. Cleanup and update SSA

We initialize setjmpTable and setjmpTableSize in the entry BB. But
if the entry BB contains a setjmp call, some setjmp handling
transformation will also happen in the entry BB, such as calling
saveSetjmp.

This is fine for Emscripten SjLj but not for Wasm SjLj, because in Wasm
SjLj we will add a dispatch BB that contains a switch right after the
entry BB, from which we jump to one of post-setjmp BBs. And this
dispatch BB should precede all setjmp calls.

Emscripten SjLj (current):

entry:
  %setjmpTable = ...
  %setjmpTableSize = ...
  ...
  call @saveSetjmp(...)

Wasm SjLj (follow-up):

entry:
  %setjmpTable = ...
  %setjmpTableSize = ...

setjmp.dispatch:
  ...
  ; Jump to the right post-setjmp BB, if we are returning from a
  ; longjmp. If this is the first setjmp call, go to %entry.split.
  switch i32 %no, label %entry.split [
    i32 1, label %post.setjmp1
    i32 2, label %post.setjmp2
    ...
    i32 N, label %post.setjmpN
  ]

entry.split:
  ...
  call @saveSetjmp(...)

So in Wasm SjLj we split the entry BB to make the entry block only for
setjmpTable and setjmpTableSize initialization and insert a
setjmp.dispatch BB. (This part is not in this CL. This will be a
follow-up.) But note that Emscripten SjLj and Wasm SjLj share all
steps except for the step 2. If we only split the entry BB only for Wasm
SjLj, there will be one more if-else and the code will be more
complicated.

So this CL splits the entry BB in Emscripten SjLj and put only
initialization stuff there as follows:
Emscripten SjLj (this CL):

entry:
  %setjmpTable = ...
  %setjmpTableSize = ...
  br %entry.split

entry.split:
  ...
  call @saveSetjmp(...)

This is just done to share code with Wasm SjLj. It adds an unnecessary
branch but this will be removed in later optimization passes anyway.

This is in effect NFC, meaning the program behavior will not change, but
existing ll tests files have changed because the entry block was split.
The reason I upload this in a separate CL is to make the Wasm SjLj diff
tidier, because this changes many existing Emscripten SjLj tests, which
can be confusing for the follow-up Wasm SjLj CL.

Diff Detail

Event Timeline

aheejin created this revision.Aug 25 2021, 2:24 PM
aheejin requested review of this revision.Aug 25 2021, 2:24 PM
Herald added a project: Restricted Project. · View Herald TranscriptAug 25 2021, 2:24 PM
tlively accepted this revision.Aug 25 2021, 3:31 PM
tlively added inline comments.
llvm/test/CodeGen/WebAssembly/lower-em-sjlj-alias.ll
19–20

Why remove these entirely rather than check for them in the new output?

This revision is now accepted and ready to land.Aug 25 2021, 3:31 PM
aheejin added inline comments.Aug 25 2021, 3:41 PM
llvm/test/CodeGen/WebAssembly/lower-em-sjlj-alias.ll
19–20

Not sure why I added them in the first place. All this test checks is that malloc is not transformed into an invoke, so I thought adding entry.split: call i32* saveSetjmp, ... would be unnecessary.

This revision was landed with ongoing or failed builds.Aug 25 2021, 3:47 PM
This revision was automatically updated to reflect the committed changes.