[dart2wasm] Inlined and optimized some int and double operations.

In particular functions that will benefit from the subsequent unboxing
and value propagation by Binaryen are marked for inlining.

Change-Id: Id131de47b42af11f17e227003ee828eb02c5d3cf
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/279097
Reviewed-by: Ömer Ağacan <omersa@google.com>
Commit-Queue: Aske Simon Christensen <askesc@google.com>
This commit is contained in:
Aske Simon Christensen 2023-01-18 13:37:22 +00:00 committed by Commit Queue
parent be1a45173a
commit 46f3efb8eb
3 changed files with 75 additions and 12 deletions

View file

@ -50,6 +50,7 @@ class Intrinsifier {
'_shl': (b) => b.i64_shl(),
'_shr_s': (b) => b.i64_shr_s(),
'_shr_u': (b) => b.i64_shr_u(),
'_le_u': (b) => b.i64_le_u(),
'_lt_u': (b) => b.i64_lt_u(),
}
},
@ -63,6 +64,7 @@ class Intrinsifier {
'<=': (b) => b.f64_le(),
'>': (b) => b.f64_gt(),
'>=': (b) => b.f64_ge(),
'_copysign': (b) => b.f64_copysign(),
}
},
};
@ -117,7 +119,12 @@ class Intrinsifier {
}
static bool isComparison(String op) =>
op == '<' || op == '<=' || op == '>' || op == '>=' || op == '_lt_u';
op == '<' ||
op == '<=' ||
op == '>' ||
op == '>=' ||
op == '_le_u' ||
op == '_lt_u';
Intrinsifier(this.codeGen);

View file

