| Commit message (Collapse) | Author | Age | Files | Lines |
... | |
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This updates `try`-`catch`-`catch_all` and `rethrow` instructions to
match the new spec. `delegate` is not included. Now `Try` contains not a
single `catchBody` expression but a vector of catch
bodies and events.
This updates most existing routines, optimizations, and tests modulo the
interpreter and the CFG traversal. Because the interpreter has not been
updated yet, the EH spec test is temporarily disabled in check.py. Also,
because the CFG traversal for EH is not yet updated, several EH tests in
`rse_all-features.wast`, which uses CFG traversal, are temporarily
commented out.
Also added a few more tests in existing EH test functions in
test/passes. In the previous spec, `catch` was catching all exceptions
so it was assumed that anything `try` body throws is caught by its
`catch`, but now we can assume the same only if there is a `catch_all`.
Newly added tests test cases when there is a `catch_all` and cases there
are only `catch`es separately.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The code there looks for a "sign-extend": (x << a) >> b where the
right shift is signed. If a = b = 24 for example then that is a sign
extend of an 8-bit value (it works by shifting the 8-bit value's sign bit
to the position of the 32-bit value's sign bit, then shifting all the way
back, which fills everything above 8 bits with the sign bit). The tricky
thing is that in some cases we can handle a != b - but we forgot a
place to check that. Specifically, a repeated sign-extend is not
necessary, but if the outer one has extra shifts, we can't do it.
This is annoyingly complex code, but for purposes of reviewing this
PR, you can see (unless I messed up) that the only change is to
ensure that when we look for a repeated sign extend, then we
only optimize that case when there are no extra shifts. And a
repeated sign-extend is obviously ok to remove,
(((x << a) >> a) << a) >> a => (x << a) >> a
This is an ancient bug, showing how hard it can be to find certain
patterns either by fuzzing or in the real world...
Fixes #3362
|
|
|
|
| |
values (#3399)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
bugs (#3401)
* Count signatures in tuple locals.
* Count nested signature types (confirming @aheejin was right, that was missing).
* Inlining was using the wrong type.
* OptimizeInstructions should return -1 for unhandled types, not error.
* The fuzzer should check for ref types as well, not just typed function references,
similar to what GC does.
* The fuzzer now creates a function if it has no other option for creating a constant
expression of a function type, then does a ref.func of that.
* Handle unreachability in call_ref binary reading.
* S-expression parsing fixes in more places, and add a tiny fuzzer for it.
* Switch fuzzer test to just have the metrics, and not print all the fuzz output which
changes a lot. Also fix noprint handling which only worked on binaries before.
* Fix Properties::getLiteral() to use the specific function type properly, and make
Literal's function constructor require that, to prevent future bugs.
* Turn all input types into nullable types, for now.
|
|
|
| |
The vacuum code can be deleted as it is handled by the default anyhow.
|
|
|
|
| |
See discussion in #3303
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
X - Y <= 0
=>
X <= Y
That is true mathematically, but not in the case of an overflow, e.g.
X=10, Y=0x8000000000000000. X - Y is a negative number, so
X - Y <= 0 is true. But it is not true that X <= Y (as Y is negative, but
X is not).
See discussion in #3303 (comment)
The actual regression was in #3275, but the fuzzer had an easier time
finding it due to #3303
|
|
|
|
|
|
| |
bool(i32(x) % C_pot) -> bool(i32(x) & (C_pot - 1))
bool(i32(x) % min_s) -> bool(i32(x) & max_s)
For all other situations we already do this for (i32|i64).rem_s
|
|
|
|
|
|
|
| |
Using addition in more places is better for gzip, and helps simplify the
optimizer as well.
Add a FinalOptimizer phase to do optimizations like our signed LEB tweaks, to
reduce binary size in the rare case when we do want a subtraction.
|
| |
|
|
|
| |
Move the checks for most unoptimizable expression types out into visitExpression and simplify some other code.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
We can still make x * -1.0 cheaper for non-fastMath mode as:
x * -1.0 -> -0.0 - x
Should at least help baseline compilers.
Also it could enable further optimizations, e.g.:
a + b * -1
a + (-0.0 - b)
(a - 0.0) - b
a - b
|
| |
|
|
|
|
|
| |
`C1 - (x + C2)` -> `(C1 - C2) - x`
`C1 - (x - C2)` -> `(C1 + C2) - x`
`C1 - (C2 - x)` -> `x + (C1 - C2)`
|
| |
|
|
|
|
|
|
|
|
| |
Fixes a fuzz bug that was triggered by
https://github.com/WebAssembly/binaryen/pull/3015#issuecomment-718001620
but was actually a pre-existing bug in pow2, that that PR just happened
to uncover.
|
| |
|
|
|
| |
But only when doing so doesn't require adding a new local.
|
| |
|
| |
|
|
|
|
|
|
|
|
|
| |
This change makes matchers in OptimizeInstructions more compact and readable by
removing the explicit `Abstract::` namespace from individual operations. In some
cases, this makes multi-line matcher expressions fit on a single line.
This change is only possible because it also adds an explicit "RMW" prefix to
each element of the `AtomicRMWOp` enumeration. Without that, their names
conflicted with the names of Abstract ops.
|
| |
|
|
|
|
|
| |
Extend ZeroRemover and optimizeAddedConstants to handle 64-bit integers as well.
Use Literal.makeFromInt64 to make this easier.
|
| |
|
| |
|
|
|
|
|
|
|
|
|
|
| |
i32(bool(x)) != 0 ==> i32(bool(x))
i64(bool(x)) & 1 ==> i64(bool(x))
Also:
* clean up related matching rules in optimizeWithConstantOnRight
* add more explanations about isPowerOf2Float & rename to
isPowerOfTwoInvertibleFloat
|
| |
|
| |
|
|
|
|
|
|
|
|
| |
`(uint32_t)x / C` --> `x >= C`, where `C > 2^31`
`(uint32_t)x / -1` --> `x != -1`
and for `shrinkLevel == 0`:
`(uint64_t)x / C` --> `uint64_t(x >= C)`, where `C > 2^63`
`(uint64_t)x / -1` --> `x != -1`
|
|
|
| |
When there are two versions of a function, one handling tuples and the other handling non-tuple values, the previous naming convention was to have "Single" in the name of the non-tuple handling function. This PR simplifies the convention and shortens function names by making the names plural for the tuple-handling version and singular for the non-tuple-handling version.
|
|
|
|
|
|
| |
Wasm turned out to not be that good for a DSL for such peephole optimizations,
so that never made progress. Meanwhile we have the new matcher stuff which
works well.
|
|
|
| |
Specifically, truncates constant shift values that are greater than the number of bits available and optimizes out explicit masking of the shift value that is redundant with the implicit masking performed by shift operations.
|
|
|
| |
`(signed)x % (i32|i64).min_s ==> (x & (i32|i64).max_s)` is not valid unless compared to zero.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Implement a more general (additional) version of #3153 which also handles negative constant divisors:
`(int32)x % -4 == 0` --> `(x & 3) == 0`
`x % -C_pot == 0` --> `(x & (abs(C_pot) - 1)) == 0`
and special two-complement values as well:
`(int32)x % 0x80000000 == 0` --> `(x & 0x7fffffff) == 0`
`(int64)x % 0x8000000000000000 == 0` --> `(x & 0x7fffffffffffffff) == 0`
as separete rules:
`(int32)x % 0x80000000` --> `x & 0x7fffffff`
`(int64)x % 0x8000000000000000` --> `x & 0x7fffffffffffffff`
The [previous pr](https://github.com/WebAssembly/binaryen/pull/3153) didn't use these possibilities.
|
|
|
|
|
|
|
|
|
|
|
|
| |
(found by the fuzzer)
It is not valid to replace x | (y | x) ==> y | x, if x, y cannot be reordered.
It is also not valid to replace x ^ (y ^ x) ==> y, if x, y cannot be reordered,
for a more subtle reason: if they cannot be reordered then y can affect the
value of x (the opposite is not possible as we checked x for side effects so
that we could remove one copy). If so, then the second appearance of x
could be different, if e.g. it reads a local y writes to. Whereas, if it's ok to
reorder, then it's ok to do x ^ (y ^ x) ==> x ^ (x ^ y) ==> y.
|
|
|
|
| |
mask (#3184)
|
| |
|
|
|
|
|
| |
Use overloads instead of templates where applicable and change function names
from PascalCase to camelCase. Also puts the functions in the Bits namespace to
avoid naming conflicts.
|
|
|
|
|
|
|
|
|
|
|
|
| |
Similar to clang and gcc, --fast-math makes us ignore corner cases of floating-point
math like NaN changes and (not done yet) lack of associativity and so forth.
In the future we may want to have separate fast math flags for each specific thing,
like gcc and clang do.
This undoes some changes (#2958 and #3096) where we assumed it was
ok to not change NaN bits, but @binji corrected us. We can only do such things in fast
math mode. This puts those optimizations behind that flag, adds tests for it, and
restores the interpreter to the simpler code from before with no special cases.
|
|
|
| |
Specifically, when `x` has at most 32 bits so that wrapping doesn't change its value.
|
|
|
|
|
|
| |
Specifically when the divisor is a power of two.
`eqz((signed)x % C_pot)` -> `eqz(x & (C_pot - 1))`
`(signed)x % C_pot != 0` -> `x & (C_pot - 1) != 0`
|
| |
|
|
|
| |
This can unlock further instruction optimizations that do not apply to signed operations.
|
|
|
|
|
|
|
|
|
|
|
| |
Provides an easily extensible layered API for matching expression patterns and
extracting their components. The low-level API provides modular building blocks
for creating matchers for any data type and the high-level API provides a
succinct and flexible interface for matching expressions and extracting useful
information from them.
Matchers are currently provided for Const, Unary, Binary, and Select
instructions. Adding a matcher for a new type of expression is straightforward
enough that I expect to add them as they become useful as part of other changes.
|
|
|
| |
Also includes a lot of new spec tests that eventually need to go into the spec repo
|
|
|
|
|
|
|
| |
`expr | 1` --> `1`
`expr & 1` --> `expr`
`expr == 1` --> `expr`
`expr != 1` --> `!expr`
where `maxBits(expr) == 1` i.e `expr` is boolean
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Simplifies patterns in which an expression is applied twice to its operands.
`abs(abs(x))` -> `abs(x)`
`ceil(ceil(x))` -> `ceil(x)`
`floor(floor(x))` -> `floor(x)`
`trunc(trunc(x))` -> `trunc(x)`
`nearest(nearest(x))` -> `nearest(x)`
`eqz(eqz(bool(x)))` -> `bool(x)`
`sext(sext(x))` -> `sext(x)`
`neg(neg(x))` -> `x`
`y - (y - x)` -> `x`
`(x ^ y) ^ y` -> `x`
`(x | y) | y` -> `x | y`
`(x & y) & y` -> `x & y`
`(x % y) % y` -> `x % y`
|
|
|
| |
Add floating point Eq and Ne operators to Properties::isSymmetric. Also treat additional float ops as symmetric specifically in OptimizeInstructions when their operands are known to be non-NaN.
|