Skip to content

Commit f7cb0fa

Browse files
modulovaluedart-scoped@luci-project-accounts.iam.gserviceaccount.com
authored andcommitted
[vm] Implement Float32x4 and Float64x2 SIMD fallbacks in Dart
Implementing the unoptimized fallbacks in Dart rather than as VM natives makes them easier to maintain and analyze. TEST=lib/typed_data/min_max_edge_cases_test lib/typed_data/float32x4_test lib/typed_data/float32x4_compare_test lib/typed_data/float32x4_clamp_test lib/typed_data/float64x2_functional_test lib/typed_data/float64x2_clamp_test Issue: #64170 Issue: #64248 Change-Id: Ib928e40473f0bf86251b8e4897efdf2b3b01cafc Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/549000 Reviewed-by: Slava Egorov <vegorov@google.com> Commit-Queue: Slava Egorov <vegorov@google.com> Auto-Submit: Modestas Valauskas <valauskasmodestas@gmail.com> Reviewed-by: Martin Kustermann <kustermann@google.com>
1 parent 6caec01 commit f7cb0fa

4 files changed

Lines changed: 122 additions & 458 deletions

File tree

‎runtime/lib/simd128.cc‎

Lines changed: 0 additions & 257 deletions
Original file line numberDiff line numberDiff line change
@@ -11,37 +11,6 @@
1111

