| Commit message (Collapse) | Author | Age | Files | Lines |
... | |
| |
|
|
|
|
|
| |
`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.
|
|
|
|
|
|
|
| |
`x - 0.0` -> `x`
`x + (-0.0)` -> `x`
`x - (-0.0)` -> `x + 0.0`
where `x` is `f32` or `f64`.
|
|
|
| |
This fixes a bug in which a side effect in the calculation of the size could be lost.
|
|
|
|
|
|
|
|
|
| |
According to changes in spec:
WebAssembly/bulk-memory-operations#124
WebAssembly/bulk-memory-operations#145
we unfortunately can't fold to nop even for memory.copy(x, y, 0).
So this PR revert all reductions to nop but do this only under ignoreImplicitTraps flag
|
|
|
|
|
| |
That can trap, so we can only remove it if traps are ignored,
which was not handled properly. Revert it as we consider the
options.
|
|
|
| |
Fix issue found by fuzzer: #3038 (comment)
|
|
|
| |
Replace it with a load and a store when the size is a small constant and remove it entirely when it would be a nop.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
As a follow-up to https://github.com/WebAssembly/binaryen/pull/3012#pullrequestreview-459686171 this PR prepares for the new compound Signature, Struct and Array types that are single but not basic.
This includes:
* Renames `Type::getSingle` to `Type::getBasic` (NFC). Previously, its name was not representing its implementation (`isSingle` excluded `none` and `unreachable` while `getSingle` didn't, i.e. `getSingle` really was `getBasic`). Note that a hypothetical `Type::getSingle` cannot return `ValueType` anyway (new compound types are single but don't map to `ValueType`), so I figured it's best to skip implementing it until we actually need it.
* Marks locations where we are (still) assuming that all single types are basic types, as suggested in https://github.com/WebAssembly/binaryen/pull/3012#discussion_r465356708, but using a macro, so we get useful errors once we start implementing the new types and can quickly traverse the affected locations.
The macro is added where
* there used to be a `switch (type.getSingle())` or similar that handled any basic type (NFC), but in the future will also have to handle single types that are not basic types.
* we are not dealing with `Unary`, `Binary`, `Load`, `Store` or `AtomicXY` instructions, since these don't deal with compound types anyway.
|
|
|
|
|
|
|
|
|
| |
testing for it (#3019)
getMaxBits just moves around, no logic is changed.
Aside from adding getMaxBits, the change in bits.h is 99% whitespace.
helps #2879
|
|
|
|
|
| |
x ? 1 : 0 => !!x
and so forth.
|
|
|
| |
bool(-x) ==> bool(x)
|
| |
|
|
|
|
|
|
| |
- Adds support for `Try` in `optimizeBoolean` function
- Adds support for `Try` in `getFallThrough` function
- Adds approximate cost values for instructions in EH and reference
types proposals.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This adds EH support to `EffectAnalyzer`. Before `throw` and `rethrow`
conservatively set property. Now `EffectAnalyzer` has a new property
`throws` to represent an expression that can throw, and expression that
can throw sets `throws` correctly.
When EH is enabled, any calls can throw too, so we cannot reorder them
with another expression with any side effects, meaning all calls should
be treated in the same way as branches when evaluating `invalidate`.
This prevents many reorderings, so this patch sets `throws` for calls
only when the exception handling features is enabled. This is also why I
passed `--disable-exception-handling` to `wasm2js` tests. Most of code
changes outside of `EffectAnalyzer` class was made in order to pass
`FeatureSet` to it.
`throws` isn't always set whenever an expression contains a throwable
instruction. When an throwable instruction is within an inner try, it
will be caught by the corresponding inner catch, so it does not set
`throws`.
|