|
Revision tags: llvmorg-20.1.0, llvmorg-20.1.0-rc3, llvmorg-20.1.0-rc2, llvmorg-20.1.0-rc1, llvmorg-21-init, llvmorg-19.1.7, llvmorg-19.1.6, llvmorg-19.1.5, llvmorg-19.1.4, llvmorg-19.1.3, llvmorg-19.1.2, llvmorg-19.1.1, llvmorg-19.1.0, llvmorg-19.1.0-rc4, llvmorg-19.1.0-rc3, llvmorg-19.1.0-rc2, llvmorg-19.1.0-rc1, llvmorg-20-init, llvmorg-18.1.8, llvmorg-18.1.7, llvmorg-18.1.6, llvmorg-18.1.5, llvmorg-18.1.4, llvmorg-18.1.3, llvmorg-18.1.2, llvmorg-18.1.1, llvmorg-18.1.0, llvmorg-18.1.0-rc4, llvmorg-18.1.0-rc3, llvmorg-18.1.0-rc2, llvmorg-18.1.0-rc1, llvmorg-19-init, llvmorg-17.0.6, llvmorg-17.0.5, llvmorg-17.0.4, llvmorg-17.0.3, llvmorg-17.0.2, llvmorg-17.0.1, llvmorg-17.0.0, llvmorg-17.0.0-rc4, llvmorg-17.0.0-rc3, llvmorg-17.0.0-rc2, llvmorg-17.0.0-rc1, llvmorg-18-init, llvmorg-16.0.6, llvmorg-16.0.5, llvmorg-16.0.4, llvmorg-16.0.3, llvmorg-16.0.2, llvmorg-16.0.1, llvmorg-16.0.0, llvmorg-16.0.0-rc4, llvmorg-16.0.0-rc3, llvmorg-16.0.0-rc2, llvmorg-16.0.0-rc1, llvmorg-17-init, llvmorg-15.0.7, llvmorg-15.0.6, llvmorg-15.0.5, llvmorg-15.0.4, llvmorg-15.0.3, llvmorg-15.0.2, llvmorg-15.0.1, llvmorg-15.0.0, llvmorg-15.0.0-rc3, llvmorg-15.0.0-rc2, llvmorg-15.0.0-rc1, llvmorg-16-init, llvmorg-14.0.6, llvmorg-14.0.5 |
|
| #
24e16e4a |
| 27-May-2022 |
Serguei Katkov <[email protected]> |
[SSAUpdaterImpl] Do not generate phi node with all the same incoming values
If all available vals to basic block are the same - do not build new phi node and just use this value.
Reviewed By: samee
[SSAUpdaterImpl] Do not generate phi node with all the same incoming values
If all available vals to basic block are the same - do not build new phi node and just use this value.
Reviewed By: sameerds Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D126525
show more ...
|
|
Revision tags: llvmorg-14.0.4, llvmorg-14.0.3, llvmorg-14.0.2, llvmorg-14.0.1, llvmorg-14.0.0, llvmorg-14.0.0-rc4, llvmorg-14.0.0-rc3, llvmorg-14.0.0-rc2, llvmorg-14.0.0-rc1, llvmorg-15-init |
|
| #
786da406 |
| 26-Jan-2022 |
Heejin Ahn <[email protected]> |
[WebAssembly] Don't copy noreturn attr to invokes
When we create an invoke wrapper call, if the original call instruction has a `noreturn` attribute, we shouldn't copy it, because we expect invoke w
[WebAssembly] Don't copy noreturn attr to invokes
When we create an invoke wrapper call, if the original call instruction has a `noreturn` attribute, we shouldn't copy it, because we expect invoke wrapper calls to return. This generated incorrect `free` call before an invoke wrapper call that calls `__cxa_throw`, because `__cxa_throw` has `noreturn` attribute.
Reviewed By: dschuff
Differential Revision: https://reviews.llvm.org/D118274
show more ...
|
| #
d9517efb |
| 22-Jan-2022 |
Heejin Ahn <[email protected]> |
[WebAssembly] Treat __cxa_end_catch not longjmpable in Emscripten SjLj
In D117610 we treated `__cxa_end_catch` longjmpable even though it was not to make unwind destination relationships correct. Bu
[WebAssembly] Treat __cxa_end_catch not longjmpable in Emscripten SjLj
In D117610 we treated `__cxa_end_catch` longjmpable even though it was not to make unwind destination relationships correct. But we only need to do this in Wasm SjLj, and doing this in Emscripten SjLj does not make the code incorrect but add unnecessary invokes. This CL treats `__cxa_end_catch` longjmpable only in Wasm SjLj.
Reviewed By: dschuff
Differential Revision: https://reviews.llvm.org/D117943
show more ...
|
|
Revision tags: llvmorg-13.0.1, llvmorg-13.0.1-rc3, llvmorg-13.0.1-rc2, llvmorg-13.0.1-rc1, llvmorg-13.0.0, llvmorg-13.0.0-rc4, llvmorg-13.0.0-rc3 |
|
| #
b8fc71b7 |
| 28-Aug-2021 |
Heejin Ahn <[email protected]> |
[WebAssembly] Share rethrowing BBs in LowerEmscriptenEHSjLj
There are three kinds of "rethrowing" BBs in this pass: 1. In Emscripten SjLj, after a possibly longjmping function call, we check if t
[WebAssembly] Share rethrowing BBs in LowerEmscriptenEHSjLj
There are three kinds of "rethrowing" BBs in this pass: 1. In Emscripten SjLj, after a possibly longjmping function call, we check if the thrown longjmp corresponds to one of setjmps within the current function. If not, we rethrow the longjmp by calling `emscripten_longjmp`. 2. In Emscripten EH, after a possibly throwing function call, we check if the thrown exception corresponds to the current `catch` clauses. If not, we rethrow the exception by calling `__resumeException`. 3. When both Emscripten EH and SjLj are used, when we check for an exception after a possibly throwing function call, it is possible that we get not an exception but a longjmp. In this case, we shouldn't swallow it; we should rethrow the longjmp by calling `emscripten_longjmp`. 4. When both Emscripten EH and SjLj are used, when we check for a longjmp after a possibly longjmping function call, it is possible that we get not a longjmp but an exception. In this case, we shouldn't swallot it; we should rethrow the exception by calling `__resumeException`.
Case 1 is in Emscripten SjLj, 2 is in Emscripten EH, and 3 and 4 are relevant when both Emscripten EH and SjLj are used. 3 and 4 were first implemented in D106525.
We create BBs for 1, 3, and 4 in this pass. We create those BBs for every throwing/longjmping function call, along with other BBs that contain condition checks. What this CL does is to create a single BB within a function for each of 1, 3, and 4 cases. These BBs are exiting BBs in the function and thus don't have successors, so easy to be shared between calls.
The names of BBs created are: Case 1: `call.em.longjmp` Case 3: `rethrow.exn` Case 4: `rethrow.longjmp`
For the case 2 we don't currently create BBs; we only replace the existing `resume` instruction with `call @__resumeException`. And Clang already creates only a single `resume` BB per function and reuses it, so we don't need to optimize this case.
Not sure what are good benchmarks for EH/SjLj, but this decreases the size of the object file for `grfmt_jpeg.bc` (presumably from opencv) we got from one of our users by 8.9%. Even after running `wasm-opt -O4` on them, there is still 4.8% improvement.
Reviewed By: dschuff
Differential Revision: https://reviews.llvm.org/D108945
show more ...
|
| #
f5cff292 |
| 26-Aug-2021 |
Heejin Ahn <[email protected]> |
[WebAssembly] Fix PHI when relaying longjmps
When doing Emscritpen EH, if SjLj is also enabled and used and if the thrown exception has a possiblity being a longjmp instead of an exception, we shoul
[WebAssembly] Fix PHI when relaying longjmps
When doing Emscritpen EH, if SjLj is also enabled and used and if the thrown exception has a possiblity being a longjmp instead of an exception, we shouldn't swallow it; we should rethrow, or relay it. It was done in D106525 and the code is here: https://github.com/llvm/llvm-project/blob/8441a8eea8007b9eaaaabf76055949180a702d6d/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp#L858-L898
Here is the pseudocode of that part: (copied from comments) ``` if (%__THREW__.val == 0 || %__THREW__.val == 1) goto %tail else goto %longjmp.rethrow
longjmp.rethrow: ;; This is longjmp. Rethrow it %__threwValue.val = __threwValue emscripten_longjmp(%__THREW__.val, %__threwValue.val);
tail: ;; Nothing happened or an exception is thrown ... Continue exception handling ... ```
If the current BB (where the `invoke` is created) has successors that has the current BB as its PHI incoming node, now that has to change to `tail` in the pseudocode, because `tail` is the latest BB that is connected with the next BB, but this was missing.
Reviewed By: tlively
Differential Revision: https://reviews.llvm.org/D108785
show more ...
|
|
Revision tags: llvmorg-13.0.0-rc2 |
|
| #
e849d99d |
| 25-Aug-2021 |
Heejin Ahn <[email protected]> |
[WebAssembly] Use entry block only for initializations in EmSjLj
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,
[WebAssembly] Use entry block only for initializations in EmSjLj
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.
Reviewed By: tlively
Differential Revision: https://reviews.llvm.org/D108729
show more ...
|
| #
77b921b8 |
| 07-Aug-2021 |
Heejin Ahn <[email protected]> |
[WebAssembly] Tidy up EH/SjLj options
This CL is small, but the description can be a little long because I'm trying to sum up the status quo for Emscripten/Wasm EH/SjLj options.
First, this CL adds
[WebAssembly] Tidy up EH/SjLj options
This CL is small, but the description can be a little long because I'm trying to sum up the status quo for Emscripten/Wasm EH/SjLj options.
First, this CL adds an option for Wasm SjLj (`-wasm-enable-sjlj`), which handles SjLj using Wasm EH. The implementation for this will be added as a followup CL, but this adds the option first to do error checking.
This also adds an option for Wasm EH (`-wasm-enable-eh`), which has been already implemented. Before we used `-exception-model=wasm` as the same meaning as enabling Wasm EH, but after we add Wasm SjLj, it will be possible to use Wasm EH instructions for Wasm SjLj while not enabling EH, so going forward, to use Wasm EH, `opt` and `llc` will need this option. This only affects `opt` and `llc` command lines and does not affect Emscripten user interface.
Now we have two modes of EH (Emscripten/Wasm) and also two modes of SjLj (also Emscripten/Wasm). The options corresponding to each of are: - Emscripten EH: `-enable-emscripten-cxx-exceptions` - Emscripten SjLj: `-enable-emscripten-sjlj` - Wasm EH: `-wasm-enable-eh -exception-model=wasm` `-mattr=+exception-handling` - Wasm SjLj: `-wasm-enable-sjlj -exception-model=wasm` `-mattr=+exception-handling` The reason Wasm EH/SjLj's options are a little complicated are `-exception-model` and `-mattr` are common LLVM options ane not under our control. (`-mattr` can be omitted if it is embedded within the bitcode file.)
And we have the following rules of the option composition: - Emscripten EH and Wasm EH cannot be turned on at the same itme - Emscripten SjLj and Wasm SjLj cannot be turned on at the same time - Wasm SjLj should be used with Wasm EH
Which means we now allow these combinations: - Emscripten EH + Emscripten SjLj: the current default in `emcc` - Wasm EH + Emscripten SjLj: This is allowed, but only as an interim step in which we are testing Wasm EH but not yet have a working implementation of Wasm SjLj. This will error out (D107687) in compile time if `setjmp` is called in a function in which Wasm exception is used. - Wasm EH + Wasm SjLj: This will be the default mode later when using Wasm EH. Currently Wasm SjLj implementation doesn't exist, so it doesn't work. - Emscripten EH + Wasm SjLj will not work.
This CL moves these error checking routines to `WebAssemblyPassConfig::addIRPasses`. Not sure if this is an ideal place to do this, but I couldn't find elsewhere. Currently some checking is done within LowerEmscriptenEHSjLj, but these checks only run if LowerEmscriptenEHSjLj runs so it may not run when Wasm EH is used. This moves that to `addIRPasses` and adds some more checks.
Currently LowerEmscriptenEHSjLj pass is responsible for Emscripten EH and Emscripten SjLj. Wasm EH transformations are done in multiple places, including WasmEHPrepare, LateEHPrepare, and CFGStackify. But in the followup CL, LowerEmscriptenEHSjLj pass will be also responsible for a part of Wasm SjLj transformation, because WasmSjLj will also be using several Emscripten library functions, and we will be sharing more than half of the transformation to do that between Emscripten SjLj and Wasm SjLj.
Currently we have `-enable-emscripten-cxx-exceptions` and `-enable-emscripten-sjlj` but these only work for `llc`, because for `llc` we feed these options to the pass but when we run the pass using `opt` the pass will be created with no options and the default options will be used, which turns both Emscripten EH and Emscripten SjLj on.
Now we have one more SjLj option to care for, LowerEmscriptenEHSjLj pass needs a finer way to control these options. This CL removes those default parameters and make LowerEmscriptenEHSjLj pass read directly from command line options specified. So if we only run `opt -wasm-lower-em-ehsjlj`, currently both Emscripten EH and Emscripten SjLj will run, but with this CL, none will run unless we additionally pass `-enable-emscripten-cxx-exceptions` or `-enable-emscripten-sjlj`, or both. This does not affect users; this only affects our `opt` tests because `emcc` will not call either `opt` or `llc`. As a result of this, our existing Emscripten EH/SjLj tests gained one or both of those options in their `RUN` lines.
Reviewed By: dschuff
Differential Revision: https://reviews.llvm.org/D107685
show more ...
|
| #
adb96d2e |
| 09-Aug-2021 |
Heejin Ahn <[email protected]> |
[WebAssembly] Fix leak in Emscripten SjLj
For SjLj, we allocate a table to record setjmp buffer info in the entry of each setjmp-calling function by inserting a `malloc` call, and insert a `free` ca
[WebAssembly] Fix leak in Emscripten SjLj
For SjLj, we allocate a table to record setjmp buffer info in the entry of each setjmp-calling function by inserting a `malloc` call, and insert a `free` call to free the buffer before each `ret` instruction.
But this is not sufficient; we have to free the buffer before we throw. In SjLj handling, normal functions that can possibly throw or longjmp are wrapped with an invoke and caught within the function so they don't end up escaping the function. But three functions throw and escape the function: - `__resumeException` (Emscripten library function used for Emscripten EH) - `emscripten_longjmp` (Emscripten library function used for Emscripten SjLj) - `__cxa_throw` (libc++abi function called when for C++ `throw` keyword)
The first two functions are used to rethrow the current exception/longjmp when the caught exception/longjmp is not for the current function. `__cxa_throw` is used for exception, and because we consider that a function that cannot longjmp, it escapes the function right away, before which we should free the buffer.
Currently `lsan.test_longjmp3` and `lsan.test_exceptions_longjmp3` fail in Emscripten; this CL fixes these.
Reviewed By: dschuff
Differential Revision: https://reviews.llvm.org/D107852
show more ...
|
|
Revision tags: llvmorg-13.0.0-rc1 |
|
| #
9bd02c43 |
| 02-Aug-2021 |
Heejin Ahn <[email protected]> |
[WebAssembly] Misc. cosmetic changes in EH (NFC)
- Rename `wasm.catch` intrinsic to `wasm.catch.exn`, because we are planning to add a separate `wasm.catch.longjmp` intrinsic which returns two v
[WebAssembly] Misc. cosmetic changes in EH (NFC)
- Rename `wasm.catch` intrinsic to `wasm.catch.exn`, because we are planning to add a separate `wasm.catch.longjmp` intrinsic which returns two values. - Rename several variables - Remove an unnecessary parameter from `canLongjmp` and `isEmAsmCall` from LowerEmscriptenEHSjLj pass - Add `-verify-machineinstrs` in a test for a safety measure - Add more comments + fix some errors in comments - Replace `std::vector` with `SmallVector` for cases likely with small number of elements - Renamed `EnableEH`/`EnableSjLj` to `EnableEmEH`/`EnableEmSjLj`: We are soon going to add `EnableWasmSjLj`, so this makes the distincion clearer
Reviewed By: tlively
Differential Revision: https://reviews.llvm.org/D107405
show more ...
|
|
Revision tags: llvmorg-14-init |
|
| #
c285a11e |
| 17-Jul-2021 |
Heejin Ahn <[email protected]> |
[WebAssembly] Make Emscripten EH work with Emscripten SjLj
When Emscripten EH mixes with Emscripten SjLj, we are not currently handling some of them correctly. There are three cases: 1. The current
[WebAssembly] Make Emscripten EH work with Emscripten SjLj
When Emscripten EH mixes with Emscripten SjLj, we are not currently handling some of them correctly. There are three cases: 1. The current function calls `setjmp` and there is an `invoke` to a function that can either throw or longjmp. In this case, we have to check both for exception and longjmp. We are currently handling this case correctly: https://github.com/llvm/llvm-project/blob/0c0eb76782d5224b8d81a5afbb9a152bcf7c94c7/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp#L1058-L1090 When inserting routines for functions that can longjmp, which we do only for setjmp-calling functions, we check if the function was previously an `invoke` and handle it correctly.
2. The current function does NOT call `setjmp` and there is an `invoke` to a function that can either throw or longjmp. Because there is no `setjmp` call, we haven't been doing any check for functions that can longjmp. But in that case, for `invoke`, we only check for an exception and if it is not an exception we reset `__THREW__` to 0, which can silently swallow the longjmp: https://github.com/llvm/llvm-project/blob/0c0eb76782d5224b8d81a5afbb9a152bcf7c94c7/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp#L70-L80 This CL fixes this.
3. The current function calls `setjmp` and there is no `invoke`. Because it is not an `invoke`, we haven't been doing any check for functions that can throw, and only insert longjmp-checking routines for functions that can longjmp. But in that case, if a longjmpable function throws, we only check for a longjmp so if it is not a longjmp we reset `__THREW__` to 0, which can silently swallow the exception: https://github.com/llvm/llvm-project/blob/0c0eb76782d5224b8d81a5afbb9a152bcf7c94c7/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp#L156-L169 This CL fixes this.
To do that, this moves around some code, so we register necessary functions for both EH and SjLj and precompute some data (the set of functions that contains `setjmp`) before doing actual EH or SjLj transformation.
This CL makes 2nd and 3rd tests in https://github.com/emscripten-core/emscripten/pull/14732 work.
Reviewed By: dschuff
Differential Revision: https://reviews.llvm.org/D106525
show more ...
|