1212
namespace dart {
1313

14-
static float IeeeMinF(float a, float b) {
15-
if (isnan(a)) return a;
16-
if (isnan(b)) return b;
17-
float ab = bit_cast<float>(bit_cast<uint32_t>(a) | bit_cast<uint32_t>(b));
18-
if (ab == 0.0f) return ab;
19-
return a < b ? a : b;
20-
}
21-
static float IeeeMaxF(float a, float b) {
22-
if (isnan(a)) return a;
23-
if (isnan(b)) return b;
24-
if (a == 0.0f && b == 0.0f) {
25-
return bit_cast<float>(bit_cast<uint32_t>(a) & bit_cast<uint32_t>(b));
26-
}
27-
return a > b ? a : b;
28-
}
29-
static double IeeeMinD(double a, double b) {
30-
if (isnan(a)) return a;
31-
if (isnan(b)) return b;
32-
double ab = bit_cast<double>(bit_cast<uint64_t>(a) | bit_cast<uint64_t>(b));
33-
if (ab == 0.0) return ab;
34-
return a < b ? a : b;
35-
}
36-
static double IeeeMaxD(double a, double b) {
37-
if (isnan(a)) return a;
38-
if (isnan(b)) return b;
39-
if (a == 0.0 && b == 0.0) {
40-
return bit_cast<double>(bit_cast<uint64_t>(a) & bit_cast<uint64_t>(b));
41-
}
42-
return a > b ? a : b;
43-
}
44-
4514
static void ThrowMaskRangeException(int64_t m) {
4615
if ((m < 0) || (m > 255)) {
4716
Exceptions::ThrowRangeError("mask", Integer::Handle(Integer::New(m)), 0,
@@ -61,38 +30,11 @@ DEFINE_NATIVE_ENTRY(Float32x4_fromDoubles, 0, 4) {
6130
return Float32x4::New(_x, _y, _z, _w);
6231
}
6332

64-
DEFINE_NATIVE_ENTRY(Float32x4_splat, 0, 1) {
65-
GET_NON_NULL_NATIVE_ARGUMENT(Double, v, arguments->NativeArgAt(0));
66-
float _v = v.value();
67-
return Float32x4::New(_v, _v, _v, _v);
68-
}
69-
70-
DEFINE_NATIVE_ENTRY(Float32x4_zero, 0, 0) {
71-
return Float32x4::New(0.0f, 0.0f, 0.0f, 0.0f);
72-
}
73-
7433
DEFINE_NATIVE_ENTRY(Float32x4_fromInt32x4Bits, 0, 1) {
7534
GET_NON_NULL_NATIVE_ARGUMENT(Int32x4, v, arguments->NativeArgAt(0));
7635
return Float32x4::New(v.value());
7736
}
7837

79-
DEFINE_NATIVE_ENTRY(Float32x4_fromFloat64x2, 0, 1) {
80-
GET_NON_NULL_NATIVE_ARGUMENT(Float64x2, v, arguments->NativeArgAt(0));
81-
float _x = static_cast<float>(v.x());
82-
float _y = static_cast<float>(v.y());
83-
return Float32x4::New(_x, _y, 0.0f, 0.0f);
84-
}
85-
86-
DEFINE_NATIVE_ENTRY(Float32x4_add, 0, 2) {
87-
GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
88-
GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, other, arguments->NativeArgAt(1));
89-
float _x = self.x() + other.x();
90-
float _y = self.y() + other.y();
91-
float _z = self.z() + other.z();
92-
float _w = self.w() + other.w();
93-
return Float32x4::New(_x, _y, _z, _w);
94-
}
95-
9638
DEFINE_NATIVE_ENTRY(Float32x4_negate, 0, 1) {
9739
GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
9840
float _x = -self.x();
@@ -102,96 +44,6 @@ DEFINE_NATIVE_ENTRY(Float32x4_negate, 0, 1) {
10244
return Float32x4::New(_x, _y, _z, _w);
10345
}
10446

105-
DEFINE_NATIVE_ENTRY(Float32x4_sub, 0, 2) {
106-
GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
107-
GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, other, arguments->NativeArgAt(1));
108-
float _x = self.x() - other.x();
109-
float _y = self.y() - other.y();
110-
float _z = self.z() - other.z();
111-
float _w = self.w() - other.w();
112-
return Float32x4::New(_x, _y, _z, _w);
113-
}
114-
115-
DEFINE_NATIVE_ENTRY(Float32x4_mul, 0, 2) {
116-
GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
117-
GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, other, arguments->NativeArgAt(1));
118-
float _x = self.x() * other.x();
119-
float _y = self.y() * other.y();
120-
float _z = self.z() * other.z();
121-
float _w = self.w() * other.w();
122-
return Float32x4::New(_x, _y, _z, _w);
123-
}
124-
125-
DEFINE_NATIVE_ENTRY(Float32x4_div, 0, 2) {
126-
GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
127-
GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, other, arguments->NativeArgAt(1));
128-
float _x = Utils::DivideAllowZero(self.x(), other.x());
129-
float _y = Utils::DivideAllowZero(self.y(), other.y());
130-
float _z = Utils::DivideAllowZero(self.z(), other.z());
131-
float _w = Utils::DivideAllowZero(self.w(), other.w());
132-
return Float32x4::New(_x, _y, _z, _w);
133-
}
134-
135-
DEFINE_NATIVE_ENTRY(Float32x4_cmplt, 0, 2) {
136-
GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, a, arguments->NativeArgAt(0));
137-
GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, b, arguments->NativeArgAt(1));
138-
uint32_t _x = a.x() < b.x() ? 0xFFFFFFFF : 0x0;
139-
uint32_t _y = a.y() < b.y() ? 0xFFFFFFFF : 0x0;
140-
uint32_t _z = a.z() < b.z() ? 0xFFFFFFFF : 0x0;
141-
uint32_t _w = a.w() < b.w() ? 0xFFFFFFFF : 0x0;
142-
return Int32x4::New(_x, _y, _z, _w);
143-
}
144-
145-
DEFINE_NATIVE_ENTRY(Float32x4_cmplte, 0, 2) {
146-
GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, a, arguments->NativeArgAt(0));
147-
GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, b, arguments->NativeArgAt(1));
148-
uint32_t _x = a.x() <= b.x() ? 0xFFFFFFFF : 0x0;
149-
uint32_t _y = a.y() <= b.y() ? 0xFFFFFFFF : 0x0;
150-
uint32_t _z = a.z() <= b.z() ? 0xFFFFFFFF : 0x0;
151-
uint32_t _w = a.w() <= b.w() ? 0xFFFFFFFF : 0x0;
152-
return Int32x4::New(_x, _y, _z, _w);
153-
}
154-
155-
DEFINE_NATIVE_ENTRY(Float32x4_cmpgt, 0, 2) {
156-
GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, a, arguments->NativeArgAt(0));
157-
GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, b, arguments->NativeArgAt(1));
158-
uint32_t _x = a.x() > b.x() ? 0xFFFFFFFF : 0x0;
159-
uint32_t _y = a.y() > b.y() ? 0xFFFFFFFF : 0x0;
160-
uint32_t _z = a.z() > b.z() ? 0xFFFFFFFF : 0x0;
161-
uint32_t _w = a.w() > b.w() ? 0xFFFFFFFF : 0x0;
162-
return Int32x4::New(_x, _y, _z, _w);
163-
}
164-
165-
DEFINE_NATIVE_ENTRY(Float32x4_cmpgte, 0, 2) {
166-
GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, a, arguments->NativeArgAt(0));
167-
GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, b, arguments->NativeArgAt(1));
168-
uint32_t _x = a.x() >= b.x() ? 0xFFFFFFFF : 0x0;
169-
uint32_t _y = a.y() >= b.y() ? 0xFFFFFFFF : 0x0;
170-
uint32_t _z = a.z() >= b.z() ? 0xFFFFFFFF : 0x0;
171-
uint32_t _w = a.w() >= b.w() ? 0xFFFFFFFF : 0x0;
172-
return Int32x4::New(_x, _y, _z, _w);
173-
}
174-
175-
DEFINE_NATIVE_ENTRY(Float32x4_cmpequal, 0, 2) {
176-
GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, a, arguments->NativeArgAt(0));
177-
GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, b, arguments->NativeArgAt(1));
178-
uint32_t _x = a.x() == b.x() ? 0xFFFFFFFF : 0x0;
179-
uint32_t _y = a.y() == b.y() ? 0xFFFFFFFF : 0x0;
180-
uint32_t _z = a.z() == b.z() ? 0xFFFFFFFF : 0x0;
181-
uint32_t _w = a.w() == b.w() ? 0xFFFFFFFF : 0x0;
182-
return Int32x4::New(_x, _y, _z, _w);
183-
}
184-
185-
DEFINE_NATIVE_ENTRY(Float32x4_cmpnequal, 0, 2) {
186-
GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, a, arguments->NativeArgAt(0));
187-
GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, b, arguments->NativeArgAt(1));
188-
uint32_t _x = a.x() != b.x() ? 0xFFFFFFFF : 0x0;
189-
uint32_t _y = a.y() != b.y() ? 0xFFFFFFFF : 0x0;
190-
uint32_t _z = a.z() != b.z() ? 0xFFFFFFFF : 0x0;
191-
uint32_t _w = a.w() != b.w() ? 0xFFFFFFFF : 0x0;
192-
return Int32x4::New(_x, _y, _z, _w);
193-
}
194-
19547
DEFINE_NATIVE_ENTRY(Float32x4_scale, 0, 2) {
19648
GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
19749
GET_NON_NULL_NATIVE_ARGUMENT(Double, scale, arguments->NativeArgAt(1));
@@ -381,35 +233,6 @@ DEFINE_NATIVE_ENTRY(Float32x4_setW, 0, 2) {
381233
return Float32x4::New(_x, _y, _z, _w);
382234
}
383235

384-
DEFINE_NATIVE_ENTRY(Float32x4_min, 0, 2) {
385-
GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
386-
GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, other, arguments->NativeArgAt(1));
387-
float _x = IeeeMinF(self.x(), other.x());
388-
float _y = IeeeMinF(self.y(), other.y());
389-
float _z = IeeeMinF(self.z(), other.z());
390-
float _w = IeeeMinF(self.w(), other.w());
391-
return Float32x4::New(_x, _y, _z, _w);
392-
}
393-
394-
DEFINE_NATIVE_ENTRY(Float32x4_max, 0, 2) {
395-
GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
396-
GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, other, arguments->NativeArgAt(1));
397-
float _x = IeeeMaxF(self.x(), other.x());
398-
float _y = IeeeMaxF(self.y(), other.y());
399-
float _z = IeeeMaxF(self.z(), other.z());
400-
float _w = IeeeMaxF(self.w(), other.w());
401-
return Float32x4::New(_x, _y, _z, _w);
402-
}
403-
404-
DEFINE_NATIVE_ENTRY(Float32x4_sqrt, 0, 1) {
405-
GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
406-
float _x = sqrtf(self.x());
407-
float _y = sqrtf(self.y());
408-
float _z = sqrtf(self.z());
409-
float _w = sqrtf(self.w());
410-
return Float32x4::New(_x, _y, _z, _w);
411-
}
412-
413236
DEFINE_NATIVE_ENTRY(Float32x4_reciprocal, 0, 1) {
414237
GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
415238
float _x = Utils::DivideAllowZero(1.0f, self.x());
@@ -509,70 +332,13 @@ DEFINE_NATIVE_ENTRY(Float64x2_fromDoubles, 0, 2) {
509332
return Float64x2::New(x.value(), y.value());
510333
}
511334

512-
DEFINE_NATIVE_ENTRY(Float64x2_splat, 0, 1) {
513-
GET_NON_NULL_NATIVE_ARGUMENT(Double, v, arguments->NativeArgAt(0));
514-
return Float64x2::New(v.value(), v.value());
515-
}
516-
517-
DEFINE_NATIVE_ENTRY(Float64x2_zero, 0, 0) {
518-
return Float64x2::New(0.0, 0.0);
519-
}
520-
521335
DEFINE_NATIVE_ENTRY(Float64x2_fromFloat32x4, 0, 1) {
522336
GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, v, arguments->NativeArgAt(0));
523337
double _x = v.x();
524338
double _y = v.y();
525339
return Float64x2::New(_x, _y);
526340
}
527341

