Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Enable the optimizer with WebAssembly. #4993

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 17 commits into from
Aug 25, 2024

Conversation

sjrd
Copy link
Member

@sjrd sjrd commented May 31, 2024

No description provided.

@sjrd sjrd force-pushed the optimizer-with-webassembly branch 4 times, most recently from 43167ba to 00c9b29 Compare June 2, 2024 21:32
@sjrd sjrd force-pushed the optimizer-with-webassembly branch from 019b27c to 367d63a Compare June 24, 2024 13:20
@sjrd sjrd force-pushed the optimizer-with-webassembly branch from 367d63a to d2e1a37 Compare July 1, 2024 16:46
@sjrd sjrd force-pushed the optimizer-with-webassembly branch 2 times, most recently from 5ba5398 to 13a46b9 Compare July 30, 2024 08:34
@sjrd sjrd force-pushed the optimizer-with-webassembly branch 4 times, most recently from 427dd73 to 909e82a Compare August 10, 2024 22:25
@sjrd sjrd changed the title CI ONLY Enable the optimizer with WebAssembly. Enable the optimizer with WebAssembly. Aug 10, 2024
@sjrd sjrd requested a review from gzm0 August 10, 2024 22:25
@sjrd sjrd marked this pull request as ready for review August 10, 2024 22:25
@sjrd
Copy link
Member Author

sjrd commented Aug 10, 2024

This is now ready for review. The commits are supposed to be meaningful, i.e., not squashed.

Also review by @tanishiking, but I cannot assign you.

Copy link
Contributor

@gzm0 gzm0 left a comment

Choose a reason for hiding this comment

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

Partial review up to "enable intrinsics" (exclusive).

@sjrd sjrd force-pushed the optimizer-with-webassembly branch from 909e82a to 4851517 Compare August 11, 2024 11:36
Copy link
Contributor

@tanishiking tanishiking left a comment

Choose a reason for hiding this comment

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

Left several questions, overall it looks good to me :)

Comment on lines +2883 to +2909
genTreeAuto(tree.record)

markPosition(tree)

val tempTypes = transformResultType(tree.tpe)
val tempLocals = tempTypes.map(addSyntheticLocal(_))

val recordType = tree.record.tpe.asInstanceOf[RecordType]
for (recordField <- recordType.fields.reverseIterator) {
if (recordField.name == tree.field.name) {
// Store this one in our temp locals
for (tempLocal <- tempLocals.reverseIterator)
fb += wa.LocalSet(tempLocal)
} else {
// Discard this field
for (_ <- transformResultType(recordField.tpe))
fb += wa.Drop
}
}

// Read back our locals
for (tempLocal <- tempLocals)
fb += wa.LocalGet(tempLocal)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

[note]
When the tree looks like

RecordSelect({
  "x": ...,
  "y": {"a": ..., "b": ...},
  "z": {"z1": ..., "z2": ...}
}, "y")

The resulting code looks like

;; tempTypes = [(type of "a"), (type of "b")]
;; tempLocals = [local a, local b]

;; push value for "x"
;; push ... "a"
;; push ... "b"
;; push ... "z1"
;; push ... "z2"

;; drop values for "z" for else branch
drop ;; z2
drop ;; z1
;; field found, local.set values
local.set $b
local.set $a
;; drop values for "x"
drop

;; read back locals
local.get $a
local.get $b

@sjrd sjrd force-pushed the optimizer-with-webassembly branch from 4851517 to a133a94 Compare August 13, 2024 14:18
}

case IntegerRotateLeft =>
contTree(wasmBinaryOp(WasmBinaryOp.I32Rotl, targs.head, targs.tail.head))
Copy link
Contributor

Choose a reason for hiding this comment

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

What is the rationale to not constant fold here (but above)?

Also, instead of targs.tail.head, destructure targs:

