[dart2wasm] Use bitwise-and instead of modulo in typed data ops
Generated code for modulo is not as good as bitwise-and, even after
inlining modulo as we inline truncating division in [12e0690][1].
Bitwise-and saves 0.3% binary space in the TypedData benchmark. It
should also be faster.
[1]: https://github.com/dart-lang/sdk/commit/12e0690dfeb869482b32d3a4b3327924103946f6
Change-Id: I4ebac592d7c93d0e81e8b28e789f671ce261780a
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/336361
Commit-Queue: Ömer Ağacan <omersa@google.com>
Reviewed-by: Aske Simon Christensen <askesc@google.com>
diff --git a/sdk/lib/_internal/wasm/lib/typed_data.dart b/sdk/lib/_internal/wasm/lib/typed_data.dart
index 72ea793..999dbf2 100644
--- a/sdk/lib/_internal/wasm/lib/typed_data.dart
+++ b/sdk/lib/_internal/wasm/lib/typed_data.dart
@@ -528,9 +528,7 @@
int _getUint8Unchecked(int byteOffset) {
byteOffset += offsetInBytes;
final byteIndex = byteOffset ~/ elementSizeInBytes;
- return (_data.readUnsigned(byteIndex) >>
- (8 * (byteOffset % elementSizeInBytes))) &
- 0xFF;
+ return (_data.readUnsigned(byteIndex) >> (8 * (byteOffset & 1))) & 0xFF;
}
@override
@@ -538,7 +536,7 @@
byteOffset += offsetInBytes;
final byteIndex = byteOffset ~/ elementSizeInBytes;
final element = _data.readUnsigned(byteIndex);
- final byteElementIndex = byteOffset % elementSizeInBytes;
+ final byteElementIndex = byteOffset & 1;
final b1 = byteElementIndex == 0 ? value : (element & 0xFF);
final b2 = byteElementIndex == 1 ? value : (element >> 8);
final newValue = (b2 << 8) | b1;
@@ -548,7 +546,7 @@
@override
int _getUint16Unchecked(int byteOffset, [Endian endian = Endian.big]) {
final totalOffset = offsetInBytes + byteOffset;
- if (totalOffset % elementSizeInBytes == 0 && endian == Endian.little) {
+ if (totalOffset & 1 == 0 && endian == Endian.little) {
return _data.readUnsigned(totalOffset ~/ elementSizeInBytes);
} else {
return super._getUint16Unchecked(byteOffset, endian);
@@ -559,7 +557,7 @@
void _setUint16Unchecked(int byteOffset, int value,
[Endian endian = Endian.big]) {
final totalOffset = offsetInBytes + byteOffset;
- if (totalOffset % elementSizeInBytes == 0 && endian == Endian.little) {
+ if (totalOffset & 1 == 0 && endian == Endian.little) {
_data.write(totalOffset ~/ elementSizeInBytes, value);
} else {
super._setUint16Unchecked(byteOffset, value, endian);
@@ -593,9 +591,7 @@
int _getUint8Unchecked(int byteOffset) {
byteOffset += offsetInBytes;
final byteIndex = byteOffset ~/ elementSizeInBytes;
- return (_data.readUnsigned(byteIndex) >>
- (8 * (byteOffset % elementSizeInBytes))) &
- 0xFF;
+ return (_data.readUnsigned(byteIndex) >> (8 * (byteOffset & 3))) & 0xFF;
}
@override
@@ -603,7 +599,7 @@
byteOffset += offsetInBytes;
final byteIndex = byteOffset ~/ elementSizeInBytes;
final element = _data.readUnsigned(byteIndex);
- final byteElementIndex = byteOffset % elementSizeInBytes;
+ final byteElementIndex = byteOffset & 3;
final b1 = byteElementIndex == 0 ? value : (element & 0xFF);
final b2 = byteElementIndex == 1 ? value : ((element >> 8) & 0xFF);
final b3 = byteElementIndex == 2 ? value : ((element >> 16) & 0xFF);
@@ -615,7 +611,7 @@
@override
int _getInt32Unchecked(int byteOffset, [Endian endian = Endian.big]) {
final totalOffset = offsetInBytes + byteOffset;
- if (totalOffset % elementSizeInBytes == 0 && endian == Endian.little) {
+ if (totalOffset & 3 == 0 && endian == Endian.little) {
return _data.readSigned(totalOffset ~/ elementSizeInBytes);
} else {
return super._getInt32Unchecked(byteOffset, endian);
@@ -625,7 +621,7 @@
@override
int _getUint32Unchecked(int byteOffset, [Endian endian = Endian.big]) {
final totalOffset = offsetInBytes + byteOffset;
- if (totalOffset % elementSizeInBytes == 0 && endian == Endian.little) {
+ if (totalOffset & 3 == 0 && endian == Endian.little) {
return _data.readUnsigned(totalOffset ~/ elementSizeInBytes);
} else {
return super._getUint32Unchecked(byteOffset, endian);
@@ -636,7 +632,7 @@
void _setInt32Unchecked(int byteOffset, int value,
[Endian endian = Endian.big]) {
final totalOffset = offsetInBytes + byteOffset;
- if (totalOffset % elementSizeInBytes == 0 && endian == Endian.little) {
+ if (totalOffset & 3 == 0 && endian == Endian.little) {
_data.write(totalOffset ~/ elementSizeInBytes, value.toUnsigned(32));
} else {
super._setInt32Unchecked(byteOffset, value, endian);
@@ -647,7 +643,7 @@
void _setUint32Unchecked(int byteOffset, int value,
[Endian endian = Endian.big]) {
final totalOffset = offsetInBytes + byteOffset;
- if (totalOffset % elementSizeInBytes == 0 && endian == Endian.little) {
+ if (totalOffset & 3 == 0 && endian == Endian.little) {
_data.write(totalOffset ~/ elementSizeInBytes, value);
} else {
super._setUint32Unchecked(byteOffset, value, endian);
@@ -681,9 +677,7 @@
int _getUint8Unchecked(int byteOffset) {
byteOffset += offsetInBytes;
final byteIndex = byteOffset ~/ elementSizeInBytes;
- return (_data.readUnsigned(byteIndex) >>
- (8 * (byteOffset % elementSizeInBytes))) &
- 0xFF;
+ return (_data.readUnsigned(byteIndex) >> (8 * (byteOffset & 7))) & 0xFF;
}
@override
@@ -691,7 +685,7 @@
byteOffset += offsetInBytes;
final byteIndex = byteOffset ~/ elementSizeInBytes;
final element = _data.readUnsigned(byteIndex);
- final byteElementIndex = byteOffset % elementSizeInBytes;
+ final byteElementIndex = byteOffset & 7;
final b1 = byteElementIndex == 0 ? value : (element & 0xFF);
final b2 = byteElementIndex == 1 ? value : ((element >> 8) & 0xFF);
final b3 = byteElementIndex == 2 ? value : ((element >> 16) & 0xFF);
@@ -714,7 +708,7 @@
@override
int _getInt64Unchecked(int byteOffset, [Endian endian = Endian.big]) {
final totalOffset = offsetInBytes + byteOffset;
- if (totalOffset % elementSizeInBytes == 0 && endian == Endian.little) {
+ if (totalOffset & 7 == 0 && endian == Endian.little) {
return _data.readSigned(totalOffset ~/ elementSizeInBytes);
} else {
return super._getInt64Unchecked(byteOffset, endian);
@@ -724,7 +718,7 @@
@override
int _getUint64Unchecked(int byteOffset, [Endian endian = Endian.big]) {
final totalOffset = offsetInBytes + byteOffset;
- if (totalOffset % elementSizeInBytes == 0 && endian == Endian.little) {
+ if (totalOffset & 7 == 0 && endian == Endian.little) {
return _data.readUnsigned(totalOffset ~/ elementSizeInBytes);
} else {
return super._getUint64Unchecked(byteOffset, endian);
@@ -735,7 +729,7 @@
void _setInt64Unchecked(int byteOffset, int value,
[Endian endian = Endian.big]) {
final totalOffset = offsetInBytes + byteOffset;
- if (totalOffset % elementSizeInBytes == 0 && endian == Endian.little) {
+ if (totalOffset & 7 == 0 && endian == Endian.little) {
_data.write(totalOffset ~/ elementSizeInBytes, value);
} else {
super._setInt64Unchecked(byteOffset, value, endian);
@@ -746,7 +740,7 @@
void _setUint64Unchecked(int byteOffset, int value,
[Endian endian = Endian.big]) {
final totalOffset = offsetInBytes + byteOffset;
- if (totalOffset % elementSizeInBytes == 0 && endian == Endian.little) {
+ if (totalOffset & 7 == 0 && endian == Endian.little) {
_data.write(totalOffset ~/ elementSizeInBytes, value);
} else {
super._setUint64Unchecked(byteOffset, value, endian);
@@ -781,7 +775,7 @@
byteOffset += offsetInBytes;
final byteIndex = byteOffset ~/ elementSizeInBytes;
final word = floatToIntBits(_data.read(byteIndex));
- return (word >> (8 * (byteOffset % elementSizeInBytes))) & 0xFF;
+ return (word >> (8 * (byteOffset & 3))) & 0xFF;
}
@override
@@ -789,7 +783,7 @@
byteOffset += offsetInBytes;
final byteIndex = byteOffset ~/ elementSizeInBytes;
final element = floatToIntBits(_data.read(byteIndex));
- final byteElementIndex = byteOffset % elementSizeInBytes;
+ final byteElementIndex = byteOffset & 3;
final b1 = byteElementIndex == 0 ? value : (element & 0xFF);
final b2 = byteElementIndex == 1 ? value : ((element >> 8) & 0xFF);
final b3 = byteElementIndex == 2 ? value : ((element >> 16) & 0xFF);
@@ -801,7 +795,7 @@
@override
double _getFloat32Unchecked(int byteOffset, [Endian endian = Endian.big]) {
final totalOffset = offsetInBytes + byteOffset;
- if (totalOffset % elementSizeInBytes == 0 && endian == Endian.little) {
+ if (totalOffset & 3 == 0 && endian == Endian.little) {
return _data.read(totalOffset ~/ elementSizeInBytes);
} else {
return super._getFloat32Unchecked(byteOffset, endian);
@@ -812,7 +806,7 @@
void _setFloat32Unchecked(int byteOffset, double value,
[Endian endian = Endian.big]) {
final totalOffset = offsetInBytes + byteOffset;
- if (totalOffset % elementSizeInBytes == 0 && endian == Endian.little) {
+ if (totalOffset & 3 == 0 && endian == Endian.little) {
_data.write(totalOffset ~/ elementSizeInBytes, value);
} else {
super._setFloat32Unchecked(byteOffset, value, endian);
@@ -847,7 +841,7 @@
byteOffset += offsetInBytes;
final byteIndex = byteOffset ~/ elementSizeInBytes;
final word = doubleToIntBits(_data.read(byteIndex));
- return (word >> (8 * (byteOffset % elementSizeInBytes))) & 0xFF;
+ return (word >> (8 * (byteOffset & 7))) & 0xFF;
}
@override
@@ -855,7 +849,7 @@
byteOffset += offsetInBytes;
final byteIndex = byteOffset ~/ elementSizeInBytes;
final element = doubleToIntBits(_data.read(byteIndex));
- final byteElementIndex = byteOffset % elementSizeInBytes;
+ final byteElementIndex = byteOffset & 7;
final b1 = byteElementIndex == 0 ? value : (element & 0xFF);
final b2 = byteElementIndex == 1 ? value : ((element >> 8) & 0xFF);
final b3 = byteElementIndex == 2 ? value : ((element >> 16) & 0xFF);
@@ -878,7 +872,7 @@
@override
double _getFloat64Unchecked(int byteOffset, [Endian endian = Endian.big]) {
final totalOffset = offsetInBytes + byteOffset;
- if (totalOffset % elementSizeInBytes == 0 && endian == Endian.little) {
+ if (totalOffset & 7 == 0 && endian == Endian.little) {
return _data.read(totalOffset ~/ elementSizeInBytes);
} else {
return super._getFloat64Unchecked(byteOffset, endian);
@@ -889,7 +883,7 @@
void _setFloat64Unchecked(int byteOffset, double value,
[Endian endian = Endian.big]) {
final totalOffset = offsetInBytes + byteOffset;
- if (totalOffset % elementSizeInBytes == 0 && endian == Endian.little) {
+ if (totalOffset & 7 == 0 && endian == Endian.little) {
_data.write(totalOffset ~/ elementSizeInBytes, value);
} else {
super._setFloat64Unchecked(byteOffset, value, endian);
@@ -1799,7 +1793,7 @@
} else if (destDartElementSizeInBytes == 2 &&
destBuffer is _I16ByteBuffer &&
fromBuffer is _I16ByteBuffer) {
- if (fromBufferByteOffset % 2 == 0 && destBufferByteOffset % 2 == 0) {
+ if (fromBufferByteOffset & 1 == 0 && destBufferByteOffset & 1 == 0) {
destBuffer._data.copy(destBufferByteOffset ~/ 2, fromBuffer._data,
fromBufferByteOffset ~/ 2, count);
return;
@@ -1807,7 +1801,7 @@
} else if (destDartElementSizeInBytes == 4 &&
destBuffer is _I32ByteBuffer &&
fromBuffer is _I32ByteBuffer) {
- if (fromBufferByteOffset % 4 == 0 && destBufferByteOffset % 4 == 0) {
+ if (fromBufferByteOffset & 3 == 0 && destBufferByteOffset & 3 == 0) {
destBuffer._data.copy(destBufferByteOffset ~/ 4, fromBuffer._data,
fromBufferByteOffset ~/ 4, count);
return;
@@ -1815,7 +1809,7 @@
} else if (destDartElementSizeInBytes == 8 &&
destBuffer is _I64ByteBuffer &&
fromBuffer is _I64ByteBuffer) {
- if (fromBufferByteOffset % 8 == 0 && destBufferByteOffset % 8 == 0) {
+ if (fromBufferByteOffset & 7 == 0 && destBufferByteOffset & 7 == 0) {
destBuffer._data.copy(destBufferByteOffset ~/ 8, fromBuffer._data,
fromBufferByteOffset ~/ 8, count);
return;
@@ -2179,7 +2173,7 @@
if (destDartElementSizeInBytes == 4 &&
destBuffer is _F32ByteBuffer &&
fromBuffer is _F32ByteBuffer) {
- if (fromBufferByteOffset % 4 == 0 && destBufferByteOffset % 4 == 0) {
+ if (fromBufferByteOffset & 3 == 0 && destBufferByteOffset & 3 == 0) {
destBuffer._data.copy(destBufferByteOffset ~/ 4, fromBuffer._data,
fromBufferByteOffset ~/ 4, count);
return;
@@ -2187,7 +2181,7 @@
} else if (destDartElementSizeInBytes == 8 &&
destBuffer is _F64ByteBuffer &&
fromBuffer is _F64ByteBuffer) {
- if (fromBufferByteOffset % 8 == 0 && destBufferByteOffset % 8 == 0) {
+ if (fromBufferByteOffset & 7 == 0 && destBufferByteOffset & 7 == 0) {
destBuffer._data.copy(destBufferByteOffset ~/ 8, fromBuffer._data,
fromBufferByteOffset ~/ 8, count);
return;