528-
DEFINE_NATIVE_ENTRY(Float64x2_add, 0, 2) {
529-
GET_NON_NULL_NATIVE_ARGUMENT(Float64x2, self, arguments->NativeArgAt(0));
530-
GET_NON_NULL_NATIVE_ARGUMENT(Float64x2, other, arguments->NativeArgAt(1));
531-
double _x = self.x() + other.x();
532-
double _y = self.y() + other.y();
533-
return Float64x2::New(_x, _y);
534-
}
535-
536-
DEFINE_NATIVE_ENTRY(Float64x2_negate, 0, 1) {
537-
GET_NON_NULL_NATIVE_ARGUMENT(Float64x2, self, arguments->NativeArgAt(0));
538-
double _x = -self.x();
539-
double _y = -self.y();
540-
return Float64x2::New(_x, _y);
541-
}
542-
543-
DEFINE_NATIVE_ENTRY(Float64x2_sub, 0, 2) {
544-
GET_NON_NULL_NATIVE_ARGUMENT(Float64x2, self, arguments->NativeArgAt(0));
545-
GET_NON_NULL_NATIVE_ARGUMENT(Float64x2, other, arguments->NativeArgAt(1));
546-
double _x = self.x() - other.x();
547-
double _y = self.y() - other.y();
548-
return Float64x2::New(_x, _y);
549-
}
550-
551-
DEFINE_NATIVE_ENTRY(Float64x2_mul, 0, 2) {
552-
GET_NON_NULL_NATIVE_ARGUMENT(Float64x2, self, arguments->NativeArgAt(0));
553-
GET_NON_NULL_NATIVE_ARGUMENT(Float64x2, other, arguments->NativeArgAt(1));
554-
double _x = self.x() * other.x();
555-
double _y = self.y() * other.y();
556-
return Float64x2::New(_x, _y);
557-
}
558-
559-
DEFINE_NATIVE_ENTRY(Float64x2_div, 0, 2) {
560-
GET_NON_NULL_NATIVE_ARGUMENT(Float64x2, self, arguments->NativeArgAt(0));
561-
GET_NON_NULL_NATIVE_ARGUMENT(Float64x2, other, arguments->NativeArgAt(1));
562-
double _x = Utils::DivideAllowZero(self.x(), other.x());
563-
double _y = Utils::DivideAllowZero(self.y(), other.y());
564-
return Float64x2::New(_x, _y);
565-
}
566-
567-
DEFINE_NATIVE_ENTRY(Float64x2_scale, 0, 2) {
568-
GET_NON_NULL_NATIVE_ARGUMENT(Float64x2, self, arguments->NativeArgAt(0));
569-
GET_NON_NULL_NATIVE_ARGUMENT(Double, scale, arguments->NativeArgAt(1));
570-
double _s = scale.value();
571-
double _x = self.x() * _s;
572-
double _y = self.y() * _s;
573-
return Float64x2::New(_x, _y);
574-
}
575-
576342
DEFINE_NATIVE_ENTRY(Float64x2_abs, 0, 1) {
577343
GET_NON_NULL_NATIVE_ARGUMENT(Float64x2, self, arguments->NativeArgAt(0));
578344
double _x = fabs(self.x());
@@ -664,27 +430,4 @@ DEFINE_NATIVE_ENTRY(Float64x2_setY, 0, 2) {
664430
return Float64x2::New(_x, _y);
665431
}
666432

667-
DEFINE_NATIVE_ENTRY(Float64x2_min, 0, 2) {
668-
GET_NON_NULL_NATIVE_ARGUMENT(Float64x2, self, arguments->NativeArgAt(0));
669-
GET_NON_NULL_NATIVE_ARGUMENT(Float64x2, other, arguments->NativeArgAt(1));
670-
double _x = IeeeMinD(self.x(), other.x());
671-
double _y = IeeeMinD(self.y(), other.y());
672-
return Float64x2::New(_x, _y);
673-
}
674-
675-
DEFINE_NATIVE_ENTRY(Float64x2_max, 0, 2) {
676-
GET_NON_NULL_NATIVE_ARGUMENT(Float64x2, self, arguments->NativeArgAt(0));
677-
GET_NON_NULL_NATIVE_ARGUMENT(Float64x2, other, arguments->NativeArgAt(1));
678-
double _x = IeeeMaxD(self.x(), other.x());
679-
double _y = IeeeMaxD(self.y(), other.y());
680-
return Float64x2::New(_x, _y);
681-
}
682-
683-
DEFINE_NATIVE_ENTRY(Float64x2_sqrt, 0, 1) {
684-
GET_NON_NULL_NATIVE_ARGUMENT(Float64x2, self, arguments->NativeArgAt(0));
685-
double _x = sqrt(self.x());
686-
double _y = sqrt(self.y());
687-
return Float64x2::New(_x, _y);
688-
}
689-
690433
} // namespace dart