Suggested change
contTree(wasmBinaryOp(WasmBinaryOp.I32Rotl, targs.head, targs.tail.head))
val List(arg0, arg1) = targs
contTree(wasmBinaryOp(WasmBinaryOp.I32Rotl, arg0, arg1))

Copy link
Member Author

Choose a reason for hiding this comment

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

We should constant-fold, indeed.

genericWasmDivModUnsigned(WasmBinaryOp.I32DivU, BinaryOp.Int_/,
BinaryOp.Int_==, IntLiteral(0))
case IntegerRemainderUnsigned =>
genericWasmDivModUnsigned(WasmBinaryOp.I32RemU, BinaryOp.Int_/,
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
genericWasmDivModUnsigned(WasmBinaryOp.I32RemU, BinaryOp.Int_/,
genericWasmDivModUnsigned(WasmBinaryOp.I32RemU, BinaryOp.Int_%,

Copy link
Contributor

@tanishiking tanishiking left a comment

Choose a reason for hiding this comment

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

Left a comment, otherwise LGTM from my side :)

sjrd added 3 commits August 24, 2024 11:38
This will be used to provide that information to the optimizer as
well as to user-space through linking info. Therefore, it is an
observable piece of knowledge that belongs to the core spec.
`StructField` is only used for captures, which are always
immutable.
sjrd added 14 commits August 24, 2024 11:41
However, it does box `long`s into instances, which means that two
boxed longs are not `===`.
We can selectively reintroduce them later.
The WebAssembly backend and the optimizer are now happy to work
together, so we can enable the latter.
When compiling to Wasm, the optimized implementation we have for
`ArrayBuilder` makes no sense, as it relies on JavaScript arrays.
Therefore, we revert to using the original implementations when
linking for Wasm.
This includes `arraycopy` and `getClass().getName()`, which produce
new `Transient` nodes that we need to handle in the Wasm backend.
The motivation is mainly to get intrinsics for the bit-conversions
between integers and floating point numbers, as well as for
`numberLeadingZeros`. These are building blocks for many other
low-level operations, and their JS-builtin-based implementation is
really bad on Wasm for those use cases.

Once we have the infrastructure for those as transients in the Wasm
backend, we also take the opportunity to add a series of other
methods that have a direct Wasm opcode equivalent.
The implementation based on `FloatingPointBits` is poor for a Wasm
output, as it uses JS interop. Given that we have an intrinsic for
`doubleToLongBits`, we can implement it much more efficiently for
Wasm.

This is important because this function is called to compute the
hash code of all JS `number`s, including those that originate as
`Int`s.
When we resolve a dynamic call to a single possible target, but we
do not inline it, we now replace the `Apply` by an `ApplyStatically`.
This communicates the result of the resolution to the backend, which
can emit a static `call` instead of a vtable or itable-based dispatch.
These were one of two remaining sources of `Apply` nodes that the
backend could turn into `ApplyStatically` but that the optimizer
could not (because they are created after the optimizer).
The optimizer already replaces `Apply` nodes that can be statically
resolved by `ApplyStatically`. The `isEffectivelyFinal` analysis is
therefore not useful anymore.

Technically, it was still applicable to JS property/method *names*
that are not string constants, but that is too niche to justify
keeping the analysis. Also, arguably the correct fix for that would
be to make the optimizer also optimize JS property/method names,
since it would also benefit the JS backend.
`ClassInfo` is now completely immutable.
@sjrd sjrd force-pushed the optimizer-with-webassembly branch from 8ef4404 to 828f90b Compare August 24, 2024 09:46
@sjrd sjrd requested a review from gzm0 August 24, 2024 09:46
@gzm0
Copy link
Contributor

gzm0 commented Aug 25, 2024

I've checked that @tanishiking's pending comment is also addressed, so I'll proceed with merging this.

@gzm0 gzm0 merged commit 7d19e39 into scala-js:main Aug 25, 2024
3 checks passed
@sjrd sjrd deleted the optimizer-with-webassembly branch August 25, 2024 09:17
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.

3 participants