@ -52,6 +52,9 @@ class double {
/// Wasm i64.trunc_sat_f64_s instruction
external int _toInt();
/// Wasm f64.copysign instruction
external double _copysign(double other);
}
@pragma("wasm:entry-point")
@ -86,11 +89,16 @@ class _BoxedDouble extends double {
return (bits ^ (bits >>> 32)) & 0x3FFFFFFF;
}
@pragma("wasm:prefer-inline")
double operator +(num other) => this + other.toDouble(); // Intrinsic +
@pragma("wasm:prefer-inline")
double operator -(num other) => this - other.toDouble(); // Intrinsic -
@pragma("wasm:prefer-inline")
double operator *(num other) => this * other.toDouble(); // Intrinsic *
@pragma("wasm:prefer-inline")
double operator /(num other) => this / other.toDouble(); // Intrinsic /
@pragma("wasm:prefer-inline")
int operator ~/(num other) {
return _truncDiv(this, other.toDouble());
}
@ -99,6 +107,7 @@ class _BoxedDouble extends double {
return (a / b).toInt();
}
@pragma("wasm:prefer-inline")
double operator %(num other) {
return _modulo(this, other.toDouble());
}
@ -116,6 +125,7 @@ class _BoxedDouble extends double {
return rem;
}
@pragma("wasm:prefer-inline")
double remainder(num other) {
return _remainder(this, other.toDouble());
}
@ -126,6 +136,7 @@ class _BoxedDouble extends double {
external double operator -();
@pragma("wasm:prefer-inline")
bool operator ==(Object other) {
return other is double
? this == other // Intrinsic ==
@ -134,53 +145,65 @@ class _BoxedDouble extends double {
: false;
}
@pragma("wasm:prefer-inline")
bool operator <(num other) => this < other.toDouble(); // Intrinsic <
@pragma("wasm:prefer-inline")
bool operator >(num other) => this > other.toDouble(); // Intrinsic >
@pragma("wasm:prefer-inline")
bool operator >=(num other) => this >= other.toDouble(); // Intrinsic >=
@pragma("wasm:prefer-inline")
bool operator <=(num other) => this <= other.toDouble(); // Intrinsic <=
@pragma("wasm:prefer-inline")
bool get isNegative {
if (isNaN) {
return false;
}
// Sign bit set, not NaN
int bits = doubleToIntBits(this);
return (bits & _signMask) != 0;
return (bits ^ _signMask)._le_u(_exponentMask);
}
@pragma("wasm:prefer-inline")
bool get isInfinite {
// Exponent at max, mantissa zero
int bits = doubleToIntBits(this);
return (bits & _exponentMask) == _exponentMask &&
(bits & _mantissaMask) == 0;
return (bits & (_exponentMask | _mantissaMask)) == _exponentMask;
}
@pragma("wasm:prefer-inline")
bool get isNaN {
// Exponent at max, mantissa nonzero
int bits = doubleToIntBits(this);
return (bits & _exponentMask) == _exponentMask &&
(bits & _mantissaMask) != 0;
return (bits & (_exponentMask | _mantissaMask)) > _exponentMask;
}
@pragma("wasm:prefer-inline")
bool get isFinite {
// Exponent not at max
int bits = doubleToIntBits(this);
return (bits & _exponentMask) != _exponentMask;
}
@pragma("wasm:prefer-inline")
double abs() {
// Handle negative 0.0.
if (this == 0.0) return 0.0;
return this < 0.0 ? -this : this;
return _copysign(0.0);
}
@pragma("wasm:prefer-inline")
double get sign {
if (this > 0.0) return 1.0;
if (this < 0.0) return -1.0;
return this; // +/-0.0 or NaN.
}
@pragma("wasm:prefer-inline")
int round() => roundToDouble().toInt();
@pragma("wasm:prefer-inline")
int floor() => floorToDouble().toInt();
@pragma("wasm:prefer-inline")
int ceil() => ceilToDouble().toInt();
@pragma("wasm:prefer-inline")
int truncate() => truncateToDouble().toInt();
@pragma("wasm:prefer-inline")
double roundToDouble() {
return _roundToDouble(this);
}
@ -223,6 +246,7 @@ class _BoxedDouble extends double {
return this;
}
@pragma("wasm:prefer-inline")
int toInt() {
if (!isFinite) {
throw UnsupportedError("Infinity or NaN toInt");
@ -230,6 +254,7 @@ class _BoxedDouble extends double {
return _toInt();
}
@pragma("wasm:prefer-inline")
double toDouble() {
return this;
}

View file

@ -9,6 +9,9 @@ class int {
/// Wasm i64.div_s instruction
external int _div_s(int divisor);
/// Wasm i64.le_u instruction
external bool _le_u(int other);
/// Wasm i64.lt_u instruction
external bool _lt_u(int other);
@ -38,14 +41,17 @@ class _BoxedInt extends int {
external num operator -(num other);
external num operator *(num other);
@pragma("wasm:prefer-inline")
double operator /(num other) {
return this.toDouble() / other.toDouble();
}
@pragma("wasm:prefer-inline")
int operator ~/(num other) => other is int
? _truncDiv(this.value, other)
: _BoxedDouble._truncDiv(toDouble(), unsafeCast<double>(other));
@pragma("wasm:prefer-inline")
num operator %(num other) => other is int
? _modulo(this, other)
: _BoxedDouble._modulo(toDouble(), unsafeCast<double>(other));
@ -62,6 +68,7 @@ class _BoxedInt extends int {
return rem;
}
@pragma("wasm:prefer-inline")
static int _truncDiv(int a, int b) {
// Division special case: overflow in I64.
// MIN_VALUE / -1 = (MAX_VALUE + 1), which wraps around to MIN_VALUE
@ -77,6 +84,7 @@ class _BoxedInt extends int {
return a._div_s(b);
}
@pragma("wasm:prefer-inline")
num remainder(num other) => other is int
? this - (this ~/ other) * other
: _BoxedDouble._remainder(toDouble(), unsafeCast<double>(other));
@ -87,6 +95,7 @@ class _BoxedInt extends int {
external int operator |(int other);
external int operator ^(int other);
@pragma("wasm:prefer-inline")
int operator >>(int shift) {
// Unsigned comparison to check for large and negative shifts
if (shift._lt_u(64)) {
@ -101,6 +110,7 @@ class _BoxedInt extends int {
return this._shr_s(63);
}
@pragma("wasm:prefer-inline")
int operator >>>(int shift) {
// Unsigned comparison to check for large and negative shifts
if (shift._lt_u(64)) {
@ -115,6 +125,7 @@ class _BoxedInt extends int {
return 0;
}
@pragma("wasm:prefer-inline")
int operator <<(int shift) {
// Unsigned comparison to check for large and negative shifts
if (shift._lt_u(64)) {
@ -134,6 +145,7 @@ class _BoxedInt extends int {
external bool operator >=(num other);
external bool operator <=(num other);
@pragma("wasm:prefer-inline")
bool operator ==(Object other) {
return other is int
? this == other // Intrinsic ==
@ -142,10 +154,12 @@ class _BoxedInt extends int {
: false;
}
@pragma("wasm:prefer-inline")
int abs() {
return this < 0 ? -this : this;
}
@pragma("wasm:prefer-inline")
int get sign {
return (this > 0)
? 1
@ -154,17 +168,25 @@ class _BoxedInt extends int {
: 0;
}
@pragma("wasm:prefer-inline")
bool get isEven => (this & 1) == 0;
@pragma("wasm:prefer-inline")
bool get isOdd => (this & 1) != 0;
@pragma("wasm:prefer-inline")
bool get isNaN => false;
@pragma("wasm:prefer-inline")
bool get isNegative => this < 0;
@pragma("wasm:prefer-inline")
bool get isInfinite => false;
@pragma("wasm:prefer-inline")
bool get isFinite => true;
@pragma("wasm:prefer-inline")
int toUnsigned(int width) {
return this & ((1 << width) - 1);
}
@pragma("wasm:prefer-inline")
int toSigned(int width) {
// The value of binary number weights each bit by a power of two. The
// twos-complement value weights the sign bit negatively. We compute the
@ -214,34 +236,42 @@ class _BoxedInt extends int {
}
}
@pragma("wasm:prefer-inline")
int round() {
return this;
}
@pragma("wasm:prefer-inline")
int floor() {
return this;
}
@pragma("wasm:prefer-inline")
int ceil() {
return this;
}
@pragma("wasm:prefer-inline")
int truncate() {
return this;
}
@pragma("wasm:prefer-inline")
double roundToDouble() {
return this.toDouble();
}
@pragma("wasm:prefer-inline")
double floorToDouble() {
return this.toDouble();
}
@pragma("wasm:prefer-inline")
double ceilToDouble() {
return this.toDouble();
}
@pragma("wasm:prefer-inline")
double truncateToDouble() {
return this.toDouble();
}
@ -264,6 +294,7 @@ class _BoxedInt extends int {
return this;
}
@pragma("wasm:prefer-inline")
int toInt() {
return this;
}