‎runtime/vm/bootstrap_natives.h‎

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -169,21 +169,8 @@ namespace dart {
169169
V(TypedDataView_offsetInBytes, 1) \
170170
V(TypedDataView_typedData, 1) \
171171
V(Float32x4_fromDoubles, 4) \
172-
V(Float32x4_splat, 1) \
173172
V(Float32x4_fromInt32x4Bits, 1) \
174-
V(Float32x4_fromFloat64x2, 1) \
175-
V(Float32x4_zero, 0) \
176-
V(Float32x4_add, 2) \
177173
V(Float32x4_negate, 1) \
178-
V(Float32x4_sub, 2) \
179-
V(Float32x4_mul, 2) \
180-
V(Float32x4_div, 2) \
181-
V(Float32x4_cmplt, 2) \
182-
V(Float32x4_cmplte, 2) \
183-
V(Float32x4_cmpgt, 2) \
184-
V(Float32x4_cmpgte, 2) \
185-
V(Float32x4_cmpequal, 2) \
186-
V(Float32x4_cmpnequal, 2) \
187174
V(Float32x4_scale, 2) \
188175
V(Float32x4_abs, 1) \
189176
V(Float32x4_clamp, 3) \
@@ -198,31 +185,17 @@ namespace dart {
198185
V(Float32x4_setY, 2) \
199186
V(Float32x4_setZ, 2) \
200187
V(Float32x4_setW, 2) \
201-
V(Float32x4_min, 2) \
202-
V(Float32x4_max, 2) \
203-
V(Float32x4_sqrt, 1) \
204188
V(Float32x4_reciprocal, 1) \
205189
V(Float32x4_reciprocalSqrt, 1) \
206190
V(Float64x2_fromDoubles, 2) \
207-
V(Float64x2_splat, 1) \
208-
V(Float64x2_zero, 0) \
209191
V(Float64x2_fromFloat32x4, 1) \
210-
V(Float64x2_add, 2) \
211-
V(Float64x2_negate, 1) \
212-
V(Float64x2_sub, 2) \
213-
V(Float64x2_mul, 2) \
214-
V(Float64x2_div, 2) \
215-
V(Float64x2_scale, 2) \
216192
V(Float64x2_abs, 1) \
217193
V(Float64x2_clamp, 3) \
218194
V(Float64x2_getX, 1) \
219195
V(Float64x2_getY, 1) \
220196
V(Float64x2_getSignMask, 1) \
221197
V(Float64x2_setX, 2) \
222198
V(Float64x2_setY, 2) \
223-
V(Float64x2_min, 2) \
224-
V(Float64x2_max, 2) \
225-
V(Float64x2_sqrt, 1) \
226199
V(Int32x4_fromInts, 4) \
227200
V(Int32x4_select, 3) \
228201
V(Int32x4_fromFloat32x4Bits, 1) \

0 commit comments

Comments
 (0)