SIMD shuffle API changes

R=srdjan@google.com, zra@google.com

Review URL: https://codereview.chromium.org//51373004

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@29723 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
johnmccutchan@google.com 2013-11-01 07:09:54 +00:00
parent 6179df0ad5
commit 5f63715d47
21 changed files with 1061 additions and 417 deletions

View file

@ -11,6 +11,18 @@
namespace dart {
static void ThrowMaskRangeException(int64_t m) {
if ((m < 0) || (m > 255)) {
const String& error = String::Handle(
String::NewFormatted("mask (%" Pd64 ") must be in the range [0..256)",
m));
const Array& args = Array::Handle(Array::New(1));
args.SetAt(0, error);
Exceptions::ThrowByType(Exceptions::kRange, args);
}
}
DEFINE_NATIVE_ENTRY(Float32x4_fromDoubles, 5) {
ASSERT(AbstractTypeArguments::CheckedHandle(
arguments->NativeArgAt(0)).IsNull());
@ -263,14 +275,7 @@ DEFINE_NATIVE_ENTRY(Float32x4_shuffle, 2) {
GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
GET_NON_NULL_NATIVE_ARGUMENT(Integer, mask, arguments->NativeArgAt(1));
int64_t m = mask.AsInt64Value();
if (m < 0 || m > 255) {
const String& error = String::Handle(
String::NewFormatted("mask (%" Pd64 ") must be in the range [0..256)",
m));
const Array& args = Array::Handle(Array::New(1));
args.SetAt(0, error);
Exceptions::ThrowByType(Exceptions::kRange, args);
}
ThrowMaskRangeException(m);
float data[4] = { self.x(), self.y(), self.z(), self.w() };
float _x = data[m & 0x3];
float _y = data[(m >> 2) & 0x3];
@ -280,57 +285,18 @@ DEFINE_NATIVE_ENTRY(Float32x4_shuffle, 2) {
}
DEFINE_NATIVE_ENTRY(Float32x4_withZWInXY, 2) {
DEFINE_NATIVE_ENTRY(Float32x4_shuffleMix, 3) {
GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, other, arguments->NativeArgAt(1));
float _x = other.z();
float _y = other.w();
float _z = self.z();
float _w = self.w();
return Float32x4::New(_x, _y, _z, _w);
}
DEFINE_NATIVE_ENTRY(Float32x4_interleaveXY, 2) {
GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, other, arguments->NativeArgAt(1));
float _x = self.x();
float _y = other.x();
float _z = self.y();
float _w = other.y();
return Float32x4::New(_x, _y, _z, _w);
}
DEFINE_NATIVE_ENTRY(Float32x4_interleaveZW, 2) {
GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, other, arguments->NativeArgAt(1));
float _x = self.z();
float _y = other.z();
float _z = self.w();
float _w = other.w();
return Float32x4::New(_x, _y, _z, _w);
}
DEFINE_NATIVE_ENTRY(Float32x4_interleaveXYPairs, 2) {
GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, other, arguments->NativeArgAt(1));
float _x = self.x();
float _y = self.y();
float _z = other.x();
float _w = other.y();
return Float32x4::New(_x, _y, _z, _w);
}
DEFINE_NATIVE_ENTRY(Float32x4_interleaveZWPairs, 2) {
GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, other, arguments->NativeArgAt(1));
float _x = self.z();
float _y = self.w();
float _z = other.z();
float _w = other.w();
GET_NON_NULL_NATIVE_ARGUMENT(Integer, mask, arguments->NativeArgAt(2));
int64_t m = mask.AsInt64Value();
ThrowMaskRangeException(m);
float data[4] = { self.x(), self.y(), self.z(), self.w() };
float other_data[4] = { other.x(), other.y(), other.z(), other.w() };
float _x = data[m & 0x3];
float _y = data[(m >> 2) & 0x3];
float _z = other_data[(m >> 4) & 0x3];
float _w = other_data[(m >> 6) & 0x3];
return Float32x4::New(_x, _y, _z, _w);
}
@ -552,6 +518,36 @@ DEFINE_NATIVE_ENTRY(Uint32x4_getW, 1) {
}
DEFINE_NATIVE_ENTRY(Uint32x4_shuffle, 2) {
GET_NON_NULL_NATIVE_ARGUMENT(Uint32x4, self, arguments->NativeArgAt(0));
GET_NON_NULL_NATIVE_ARGUMENT(Integer, mask, arguments->NativeArgAt(1));
int64_t m = mask.AsInt64Value();
ThrowMaskRangeException(m);
uint32_t data[4] = { self.x(), self.y(), self.z(), self.w() };
uint32_t _x = data[m & 0x3];
uint32_t _y = data[(m >> 2) & 0x3];
uint32_t _z = data[(m >> 4) & 0x3];
uint32_t _w = data[(m >> 6) & 0x3];
return Uint32x4::New(_x, _y, _z, _w);
}
DEFINE_NATIVE_ENTRY(Uint32x4_shuffleMix, 3) {
GET_NON_NULL_NATIVE_ARGUMENT(Uint32x4, self, arguments->NativeArgAt(0));
GET_NON_NULL_NATIVE_ARGUMENT(Uint32x4, zw, arguments->NativeArgAt(1));
GET_NON_NULL_NATIVE_ARGUMENT(Integer, mask, arguments->NativeArgAt(2));
int64_t m = mask.AsInt64Value();
ThrowMaskRangeException(m);
uint32_t data[4] = { self.x(), self.y(), self.z(), self.w() };
uint32_t zw_data[4] = { zw.x(), zw.y(), zw.z(), zw.w() };
uint32_t _x = data[m & 0x3];
uint32_t _y = data[(m >> 2) & 0x3];
uint32_t _z = zw_data[(m >> 4) & 0x3];
uint32_t _w = zw_data[(m >> 6) & 0x3];
return Uint32x4::New(_x, _y, _z, _w);
}
DEFINE_NATIVE_ENTRY(Uint32x4_setX, 2) {
GET_NON_NULL_NATIVE_ARGUMENT(Uint32x4, self, arguments->NativeArgAt(0));
GET_NON_NULL_NATIVE_ARGUMENT(Integer, x, arguments->NativeArgAt(1));

View file

@ -2168,14 +2168,7 @@ class _Float32x4 implements Float32x4 {
int get signMask native "Float32x4_getSignMask";
Float32x4 shuffle(int mask) native "Float32x4_shuffle";
Float32x4 withZWInXY(Float32x4 other) native "Float32x4_withZWInXY";
Float32x4 interleaveXY(Float32x4 other) native "Float32x4_interleaveXY";
Float32x4 interleaveZW(Float32x4 other) native "Float32x4_interleaveZW";
Float32x4 interleaveXYPairs(Float32x4 other)
native "Float32x4_interleaveXYPairs";
Float32x4 interleaveZWPairs(Float32x4 other)
native "Float32x4_interleaveZWPairs";
Float32x4 shuffleMix(Float32x4 zw, int mask) native "Float32x4_shuffleMix";
Float32x4 withX(double x) native "Float32x4_setX";
Float32x4 withY(double y) native "Float32x4_setY";
@ -2236,6 +2229,8 @@ class _Uint32x4 implements Uint32x4 {
int get z native "Uint32x4_getZ";
int get w native "Uint32x4_getW";
int get signMask native "Uint32x4_getSignMask";
Uint32x4 shuffle(int mask) native "Uint32x4_shuffle";
Uint32x4 shuffleMix(Uint32x4 zw, int mask) native "Uint32x4_shuffleMix";
Uint32x4 withX(int x) native "Uint32x4_setX";
Uint32x4 withY(int y) native "Uint32x4_setY";
Uint32x4 withZ(int z) native "Uint32x4_setZ";

View file

@ -216,11 +216,7 @@ namespace dart {
V(Float32x4_getW, 1) \
V(Float32x4_getSignMask, 1) \
V(Float32x4_shuffle, 2) \
V(Float32x4_withZWInXY, 2) \
V(Float32x4_interleaveXY, 2) \
V(Float32x4_interleaveZW, 2) \
V(Float32x4_interleaveXYPairs, 2) \
V(Float32x4_interleaveZWPairs, 2) \
V(Float32x4_shuffleMix, 3) \
V(Float32x4_setX, 2) \
V(Float32x4_setY, 2) \
V(Float32x4_setZ, 2) \
@ -247,6 +243,8 @@ namespace dart {
V(Uint32x4_setZ, 2) \
V(Uint32x4_setW, 2) \
V(Uint32x4_getSignMask, 1) \
V(Uint32x4_shuffle, 2) \
V(Uint32x4_shuffleMix, 3) \
V(Uint32x4_getFlagX, 1) \
V(Uint32x4_getFlagY, 1) \
V(Uint32x4_getFlagZ, 1) \

View file

@ -1692,24 +1692,30 @@ bool FlowGraphOptimizer::InlineFloat32x4Getter(InstanceCallInstr* call,
call->env(),
call);
intptr_t mask = 0;
if (getter == MethodRecognizer::kFloat32x4Shuffle) {
if ((getter == MethodRecognizer::kFloat32x4Shuffle) ||
(getter == MethodRecognizer::kFloat32x4ShuffleMix)) {
// Extract shuffle mask.
ASSERT(call->ArgumentCount() == 2);
Definition* mask_definition = call->ArgumentAt(1);
Definition* mask_definition = NULL;
if (getter == MethodRecognizer::kFloat32x4Shuffle) {
ASSERT(call->ArgumentCount() == 2);
mask_definition = call->ArgumentAt(1);
} else {
ASSERT(getter == MethodRecognizer::kFloat32x4ShuffleMix);
ASSERT(call->ArgumentCount() == 3);
mask_definition = call->ArgumentAt(2);
}
if (!mask_definition->IsConstant()) {
// Not a constant.
return false;
}
ASSERT(mask_definition->IsConstant());
ConstantInstr* constant_instruction = mask_definition->AsConstant();
const Object& constant_mask = constant_instruction->value();
if (!constant_mask.IsSmi()) {
// Not a smi.
return false;
}
ASSERT(constant_mask.IsSmi());
mask = Smi::Cast(constant_mask).Value();
if (mask < 0 || mask > 255) {
if ((mask < 0) || (mask > 255)) {
// Not a valid mask.
return false;
}
@ -1721,13 +1727,22 @@ bool FlowGraphOptimizer::InlineFloat32x4Getter(InstanceCallInstr* call,
call->deopt_id());
ReplaceCall(call, instr);
return true;
} else if (getter == MethodRecognizer::kFloat32x4ShuffleMix) {
Simd32x4ShuffleMixInstr* instr = new Simd32x4ShuffleMixInstr(
getter,
new Value(call->ArgumentAt(0)),
new Value(call->ArgumentAt(1)),
mask,
call->deopt_id());
ReplaceCall(call, instr);
return true;
} else {
ASSERT((getter == MethodRecognizer::kFloat32x4Shuffle) ||
(getter == MethodRecognizer::kFloat32x4ShuffleX) ||
(getter == MethodRecognizer::kFloat32x4ShuffleY) ||
(getter == MethodRecognizer::kFloat32x4ShuffleZ) ||
(getter == MethodRecognizer::kFloat32x4ShuffleW));
Float32x4ShuffleInstr* instr = new Float32x4ShuffleInstr(
Simd32x4ShuffleInstr* instr = new Simd32x4ShuffleInstr(
getter,
new Value(call->ArgumentAt(0)),
mask,
@ -1751,6 +1766,35 @@ bool FlowGraphOptimizer::InlineUint32x4Getter(InstanceCallInstr* call,
call->deopt_id(),
call->env(),
call);
intptr_t mask = 0;
if ((getter == MethodRecognizer::kUint32x4Shuffle) ||
(getter == MethodRecognizer::kUint32x4ShuffleMix)) {
// Extract shuffle mask.
Definition* mask_definition = NULL;
if (getter == MethodRecognizer::kUint32x4Shuffle) {
ASSERT(call->ArgumentCount() == 2);
mask_definition = call->ArgumentAt(1);
} else {
ASSERT(getter == MethodRecognizer::kUint32x4ShuffleMix);
ASSERT(call->ArgumentCount() == 3);
mask_definition = call->ArgumentAt(2);
}
if (!mask_definition->IsConstant()) {
return false;
}
ASSERT(mask_definition->IsConstant());
ConstantInstr* constant_instruction = mask_definition->AsConstant();
const Object& constant_mask = constant_instruction->value();
if (!constant_mask.IsSmi()) {
return false;
}
ASSERT(constant_mask.IsSmi());
mask = Smi::Cast(constant_mask).Value();
if ((mask < 0) || (mask > 255)) {
// Not a valid mask.
return false;
}
}
if (getter == MethodRecognizer::kUint32x4GetSignMask) {
Simd32x4GetSignMaskInstr* instr = new Simd32x4GetSignMaskInstr(
getter,
@ -1758,6 +1802,23 @@ bool FlowGraphOptimizer::InlineUint32x4Getter(InstanceCallInstr* call,
call->deopt_id());
ReplaceCall(call, instr);
return true;
} else if (getter == MethodRecognizer::kUint32x4ShuffleMix) {
Simd32x4ShuffleMixInstr* instr = new Simd32x4ShuffleMixInstr(
getter,
new Value(call->ArgumentAt(0)),
new Value(call->ArgumentAt(1)),
mask,
call->deopt_id());
ReplaceCall(call, instr);
return true;
} else if (getter == MethodRecognizer::kUint32x4Shuffle) {
Simd32x4ShuffleInstr* instr = new Simd32x4ShuffleInstr(
getter,
new Value(call->ArgumentAt(0)),
mask,
call->deopt_id());
ReplaceCall(call, instr);
return true;
} else {
Uint32x4GetFlagInstr* instr = new Uint32x4GetFlagInstr(
getter,
@ -2320,26 +2381,6 @@ bool FlowGraphOptimizer::TryInlineFloat32x4Method(
ReplaceCall(call, minmax);
return true;
}
case MethodRecognizer::kFloat32x4WithZWInXY:
case MethodRecognizer::kFloat32x4InterleaveXY:
case MethodRecognizer::kFloat32x4InterleaveZW:
case MethodRecognizer::kFloat32x4InterleaveXYPairs:
case MethodRecognizer::kFloat32x4InterleaveZWPairs: {
Definition* left = call->ArgumentAt(0);
Definition* right = call->ArgumentAt(1);
// Type check left.
AddCheckClass(left,
ICData::ZoneHandle(
call->ic_data()->AsUnaryClassChecksForArgNr(0)),
call->deopt_id(),
call->env(),
call);
Float32x4TwoArgShuffleInstr* two_arg_shuffle =
new Float32x4TwoArgShuffleInstr(recognized_kind, new Value(left),
new Value(right), call->deopt_id());
ReplaceCall(call, two_arg_shuffle);
return true;
}
case MethodRecognizer::kFloat32x4Scale: {
Definition* left = call->ArgumentAt(0);
Definition* right = call->ArgumentAt(1);
@ -2429,6 +2470,7 @@ bool FlowGraphOptimizer::TryInlineFloat32x4Method(
ReplaceCall(call, clamp);
return true;
}
case MethodRecognizer::kFloat32x4ShuffleMix:
case MethodRecognizer::kFloat32x4Shuffle: {
return InlineFloat32x4Getter(call, recognized_kind);
}
@ -2446,6 +2488,8 @@ bool FlowGraphOptimizer::TryInlineUint32x4Method(
}
ASSERT(call->HasICData());
switch (recognized_kind) {
case MethodRecognizer::kUint32x4ShuffleMix:
case MethodRecognizer::kUint32x4Shuffle:
case MethodRecognizer::kUint32x4GetFlagX:
case MethodRecognizer::kUint32x4GetFlagY:
case MethodRecognizer::kUint32x4GetFlagZ:
@ -6885,7 +6929,13 @@ void ConstantPropagator::VisitFloat32x4Constructor(
}
void ConstantPropagator::VisitFloat32x4Shuffle(Float32x4ShuffleInstr* instr) {
void ConstantPropagator::VisitSimd32x4Shuffle(Simd32x4ShuffleInstr* instr) {
SetValue(instr, non_constant_);
}
void ConstantPropagator::VisitSimd32x4ShuffleMix(
Simd32x4ShuffleMixInstr* instr) {
SetValue(instr, non_constant_);
}
@ -6948,12 +6998,6 @@ void ConstantPropagator::VisitFloat32x4ToUint32x4(
}
void ConstantPropagator::VisitFloat32x4TwoArgShuffle(
Float32x4TwoArgShuffleInstr* instr) {
SetValue(instr, non_constant_);
}
void ConstantPropagator::VisitUint32x4BoolConstructor(
Uint32x4BoolConstructorInstr* instr) {
SetValue(instr, non_constant_);

View file

@ -1049,13 +1049,26 @@ CompileType BinaryFloat32x4OpInstr::ComputeType() const {
}
CompileType Float32x4ShuffleInstr::ComputeType() const {
CompileType Simd32x4ShuffleInstr::ComputeType() const {
if ((op_kind() == MethodRecognizer::kFloat32x4ShuffleX) ||
(op_kind() == MethodRecognizer::kFloat32x4ShuffleY) ||
(op_kind() == MethodRecognizer::kFloat32x4ShuffleZ) ||
(op_kind() == MethodRecognizer::kFloat32x4ShuffleW)) {
return CompileType::FromCid(kDoubleCid);
}
if ((op_kind() == MethodRecognizer::kUint32x4Shuffle)) {
return CompileType::FromCid(kUint32x4Cid);
}
ASSERT((op_kind() == MethodRecognizer::kFloat32x4Shuffle));
return CompileType::FromCid(kFloat32x4Cid);
}
CompileType Simd32x4ShuffleMixInstr::ComputeType() const {
if (op_kind() == MethodRecognizer::kUint32x4ShuffleMix) {
return CompileType::FromCid(kUint32x4Cid);
}
ASSERT((op_kind() == MethodRecognizer::kFloat32x4ShuffleMix));
return CompileType::FromCid(kFloat32x4Cid);
}
@ -1120,11 +1133,6 @@ CompileType Float32x4ToUint32x4Instr::ComputeType() const {
}
CompileType Float32x4TwoArgShuffleInstr::ComputeType() const {
return CompileType::FromCid(kFloat32x4Cid);
}
CompileType Uint32x4BoolConstructorInstr::ComputeType() const {
return CompileType::FromCid(kUint32x4Cid);
}

View file

@ -607,12 +607,19 @@ void BinaryFloat32x4OpInstr::PrintOperandsTo(BufferFormatter* f) const {
}
void Float32x4ShuffleInstr::PrintOperandsTo(BufferFormatter* f) const {
void Simd32x4ShuffleInstr::PrintOperandsTo(BufferFormatter* f) const {
// TODO(johnmccutchan): Add proper string enumeration of shuffle.
f->Print("SHUFFLE ");
f->Print("%s, ", MethodRecognizer::KindToCString(op_kind()));
value()->PrintTo(f);
}
void Simd32x4ShuffleMixInstr::PrintOperandsTo(BufferFormatter* f) const {
f->Print("%s, ", MethodRecognizer::KindToCString(op_kind()));
xy()->PrintTo(f);
f->Print(", ");
zw()->PrintTo(f);
}
void Simd32x4GetSignMaskInstr::PrintOperandsTo(BufferFormatter* f) const {
if (op_kind() == MethodRecognizer::kFloat32x4GetSignMask) {
@ -706,12 +713,7 @@ void Float32x4ToUint32x4Instr::PrintOperandsTo(BufferFormatter* f) const {
}
void Float32x4TwoArgShuffleInstr::PrintOperandsTo(BufferFormatter* f) const {
f->Print("%s, ", MethodRecognizer::KindToCString(op_kind()));
left()->PrintTo(f);
f->Print(", ");
right()->PrintTo(f);
}
void Uint32x4BoolConstructorInstr::PrintOperandsTo(BufferFormatter* f) const {

View file

@ -95,6 +95,7 @@ class Range;
V(Float32x4, Float32x4.fromUint32x4Bits, Float32x4FromUint32x4Bits, \
770033146) \
V(_Float32x4, shuffle, Float32x4Shuffle, 1178727105) \
V(_Float32x4, shuffleMix, Float32x4ShuffleMix, 927956119) \
V(_Float32x4, get:x, Float32x4ShuffleX, 1351717838) \
V(_Float32x4, get:y, Float32x4ShuffleY, 217386410) \
V(_Float32x4, get:z, Float32x4ShuffleZ, 2144923721) \
@ -119,11 +120,6 @@ class Range;
V(_Float32x4, withY, Float32x4WithY, 1806065938) \
V(_Float32x4, withZ, Float32x4WithZ, 320659034) \
V(_Float32x4, withW, Float32x4WithW, 1108437255) \
V(_Float32x4, withZWInXY, Float32x4WithZWInXY, 1198101679) \
V(_Float32x4, interleaveXY, Float32x4InterleaveXY, 2001324072) \
V(_Float32x4, interleaveZW, Float32x4InterleaveZW, 928280031) \
V(_Float32x4, interleaveXYPairs, Float32x4InterleaveXYPairs, 1046078993) \
V(_Float32x4, interleaveZWPairs, Float32x4InterleaveZWPairs, 1001751955) \
V(Uint32x4, Uint32x4.bool, Uint32x4BoolConstructor, 517444095) \
V(Uint32x4, Uint32x4.fromFloat32x4Bits, Uint32x4FromFloat32x4Bits, \
1080034855) \
@ -132,6 +128,8 @@ class Range;
V(_Uint32x4, get:flagZ, Uint32x4GetFlagZ, 944733935) \
V(_Uint32x4, get:flagW, Uint32x4GetFlagW, 22746169) \
V(_Uint32x4, get:signMask, Uint32x4GetSignMask, 1858144083) \
V(_Uint32x4, shuffle, Uint32x4Shuffle, 146209630) \
V(_Uint32x4, shuffleMix, Uint32x4ShuffleMix, 1251494596) \
V(_Uint32x4, select, Uint32x4Select, 72244182) \
V(_Uint32x4, withFlagX, Uint32x4WithFlagX, 1475542073) \
V(_Uint32x4, withFlagY, Uint32x4WithFlagY, 830610988) \
@ -677,7 +675,8 @@ class EmbeddedArray<T, 0> {
M(GuardField) \
M(IfThenElse) \
M(BinaryFloat32x4Op) \
M(Float32x4Shuffle) \
M(Simd32x4Shuffle) \
M(Simd32x4ShuffleMix) \
M(Simd32x4GetSignMask) \
M(Float32x4Constructor) \
M(Float32x4Zero) \
@ -690,7 +689,6 @@ class EmbeddedArray<T, 0> {
M(Float32x4Clamp) \
M(Float32x4With) \
M(Float32x4ToUint32x4) \
M(Float32x4TwoArgShuffle) \
M(MaterializeObject) \
M(Uint32x4BoolConstructor) \
M(Uint32x4GetFlag) \
@ -967,7 +965,8 @@ FOR_EACH_INSTRUCTION(INSTRUCTION_TYPE_CHECK)
friend class BinaryFloat32x4OpInstr;
friend class Float32x4ZeroInstr;
friend class Float32x4SplatInstr;
friend class Float32x4ShuffleInstr;
friend class Simd32x4ShuffleInstr;
friend class Simd32x4ShuffleMixInstr;
friend class Simd32x4GetSignMaskInstr;
friend class Float32x4ConstructorInstr;
friend class Float32x4ComparisonInstr;
@ -978,7 +977,6 @@ FOR_EACH_INSTRUCTION(INSTRUCTION_TYPE_CHECK)
friend class Float32x4ClampInstr;
friend class Float32x4WithInstr;
friend class Float32x4ToUint32x4Instr;
friend class Float32x4TwoArgShuffleInstr;
friend class Uint32x4BoolConstructorInstr;
friend class Uint32x4GetFlagInstr;
friend class Uint32x4SetFlagInstr;
@ -4996,11 +4994,11 @@ class BinaryFloat32x4OpInstr : public TemplateDefinition<2> {
};
class Float32x4ShuffleInstr : public TemplateDefinition<1> {
class Simd32x4ShuffleInstr : public TemplateDefinition<1> {
public:
Float32x4ShuffleInstr(MethodRecognizer::Kind op_kind, Value* value,
intptr_t mask,
intptr_t deopt_id)
Simd32x4ShuffleInstr(MethodRecognizer::Kind op_kind, Value* value,
intptr_t mask,
intptr_t deopt_id)
: op_kind_(op_kind), mask_(mask) {
SetInputAt(0, value);
deopt_id_ = deopt_id;
@ -5023,11 +5021,88 @@ class Float32x4ShuffleInstr : public TemplateDefinition<1> {
(op_kind_ == MethodRecognizer::kFloat32x4ShuffleW)) {
return kUnboxedDouble;
}
if ((op_kind_ == MethodRecognizer::kUint32x4Shuffle)) {
return kUnboxedUint32x4;
}
ASSERT((op_kind_ == MethodRecognizer::kFloat32x4Shuffle));
return kUnboxedFloat32x4;
}
virtual Representation RequiredInputRepresentation(intptr_t idx) const {
ASSERT(idx == 0);
if ((op_kind_ == MethodRecognizer::kFloat32x4ShuffleX) ||
(op_kind_ == MethodRecognizer::kFloat32x4ShuffleY) ||
(op_kind_ == MethodRecognizer::kFloat32x4ShuffleZ) ||
(op_kind_ == MethodRecognizer::kFloat32x4ShuffleW) ||
(op_kind_ == MethodRecognizer::kFloat32x4Shuffle)) {
return kUnboxedFloat32x4;
}
ASSERT((op_kind_ == MethodRecognizer::kUint32x4Shuffle));
return kUnboxedUint32x4;
}
virtual intptr_t DeoptimizationTarget() const {
// Direct access since this instruction cannot deoptimize, and the deopt-id
// was inherited from another instruction that could deoptimize.
return deopt_id_;
}
DECLARE_INSTRUCTION(Simd32x4Shuffle)
virtual CompileType ComputeType() const;
virtual bool AllowsCSE() const { return true; }
virtual EffectSet Effects() const { return EffectSet::None(); }
virtual EffectSet Dependencies() const { return EffectSet::None(); }
virtual bool AttributesEqual(Instruction* other) const {
return (op_kind() == other->AsSimd32x4Shuffle()->op_kind()) &&
(mask() == other->AsSimd32x4Shuffle()->mask());
}
virtual bool MayThrow() const { return false; }
private:
const MethodRecognizer::Kind op_kind_;
const intptr_t mask_;
DISALLOW_COPY_AND_ASSIGN(Simd32x4ShuffleInstr);
};
class Simd32x4ShuffleMixInstr : public TemplateDefinition<2> {
public:
Simd32x4ShuffleMixInstr(MethodRecognizer::Kind op_kind, Value* xy,
Value* zw, intptr_t mask, intptr_t deopt_id)
: op_kind_(op_kind), mask_(mask) {
SetInputAt(0, xy);
SetInputAt(1, zw);
deopt_id_ = deopt_id;
}
Value* xy() const { return inputs_[0]; }
Value* zw() const { return inputs_[1]; }
MethodRecognizer::Kind op_kind() const { return op_kind_; }
intptr_t mask() const { return mask_; }
virtual void PrintOperandsTo(BufferFormatter* f) const;
virtual bool CanDeoptimize() const { return false; }
virtual Representation representation() const {
if (op_kind() == MethodRecognizer::kUint32x4ShuffleMix) {
return kUnboxedUint32x4;
}
ASSERT(op_kind() == MethodRecognizer::kFloat32x4ShuffleMix);
return kUnboxedFloat32x4;
}
virtual Representation RequiredInputRepresentation(intptr_t idx) const {
ASSERT((idx == 0) || (idx == 1));
if (op_kind() == MethodRecognizer::kUint32x4ShuffleMix) {
return kUnboxedUint32x4;
}
ASSERT(op_kind() == MethodRecognizer::kFloat32x4ShuffleMix);
return kUnboxedFloat32x4;
}
@ -5037,15 +5112,15 @@ class Float32x4ShuffleInstr : public TemplateDefinition<1> {
return deopt_id_;
}
DECLARE_INSTRUCTION(Float32x4Shuffle)
DECLARE_INSTRUCTION(Simd32x4ShuffleMix)
virtual CompileType ComputeType() const;
virtual bool AllowsCSE() const { return true; }
virtual EffectSet Effects() const { return EffectSet::None(); }
virtual EffectSet Dependencies() const { return EffectSet::None(); }
virtual bool AttributesEqual(Instruction* other) const {
return op_kind() == other->AsFloat32x4Shuffle()->op_kind() &&
mask() == other->AsFloat32x4Shuffle()->mask();
return (op_kind() == other->AsSimd32x4ShuffleMix()->op_kind()) &&
(mask() == other->AsSimd32x4ShuffleMix()->mask());
}
virtual bool MayThrow() const { return false; }
@ -5054,7 +5129,7 @@ class Float32x4ShuffleInstr : public TemplateDefinition<1> {
const MethodRecognizer::Kind op_kind_;
const intptr_t mask_;
DISALLOW_COPY_AND_ASSIGN(Float32x4ShuffleInstr);
DISALLOW_COPY_AND_ASSIGN(Simd32x4ShuffleMixInstr);
};
@ -5757,59 +5832,6 @@ class Simd32x4GetSignMaskInstr : public TemplateDefinition<1> {
};
class Float32x4TwoArgShuffleInstr : public TemplateDefinition<2> {
public:
Float32x4TwoArgShuffleInstr(MethodRecognizer::Kind op_kind, Value* left,
Value* right, intptr_t deopt_id)
: op_kind_(op_kind) {
SetInputAt(0, left);
SetInputAt(1, right);
deopt_id_ = deopt_id;
}
Value* left() const { return inputs_[0]; }
Value* right() const { return inputs_[1]; }
MethodRecognizer::Kind op_kind() const { return op_kind_; }
virtual void PrintOperandsTo(BufferFormatter* f) const;
virtual bool CanDeoptimize() const { return false; }
virtual Representation representation() const {
return kUnboxedFloat32x4;
}
virtual Representation RequiredInputRepresentation(intptr_t idx) const {
ASSERT((idx == 0) || (idx == 1));
return kUnboxedFloat32x4;
}
virtual intptr_t DeoptimizationTarget() const {
// Direct access since this instruction cannot deoptimize, and the deopt-id
// was inherited from another instruction that could deoptimize.
return deopt_id_;
}
DECLARE_INSTRUCTION(Float32x4TwoArgShuffle)
virtual CompileType ComputeType() const;
virtual bool AllowsCSE() const { return true; }
virtual EffectSet Effects() const { return EffectSet::None(); }
virtual EffectSet Dependencies() const { return EffectSet::None(); }
virtual bool AttributesEqual(Instruction* other) const {
return op_kind() == other->AsFloat32x4TwoArgShuffle()->op_kind();
}
virtual bool MayThrow() const { return false; }
private:
const MethodRecognizer::Kind op_kind_;
DISALLOW_COPY_AND_ASSIGN(Float32x4TwoArgShuffleInstr);
};
class Uint32x4SelectInstr : public TemplateDefinition<3> {
public:
Uint32x4SelectInstr(Value* mask, Value* trueValue, Value* falseValue,

View file

@ -3043,7 +3043,7 @@ void BinaryFloat32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
}
LocationSummary* Float32x4ShuffleInstr::MakeLocationSummary() const {
LocationSummary* Simd32x4ShuffleInstr::MakeLocationSummary() const {
const intptr_t kNumInputs = 1;
const intptr_t kNumTemps = 0;
LocationSummary* summary =
@ -3055,7 +3055,7 @@ LocationSummary* Float32x4ShuffleInstr::MakeLocationSummary() const {
}
void Float32x4ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
void Simd32x4ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
QRegister value = locs()->in(0).fpu_reg();
QRegister result = locs()->out().fpu_reg();
DRegister dresult0 = EvenDRegisterOf(result);
@ -3073,6 +3073,7 @@ void Float32x4ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
// For some cases the vdup instruction requires fewer
// instructions. For arbitrary shuffles, use vtbl.
switch (op_kind()) {
case MethodRecognizer::kFloat32x4ShuffleX:
__ vdup(kWord, result, dvalue0, 0);
@ -3090,6 +3091,7 @@ void Float32x4ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
__ vdup(kWord, result, dvalue1, 1);
__ vcvtds(dresult0, sresult0);
break;
case MethodRecognizer::kUint32x4Shuffle:
case MethodRecognizer::kFloat32x4Shuffle:
if (mask_ == 0x00) {
__ vdup(kWord, result, dvalue0, 0);
@ -3100,6 +3102,8 @@ void Float32x4ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
} else if (mask_ == 0xFF) {
__ vdup(kWord, result, dvalue1, 1);
} else {
// TODO(zra): Investigate better instruction sequences for other
// shuffle masks.
SRegister svalues[4];
svalues[0] = EvenSRegisterOf(dtemp0);
@ -3119,6 +3123,62 @@ void Float32x4ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
}
LocationSummary* Simd32x4ShuffleMixInstr::MakeLocationSummary() const {
const intptr_t kNumInputs = 2;
const intptr_t kNumTemps = 0;
LocationSummary* summary =
new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
// Low (< Q7) Q registers are needed for the vcvtds and vmovs instructions.
summary->set_in(0, Location::FpuRegisterLocation(Q4));
summary->set_in(1, Location::FpuRegisterLocation(Q5));
summary->set_out(Location::FpuRegisterLocation(Q6));
return summary;
}
void Simd32x4ShuffleMixInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
QRegister left = locs()->in(0).fpu_reg();
QRegister right = locs()->in(1).fpu_reg();
QRegister result = locs()->out().fpu_reg();
DRegister dresult0 = EvenDRegisterOf(result);
DRegister dresult1 = OddDRegisterOf(result);
SRegister sresult0 = EvenSRegisterOf(dresult0);
SRegister sresult1 = OddSRegisterOf(dresult0);
SRegister sresult2 = EvenSRegisterOf(dresult1);
SRegister sresult3 = OddSRegisterOf(dresult1);
DRegister dleft0 = EvenDRegisterOf(left);
DRegister dleft1 = OddDRegisterOf(left);
DRegister dright0 = EvenDRegisterOf(right);
DRegister dright1 = OddDRegisterOf(right);
switch (op_kind()) {
case MethodRecognizer::kFloat32x4ShuffleMix:
case MethodRecognizer::kUint32x4ShuffleMix:
// TODO(zra): Investigate better instruction sequences for shuffle masks.
SRegister left_svalues[4];
SRegister right_svalues[4];
left_svalues[0] = EvenSRegisterOf(dleft0);
left_svalues[1] = OddSRegisterOf(dleft0);
left_svalues[2] = EvenSRegisterOf(dleft1);
left_svalues[3] = OddSRegisterOf(dleft1);
right_svalues[0] = EvenSRegisterOf(dright0);
right_svalues[1] = OddSRegisterOf(dright0);
right_svalues[2] = EvenSRegisterOf(dright1);
right_svalues[3] = OddSRegisterOf(dright1);
__ vmovs(sresult0, left_svalues[mask_ & 0x3]);
__ vmovs(sresult1, left_svalues[(mask_ >> 2) & 0x3]);
__ vmovs(sresult2, right_svalues[(mask_ >> 4) & 0x3]);
__ vmovs(sresult3, right_svalues[(mask_ >> 6) & 0x3]);
break;
default: UNREACHABLE();
}
}
LocationSummary* Simd32x4GetSignMaskInstr::MakeLocationSummary() const {
const intptr_t kNumInputs = 1;
const intptr_t kNumTemps = 1;
@ -3485,56 +3545,6 @@ void Float32x4ToUint32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
}
LocationSummary* Float32x4TwoArgShuffleInstr::MakeLocationSummary() const {
const intptr_t kNumInputs = 2;
const intptr_t kNumTemps = 0;
LocationSummary* summary =
new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
summary->set_in(0, Location::RequiresFpuRegister());
summary->set_in(1, Location::RequiresFpuRegister());
summary->set_out(Location::SameAsFirstInput());
return summary;
}
void Float32x4TwoArgShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
QRegister left = locs()->in(0).fpu_reg();
QRegister right = locs()->in(1).fpu_reg();
QRegister result = locs()->out().fpu_reg();
ASSERT(result == left);
DRegister dleft0 = EvenDRegisterOf(left);
DRegister dleft1 = OddDRegisterOf(left);
DRegister dright0 = EvenDRegisterOf(right);
DRegister dright1 = OddDRegisterOf(right);
switch (op_kind()) {
case MethodRecognizer::kFloat32x4WithZWInXY:
__ vmovd(dleft0, dright1);
break;
case MethodRecognizer::kFloat32x4InterleaveXY:
__ vmovq(QTMP, right);
__ vzipqw(left, QTMP);
break;
case MethodRecognizer::kFloat32x4InterleaveZW:
__ vmovq(QTMP, right);
__ vzipqw(left, QTMP);
__ vmovq(left, QTMP);
break;
case MethodRecognizer::kFloat32x4InterleaveXYPairs:
__ vmovd(dleft1, dright0);
break;
case MethodRecognizer::kFloat32x4InterleaveZWPairs:
__ vmovq(QTMP, right);
__ vmovd(EvenDRegisterOf(QTMP), dleft1);
__ vmovq(result, QTMP);
break;
default: UNREACHABLE();
}
}
LocationSummary* Uint32x4BoolConstructorInstr::MakeLocationSummary() const {
const intptr_t kNumInputs = 4;
const intptr_t kNumTemps = 1;

View file

@ -3135,7 +3135,7 @@ void BinaryFloat32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
}
LocationSummary* Float32x4ShuffleInstr::MakeLocationSummary() const {
LocationSummary* Simd32x4ShuffleInstr::MakeLocationSummary() const {
const intptr_t kNumInputs = 1;
const intptr_t kNumTemps = 0;
LocationSummary* summary =
@ -3146,7 +3146,7 @@ LocationSummary* Float32x4ShuffleInstr::MakeLocationSummary() const {
}
void Float32x4ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
void Simd32x4ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
XmmRegister value = locs()->in(0).fpu_reg();
ASSERT(locs()->out().fpu_reg() == value);
@ -3169,6 +3169,7 @@ void Float32x4ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
__ cvtss2sd(value, value);
break;
case MethodRecognizer::kFloat32x4Shuffle:
case MethodRecognizer::kUint32x4Shuffle:
__ shufps(value, value, Immediate(mask_));
break;
default: UNREACHABLE();
@ -3176,6 +3177,33 @@ void Float32x4ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
}
LocationSummary* Simd32x4ShuffleMixInstr::MakeLocationSummary() const {
const intptr_t kNumInputs = 2;
const intptr_t kNumTemps = 0;
LocationSummary* summary =
new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
summary->set_in(0, Location::RequiresFpuRegister());
summary->set_in(1, Location::RequiresFpuRegister());
summary->set_out(Location::SameAsFirstInput());
return summary;
}
void Simd32x4ShuffleMixInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
XmmRegister left = locs()->in(0).fpu_reg();
XmmRegister right = locs()->in(1).fpu_reg();
ASSERT(locs()->out().fpu_reg() == left);
switch (op_kind()) {
case MethodRecognizer::kFloat32x4ShuffleMix:
case MethodRecognizer::kUint32x4ShuffleMix:
__ shufps(left, right, Immediate(mask_));
break;
default: UNREACHABLE();
}
}
LocationSummary* Simd32x4GetSignMaskInstr::MakeLocationSummary() const {
const intptr_t kNumInputs = 1;
const intptr_t kNumTemps = 0;
@ -3537,45 +3565,6 @@ void Float32x4ToUint32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
}
LocationSummary* Float32x4TwoArgShuffleInstr::MakeLocationSummary() const {
const intptr_t kNumInputs = 2;
const intptr_t kNumTemps = 0;
LocationSummary* summary =
new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
summary->set_in(0, Location::RequiresFpuRegister());
summary->set_in(1, Location::RequiresFpuRegister());
summary->set_out(Location::SameAsFirstInput());
return summary;
}
void Float32x4TwoArgShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
XmmRegister left = locs()->in(0).fpu_reg();
XmmRegister right = locs()->in(1).fpu_reg();
ASSERT(locs()->out().fpu_reg() == left);
switch (op_kind()) {
case MethodRecognizer::kFloat32x4WithZWInXY:
__ movhlps(left, right);
break;
case MethodRecognizer::kFloat32x4InterleaveXY:
__ unpcklps(left, right);
break;
case MethodRecognizer::kFloat32x4InterleaveZW:
__ unpckhps(left, right);
break;
case MethodRecognizer::kFloat32x4InterleaveXYPairs:
__ unpcklpd(left, right);
break;
case MethodRecognizer::kFloat32x4InterleaveZWPairs:
__ unpckhpd(left, right);
break;
default: UNREACHABLE();
}
}
LocationSummary* Uint32x4BoolConstructorInstr::MakeLocationSummary() const {
const intptr_t kNumInputs = 4;
const intptr_t kNumTemps = 0;

View file

@ -2969,13 +2969,25 @@ void BinaryFloat32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
}
LocationSummary* Float32x4ShuffleInstr::MakeLocationSummary() const {
LocationSummary* Simd32x4ShuffleInstr::MakeLocationSummary() const {
UNIMPLEMENTED();
return NULL;
}
void Float32x4ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
void Simd32x4ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
UNIMPLEMENTED();
}
LocationSummary* Simd32x4ShuffleMixInstr::MakeLocationSummary() const {
UNIMPLEMENTED();
return NULL;
}
void Simd32x4ShuffleMixInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
UNIMPLEMENTED();
}
@ -3101,17 +3113,6 @@ void Float32x4ToUint32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
}
LocationSummary* Float32x4TwoArgShuffleInstr::MakeLocationSummary() const {
UNIMPLEMENTED();
return NULL;
}
void Float32x4TwoArgShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
UNIMPLEMENTED();
}
LocationSummary* Uint32x4BoolConstructorInstr::MakeLocationSummary() const {
UNIMPLEMENTED();
return NULL;

View file

@ -3151,7 +3151,7 @@ void BinaryFloat32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
}
LocationSummary* Float32x4ShuffleInstr::MakeLocationSummary() const {
LocationSummary* Simd32x4ShuffleInstr::MakeLocationSummary() const {
const intptr_t kNumInputs = 1;
const intptr_t kNumTemps = 0;
LocationSummary* summary =
@ -3162,7 +3162,7 @@ LocationSummary* Float32x4ShuffleInstr::MakeLocationSummary() const {
}
void Float32x4ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
void Simd32x4ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
XmmRegister value = locs()->in(0).fpu_reg();
ASSERT(locs()->out().fpu_reg() == value);
@ -3185,6 +3185,7 @@ void Float32x4ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
__ cvtss2sd(value, value);
break;
case MethodRecognizer::kFloat32x4Shuffle:
case MethodRecognizer::kUint32x4Shuffle:
__ shufps(value, value, Immediate(mask_));
break;
default: UNREACHABLE();
@ -3192,6 +3193,33 @@ void Float32x4ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
}
LocationSummary* Simd32x4ShuffleMixInstr::MakeLocationSummary() const {
const intptr_t kNumInputs = 2;
const intptr_t kNumTemps = 0;
LocationSummary* summary =
new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
summary->set_in(0, Location::RequiresFpuRegister());
summary->set_in(1, Location::RequiresFpuRegister());
summary->set_out(Location::SameAsFirstInput());
return summary;
}
void Simd32x4ShuffleMixInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
XmmRegister left = locs()->in(0).fpu_reg();
XmmRegister right = locs()->in(1).fpu_reg();
ASSERT(locs()->out().fpu_reg() == left);
switch (op_kind()) {
case MethodRecognizer::kFloat32x4ShuffleMix:
case MethodRecognizer::kUint32x4ShuffleMix:
__ shufps(left, right, Immediate(mask_));
break;
default: UNREACHABLE();
}
}
LocationSummary* Simd32x4GetSignMaskInstr::MakeLocationSummary() const {
const intptr_t kNumInputs = 1;
const intptr_t kNumTemps = 0;
@ -3553,45 +3581,6 @@ void Float32x4ToUint32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
}
LocationSummary* Float32x4TwoArgShuffleInstr::MakeLocationSummary() const {
const intptr_t kNumInputs = 2;
const intptr_t kNumTemps = 0;
LocationSummary* summary =
new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
summary->set_in(0, Location::RequiresFpuRegister());
summary->set_in(1, Location::RequiresFpuRegister());
summary->set_out(Location::SameAsFirstInput());
return summary;
}
void Float32x4TwoArgShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
XmmRegister left = locs()->in(0).fpu_reg();
XmmRegister right = locs()->in(1).fpu_reg();
ASSERT(locs()->out().fpu_reg() == left);
switch (op_kind()) {
case MethodRecognizer::kFloat32x4WithZWInXY:
__ movhlps(left, right);
break;
case MethodRecognizer::kFloat32x4InterleaveXY:
__ unpcklps(left, right);
break;
case MethodRecognizer::kFloat32x4InterleaveZW:
__ unpckhps(left, right);
break;
case MethodRecognizer::kFloat32x4InterleaveXYPairs:
__ unpcklpd(left, right);
break;
case MethodRecognizer::kFloat32x4InterleaveZWPairs:
__ unpckhpd(left, right);
break;
default: UNREACHABLE();
}
}
LocationSummary* Uint32x4BoolConstructorInstr::MakeLocationSummary() const {
const intptr_t kNumInputs = 4;
const intptr_t kNumTemps = 1;

View file

@ -1097,7 +1097,7 @@ class Float32x4 {
return mx | my << 1 | mz << 2 | mw << 3;
}
/// Mask passed to [shuffle].
/// Mask passed to [shuffle] and [shuffleMix].
static const int XXXX = 0x0;
static const int XXXY = 0x40;
static const int XXXZ = 0x80;
@ -1357,7 +1357,7 @@ class Float32x4 {
/// Shuffle the lane values. [mask] must be one of the 256 shuffle constants.
Float32x4 shuffle(int m) {
if (m < 0 || m > 255) {
if ((m < 0) || (m > 255)) {
throw new RangeError('mask $m must be in the range [0..256)');
}
double _x = _storage[m & 0x3];
@ -1367,53 +1367,17 @@ class Float32x4 {
return new Float32x4(_x, _y, _z, _w);
}
/// Returns a new [Float32x4] with values in the X and Y lanes
/// replaced with the values in the Z and W lanes of [other].
Float32x4 withZWInXY(Float32x4 other) {
double _x = other._storage[2];
double _y = other._storage[3];
double _z = _storage[2];
double _w = _storage[3];
return new Float32x4(_x, _y, _z, _w);
}
/// Returns a new [Float32x4] with the X and Y lane values
/// from [this] and [other] interleaved.
Float32x4 interleaveXY(Float32x4 other) {
double _x = _storage[0];
double _y = other._storage[0];
double _z = _storage[1];
double _w = other._storage[1];
return new Float32x4(_x, _y, _z, _w);
}
/// Returns a new [Float32x4] with the Z and W lane values
/// from [this] and [other] interleaved.
Float32x4 interleaveZW(Float32x4 other) {
double _x = _storage[2];
double _y = other._storage[2];
double _z = _storage[3];
double _w = other._storage[3];
return new Float32x4(_x, _y, _z, _w);
}
/// Returns a new [Float32x4] with the X and Y lane value pairs
/// from [this] and [other] interleaved.
Float32x4 interleaveXYPairs(Float32x4 other) {
double _x = _storage[0];
double _y = _storage[1];
double _z = other._storage[0];
double _w = other._storage[1];
return new Float32x4(_x, _y, _z, _w);
}
/// Returns a new [Float32x4] with the Z and W lane value pairs
/// from [this] and [other] interleaved.
Float32x4 interleaveZWPairs(Float32x4 other) {
double _x = _storage[2];
double _y = _storage[3];
double _z = other._storage[2];
double _w = other._storage[3];
/// Shuffle the lane values in [this] and [other]. The returned
/// Float32x4 will have XY lanes from [this] and ZW lanes from [other].
/// Uses the same [mask] as [shuffle].
Float32x4 shuffleMix(Float32x4 other, int m) {
if ((m < 0) || (m > 255)) {
throw new RangeError('mask $m must be in the range [0..256)');
}
double _x = _storage[m & 0x3];
double _y = _storage[(m >> 2) & 0x3];
double _z = other._storage[(m >> 4) & 0x3];
double _w = other._storage[(m >> 6) & 0x3];
return new Float32x4(_x, _y, _z, _w);
}
@ -1597,6 +1561,290 @@ class Uint32x4 {
return mx | my << 1 | mz << 2 | mw << 3;
}
/// Mask passed to [shuffle] and [shuffleMix].
static const int XXXX = 0x0;
static const int XXXY = 0x40;
static const int XXXZ = 0x80;
static const int XXXW = 0xC0;
static const int XXYX = 0x10;
static const int XXYY = 0x50;
static const int XXYZ = 0x90;
static const int XXYW = 0xD0;
static const int XXZX = 0x20;
static const int XXZY = 0x60;
static const int XXZZ = 0xA0;
static const int XXZW = 0xE0;
static const int XXWX = 0x30;
static const int XXWY = 0x70;
static const int XXWZ = 0xB0;
static const int XXWW = 0xF0;
static const int XYXX = 0x4;
static const int XYXY = 0x44;
static const int XYXZ = 0x84;
static const int XYXW = 0xC4;
static const int XYYX = 0x14;
static const int XYYY = 0x54;
static const int XYYZ = 0x94;
static const int XYYW = 0xD4;
static const int XYZX = 0x24;
static const int XYZY = 0x64;
static const int XYZZ = 0xA4;
static const int XYZW = 0xE4;
static const int XYWX = 0x34;
static const int XYWY = 0x74;
static const int XYWZ = 0xB4;
static const int XYWW = 0xF4;
static const int XZXX = 0x8;
static const int XZXY = 0x48;
static const int XZXZ = 0x88;
static const int XZXW = 0xC8;
static const int XZYX = 0x18;
static const int XZYY = 0x58;
static const int XZYZ = 0x98;
static const int XZYW = 0xD8;
static const int XZZX = 0x28;
static const int XZZY = 0x68;
static const int XZZZ = 0xA8;
static const int XZZW = 0xE8;
static const int XZWX = 0x38;
static const int XZWY = 0x78;
static const int XZWZ = 0xB8;
static const int XZWW = 0xF8;
static const int XWXX = 0xC;
static const int XWXY = 0x4C;
static const int XWXZ = 0x8C;
static const int XWXW = 0xCC;
static const int XWYX = 0x1C;
static const int XWYY = 0x5C;
static const int XWYZ = 0x9C;
static const int XWYW = 0xDC;
static const int XWZX = 0x2C;
static const int XWZY = 0x6C;
static const int XWZZ = 0xAC;
static const int XWZW = 0xEC;
static const int XWWX = 0x3C;
static const int XWWY = 0x7C;
static const int XWWZ = 0xBC;
static const int XWWW = 0xFC;
static const int YXXX = 0x1;
static const int YXXY = 0x41;
static const int YXXZ = 0x81;
static const int YXXW = 0xC1;
static const int YXYX = 0x11;
static const int YXYY = 0x51;
static const int YXYZ = 0x91;
static const int YXYW = 0xD1;
static const int YXZX = 0x21;
static const int YXZY = 0x61;
static const int YXZZ = 0xA1;
static const int YXZW = 0xE1;
static const int YXWX = 0x31;
static const int YXWY = 0x71;
static const int YXWZ = 0xB1;
static const int YXWW = 0xF1;
static const int YYXX = 0x5;
static const int YYXY = 0x45;
static const int YYXZ = 0x85;
static const int YYXW = 0xC5;
static const int YYYX = 0x15;
static const int YYYY = 0x55;
static const int YYYZ = 0x95;
static const int YYYW = 0xD5;
static const int YYZX = 0x25;
static const int YYZY = 0x65;
static const int YYZZ = 0xA5;
static const int YYZW = 0xE5;
static const int YYWX = 0x35;
static const int YYWY = 0x75;
static const int YYWZ = 0xB5;
static const int YYWW = 0xF5;
static const int YZXX = 0x9;
static const int YZXY = 0x49;
static const int YZXZ = 0x89;
static const int YZXW = 0xC9;
static const int YZYX = 0x19;
static const int YZYY = 0x59;
static const int YZYZ = 0x99;
static const int YZYW = 0xD9;
static const int YZZX = 0x29;
static const int YZZY = 0x69;
static const int YZZZ = 0xA9;
static const int YZZW = 0xE9;
static const int YZWX = 0x39;
static const int YZWY = 0x79;
static const int YZWZ = 0xB9;
static const int YZWW = 0xF9;
static const int YWXX = 0xD;
static const int YWXY = 0x4D;
static const int YWXZ = 0x8D;
static const int YWXW = 0xCD;
static const int YWYX = 0x1D;
static const int YWYY = 0x5D;
static const int YWYZ = 0x9D;
static const int YWYW = 0xDD;
static const int YWZX = 0x2D;
static const int YWZY = 0x6D;
static const int YWZZ = 0xAD;
static const int YWZW = 0xED;
static const int YWWX = 0x3D;
static const int YWWY = 0x7D;
static const int YWWZ = 0xBD;
static const int YWWW = 0xFD;
static const int ZXXX = 0x2;
static const int ZXXY = 0x42;
static const int ZXXZ = 0x82;
static const int ZXXW = 0xC2;
static const int ZXYX = 0x12;
static const int ZXYY = 0x52;
static const int ZXYZ = 0x92;
static const int ZXYW = 0xD2;
static const int ZXZX = 0x22;
static const int ZXZY = 0x62;
static const int ZXZZ = 0xA2;
static const int ZXZW = 0xE2;
static const int ZXWX = 0x32;
static const int ZXWY = 0x72;
static const int ZXWZ = 0xB2;
static const int ZXWW = 0xF2;
static const int ZYXX = 0x6;
static const int ZYXY = 0x46;
static const int ZYXZ = 0x86;
static const int ZYXW = 0xC6;
static const int ZYYX = 0x16;
static const int ZYYY = 0x56;
static const int ZYYZ = 0x96;
static const int ZYYW = 0xD6;
static const int ZYZX = 0x26;
static const int ZYZY = 0x66;
static const int ZYZZ = 0xA6;
static const int ZYZW = 0xE6;
static const int ZYWX = 0x36;
static const int ZYWY = 0x76;
static const int ZYWZ = 0xB6;
static const int ZYWW = 0xF6;
static const int ZZXX = 0xA;
static const int ZZXY = 0x4A;
static const int ZZXZ = 0x8A;
static const int ZZXW = 0xCA;
static const int ZZYX = 0x1A;
static const int ZZYY = 0x5A;
static const int ZZYZ = 0x9A;
static const int ZZYW = 0xDA;
static const int ZZZX = 0x2A;
static const int ZZZY = 0x6A;
static const int ZZZZ = 0xAA;
static const int ZZZW = 0xEA;
static const int ZZWX = 0x3A;
static const int ZZWY = 0x7A;
static const int ZZWZ = 0xBA;
static const int ZZWW = 0xFA;
static const int ZWXX = 0xE;
static const int ZWXY = 0x4E;
static const int ZWXZ = 0x8E;
static const int ZWXW = 0xCE;
static const int ZWYX = 0x1E;
static const int ZWYY = 0x5E;
static const int ZWYZ = 0x9E;
static const int ZWYW = 0xDE;
static const int ZWZX = 0x2E;
static const int ZWZY = 0x6E;
static const int ZWZZ = 0xAE;
static const int ZWZW = 0xEE;
static const int ZWWX = 0x3E;
static const int ZWWY = 0x7E;
static const int ZWWZ = 0xBE;
static const int ZWWW = 0xFE;
static const int WXXX = 0x3;
static const int WXXY = 0x43;
static const int WXXZ = 0x83;
static const int WXXW = 0xC3;
static const int WXYX = 0x13;
static const int WXYY = 0x53;
static const int WXYZ = 0x93;
static const int WXYW = 0xD3;
static const int WXZX = 0x23;
static const int WXZY = 0x63;
static const int WXZZ = 0xA3;
static const int WXZW = 0xE3;
static const int WXWX = 0x33;
static const int WXWY = 0x73;
static const int WXWZ = 0xB3;
static const int WXWW = 0xF3;
static const int WYXX = 0x7;
static const int WYXY = 0x47;
static const int WYXZ = 0x87;
static const int WYXW = 0xC7;
static const int WYYX = 0x17;
static const int WYYY = 0x57;
static const int WYYZ = 0x97;
static const int WYYW = 0xD7;
static const int WYZX = 0x27;
static const int WYZY = 0x67;
static const int WYZZ = 0xA7;
static const int WYZW = 0xE7;
static const int WYWX = 0x37;
static const int WYWY = 0x77;
static const int WYWZ = 0xB7;
static const int WYWW = 0xF7;
static const int WZXX = 0xB;
static const int WZXY = 0x4B;
static const int WZXZ = 0x8B;
static const int WZXW = 0xCB;
static const int WZYX = 0x1B;
static const int WZYY = 0x5B;
static const int WZYZ = 0x9B;
static const int WZYW = 0xDB;
static const int WZZX = 0x2B;
static const int WZZY = 0x6B;
static const int WZZZ = 0xAB;
static const int WZZW = 0xEB;
static const int WZWX = 0x3B;
static const int WZWY = 0x7B;
static const int WZWZ = 0xBB;
static const int WZWW = 0xFB;
static const int WWXX = 0xF;
static const int WWXY = 0x4F;
static const int WWXZ = 0x8F;
static const int WWXW = 0xCF;
static const int WWYX = 0x1F;
static const int WWYY = 0x5F;
static const int WWYZ = 0x9F;
static const int WWYW = 0xDF;
static const int WWZX = 0x2F;
static const int WWZY = 0x6F;
static const int WWZZ = 0xAF;
static const int WWZW = 0xEF;
static const int WWWX = 0x3F;
static const int WWWY = 0x7F;
static const int WWWZ = 0xBF;
static const int WWWW = 0xFF;
/// Shuffle the lane values. [mask] must be one of the 256 shuffle constants.
Uint32x4 shuffle(int mask) {
if ((mask < 0) || (mask > 255)) {
throw new RangeError('mask $mask must be in the range [0..256)');
}
int _x = _storage[mask & 0x3];
int _y = _storage[(mask >> 2) & 0x3];
int _z = _storage[(mask >> 4) & 0x3];
int _w = _storage[(mask >> 6) & 0x3];
return new Uint32x4(_x, _y, _z, _w);
}
/// Shuffle the lane values in [this] and [other]. The returned
/// Uint32x4 will have XY lanes from [this] and ZW lanes from [other].
/// Uses the same [mask] as [shuffle].
Uint32x4 shuffleMix(Uint32x4 other, int mask) {
if ((mask < 0) || (mask > 255)) {
throw new RangeError('mask $mask must be in the range [0..256)');
}
int _x = _storage[mask & 0x3];
int _y = _storage[(mask >> 2) & 0x3];
int _z = other._storage[(mask >> 4) & 0x3];
int _w = other._storage[(mask >> 6) & 0x3];
return new Uint32x4(_x, _y, _z, _w);
}
/// Returns a new [Uint32x4] copied from [this] with a new x value.
Uint32x4 withX(int x) {
int _x = x;

View file

@ -921,7 +921,7 @@ abstract class Float32x4 {
/// Extract the sign bits from each lane return them in the first 4 bits.
int get signMask;
/// Mask passed to [shuffle].
/// Mask passed to [shuffle] or [shuffleMix].
static const int XXXX = 0x0;
static const int XXXY = 0x40;
static const int XXXZ = 0x80;
@ -1182,25 +1182,10 @@ abstract class Float32x4 {
/// Shuffle the lane values. [mask] must be one of the 256 shuffle constants.
Float32x4 shuffle(int mask);
/// Returns a new [Float32x4] with values in the X and Y lanes
/// replaced with the values in the Z and W lanes of [other].
Float32x4 withZWInXY(Float32x4 other);
/// Returns a new [Float32x4] with the X and Y lane values
/// from [this] and [other] interleaved.
Float32x4 interleaveXY(Float32x4 other);
/// Returns a new [Float32x4] with the Z and W lane values
/// from [this] and [other] interleaved.
Float32x4 interleaveZW(Float32x4 other);
/// Returns a new [Float32x4] with the X and Y lane value pairs
/// from [this] and [other] interleaved.
Float32x4 interleaveXYPairs(Float32x4 other);
/// Returns a new [Float32x4] with the Z and W lane value pairs
/// from [this] and [other] interleaved.
Float32x4 interleaveZWPairs(Float32x4 other);
/// Shuffle the lane values in [this] and [other]. The returned
/// Float32x4 will have XY lanes from [this] and ZW lanes from [other].
/// Uses the same [mask] as [shuffle].
Float32x4 shuffleMix(Float32x4 other, int mask);
/// Returns a new [Float32x4] copied from [this] with a new x value.
Float32x4 withX(double x);
@ -1261,6 +1246,272 @@ abstract class Uint32x4 {
/// Extract the top bit from each lane return them in the first 4 bits.
int get signMask;
/// Mask passed to [shuffle] or [shuffleMix].
static const int XXXX = 0x0;
static const int XXXY = 0x40;
static const int XXXZ = 0x80;
static const int XXXW = 0xC0;
static const int XXYX = 0x10;
static const int XXYY = 0x50;
static const int XXYZ = 0x90;
static const int XXYW = 0xD0;
static const int XXZX = 0x20;
static const int XXZY = 0x60;
static const int XXZZ = 0xA0;
static const int XXZW = 0xE0;
static const int XXWX = 0x30;
static const int XXWY = 0x70;
static const int XXWZ = 0xB0;
static const int XXWW = 0xF0;
static const int XYXX = 0x4;
static const int XYXY = 0x44;
static const int XYXZ = 0x84;
static const int XYXW = 0xC4;
static const int XYYX = 0x14;
static const int XYYY = 0x54;
static const int XYYZ = 0x94;
static const int XYYW = 0xD4;
static const int XYZX = 0x24;
static const int XYZY = 0x64;
static const int XYZZ = 0xA4;
static const int XYZW = 0xE4;
static const int XYWX = 0x34;
static const int XYWY = 0x74;
static const int XYWZ = 0xB4;
static const int XYWW = 0xF4;
static const int XZXX = 0x8;
static const int XZXY = 0x48;
static const int XZXZ = 0x88;
static const int XZXW = 0xC8;
static const int XZYX = 0x18;
static const int XZYY = 0x58;
static const int XZYZ = 0x98;
static const int XZYW = 0xD8;
static const int XZZX = 0x28;
static const int XZZY = 0x68;
static const int XZZZ = 0xA8;
static const int XZZW = 0xE8;
static const int XZWX = 0x38;
static const int XZWY = 0x78;
static const int XZWZ = 0xB8;
static const int XZWW = 0xF8;
static const int XWXX = 0xC;
static const int XWXY = 0x4C;
static const int XWXZ = 0x8C;
static const int XWXW = 0xCC;
static const int XWYX = 0x1C;
static const int XWYY = 0x5C;
static const int XWYZ = 0x9C;
static const int XWYW = 0xDC;
static const int XWZX = 0x2C;
static const int XWZY = 0x6C;
static const int XWZZ = 0xAC;
static const int XWZW = 0xEC;
static const int XWWX = 0x3C;
static const int XWWY = 0x7C;
static const int XWWZ = 0xBC;
static const int XWWW = 0xFC;
static const int YXXX = 0x1;
static const int YXXY = 0x41;
static const int YXXZ = 0x81;
static const int YXXW = 0xC1;
static const int YXYX = 0x11;
static const int YXYY = 0x51;
static const int YXYZ = 0x91;
static const int YXYW = 0xD1;
static const int YXZX = 0x21;
static const int YXZY = 0x61;
static const int YXZZ = 0xA1;
static const int YXZW = 0xE1;
static const int YXWX = 0x31;
static const int YXWY = 0x71;
static const int YXWZ = 0xB1;
static const int YXWW = 0xF1;
static const int YYXX = 0x5;
static const int YYXY = 0x45;
static const int YYXZ = 0x85;
static const int YYXW = 0xC5;
static const int YYYX = 0x15;
static const int YYYY = 0x55;
static const int YYYZ = 0x95;
static const int YYYW = 0xD5;
static const int YYZX = 0x25;
static const int YYZY = 0x65;
static const int YYZZ = 0xA5;
static const int YYZW = 0xE5;
static const int YYWX = 0x35;
static const int YYWY = 0x75;
static const int YYWZ = 0xB5;
static const int YYWW = 0xF5;
static const int YZXX = 0x9;
static const int YZXY = 0x49;
static const int YZXZ = 0x89;
static const int YZXW = 0xC9;
static const int YZYX = 0x19;
static const int YZYY = 0x59;
static const int YZYZ = 0x99;
static const int YZYW = 0xD9;
static const int YZZX = 0x29;
static const int YZZY = 0x69;
static const int YZZZ = 0xA9;
static const int YZZW = 0xE9;
static const int YZWX = 0x39;
static const int YZWY = 0x79;
static const int YZWZ = 0xB9;
static const int YZWW = 0xF9;
static const int YWXX = 0xD;
static const int YWXY = 0x4D;
static const int YWXZ = 0x8D;
static const int YWXW = 0xCD;
static const int YWYX = 0x1D;
static const int YWYY = 0x5D;
static const int YWYZ = 0x9D;
static const int YWYW = 0xDD;
static const int YWZX = 0x2D;
static const int YWZY = 0x6D;
static const int YWZZ = 0xAD;
static const int YWZW = 0xED;
static const int YWWX = 0x3D;
static const int YWWY = 0x7D;
static const int YWWZ = 0xBD;
static const int YWWW = 0xFD;
static const int ZXXX = 0x2;
static const int ZXXY = 0x42;
static const int ZXXZ = 0x82;
static const int ZXXW = 0xC2;
static const int ZXYX = 0x12;
static const int ZXYY = 0x52;
static const int ZXYZ = 0x92;
static const int ZXYW = 0xD2;
static const int ZXZX = 0x22;
static const int ZXZY = 0x62;
static const int ZXZZ = 0xA2;
static const int ZXZW = 0xE2;
static const int ZXWX = 0x32;
static const int ZXWY = 0x72;
static const int ZXWZ = 0xB2;
static const int ZXWW = 0xF2;
static const int ZYXX = 0x6;
static const int ZYXY = 0x46;
static const int ZYXZ = 0x86;
static const int ZYXW = 0xC6;
static const int ZYYX = 0x16;
static const int ZYYY = 0x56;
static const int ZYYZ = 0x96;
static const int ZYYW = 0xD6;
static const int ZYZX = 0x26;
static const int ZYZY = 0x66;
static const int ZYZZ = 0xA6;
static const int ZYZW = 0xE6;
static const int ZYWX = 0x36;
static const int ZYWY = 0x76;
static const int ZYWZ = 0xB6;
static const int ZYWW = 0xF6;
static const int ZZXX = 0xA;
static const int ZZXY = 0x4A;
static const int ZZXZ = 0x8A;
static const int ZZXW = 0xCA;
static const int ZZYX = 0x1A;
static const int ZZYY = 0x5A;
static const int ZZYZ = 0x9A;
static const int ZZYW = 0xDA;
static const int ZZZX = 0x2A;
static const int ZZZY = 0x6A;
static const int ZZZZ = 0xAA;
static const int ZZZW = 0xEA;
static const int ZZWX = 0x3A;
static const int ZZWY = 0x7A;
static const int ZZWZ = 0xBA;
static const int ZZWW = 0xFA;
static const int ZWXX = 0xE;
static const int ZWXY = 0x4E;
static const int ZWXZ = 0x8E;
static const int ZWXW = 0xCE;
static const int ZWYX = 0x1E;
static const int ZWYY = 0x5E;
static const int ZWYZ = 0x9E;
static const int ZWYW = 0xDE;
static const int ZWZX = 0x2E;
static const int ZWZY = 0x6E;
static const int ZWZZ = 0xAE;
static const int ZWZW = 0xEE;
static const int ZWWX = 0x3E;
static const int ZWWY = 0x7E;
static const int ZWWZ = 0xBE;
static const int ZWWW = 0xFE;
static const int WXXX = 0x3;
static const int WXXY = 0x43;
static const int WXXZ = 0x83;
static const int WXXW = 0xC3;
static const int WXYX = 0x13;
static const int WXYY = 0x53;
static const int WXYZ = 0x93;
static const int WXYW = 0xD3;
static const int WXZX = 0x23;
static const int WXZY = 0x63;
static const int WXZZ = 0xA3;
static const int WXZW = 0xE3;
static const int WXWX = 0x33;
static const int WXWY = 0x73;
static const int WXWZ = 0xB3;
static const int WXWW = 0xF3;
static const int WYXX = 0x7;
static const int WYXY = 0x47;
static const int WYXZ = 0x87;
static const int WYXW = 0xC7;
static const int WYYX = 0x17;
static const int WYYY = 0x57;
static const int WYYZ = 0x97;
static const int WYYW = 0xD7;
static const int WYZX = 0x27;
static const int WYZY = 0x67;
static const int WYZZ = 0xA7;
static const int WYZW = 0xE7;
static const int WYWX = 0x37;
static const int WYWY = 0x77;
static const int WYWZ = 0xB7;
static const int WYWW = 0xF7;
static const int WZXX = 0xB;
static const int WZXY = 0x4B;
static const int WZXZ = 0x8B;
static const int WZXW = 0xCB;
static const int WZYX = 0x1B;
static const int WZYY = 0x5B;
static const int WZYZ = 0x9B;
static const int WZYW = 0xDB;
static const int WZZX = 0x2B;
static const int WZZY = 0x6B;
static const int WZZZ = 0xAB;
static const int WZZW = 0xEB;
static const int WZWX = 0x3B;
static const int WZWY = 0x7B;
static const int WZWZ = 0xBB;
static const int WZWW = 0xFB;
static const int WWXX = 0xF;
static const int WWXY = 0x4F;
static const int WWXZ = 0x8F;
static const int WWXW = 0xCF;
static const int WWYX = 0x1F;
static const int WWYY = 0x5F;
static const int WWYZ = 0x9F;
static const int WWYW = 0xDF;
static const int WWZX = 0x2F;
static const int WWZY = 0x6F;
static const int WWZZ = 0xAF;
static const int WWZW = 0xEF;
static const int WWWX = 0x3F;
static const int WWWY = 0x7F;
static const int WWWZ = 0xBF;
static const int WWWW = 0xFF;
/// Shuffle the lane values. [mask] must be one of the 256 shuffle constants.
Uint32x4 shuffle(int mask);
/// Shuffle the lane values in [this] and [other]. The returned
/// Uint32x4 will have XY lanes from [this] and ZW lanes from [other].
/// Uses the same [mask] as [shuffle].
Uint32x4 shuffleMix(Uint32x4 other, int mask);
/// Returns a new [Uint32x4] copied from [this] with a new x value.
Uint32x4 withX(int x);
/// Returns a new [Uint32x4] copied from [this] with a new y value.

View file

@ -88,6 +88,14 @@ LibTest/collection/HasNextIterator/HasNextIterator_A01_t01: Fail, OK
# co19 issue #623: main() { {}; } is block and empty statement, not a map
Language/13_Statements/02_Expression_Statements_A01_t13: Fail, OK
# co19 issue #650: two argument shuffles have been refactored.
LibTest/typed_data/Float32x4/interleaveZWPairs_A01_t01: Fail # co19 issue 650
LibTest/typed_data/Float32x4/interleaveZW_A01_t01: Fail # co19 issue 650
LibTest/typed_data/Float32x4/withZWInXY_A01_t01: Fail # co19 issue 650
LibTest/typed_data/Float32x4/interleaveXY_A01_t01: Fail # co19 issue 650
LibTest/typed_data/Float32x4/interleaveXYPairs_A01_t01: Fail # co19 issue 650
# co19 issue #626: StreamTransformers have been refactored.
LibTest/async/EventTransformStream/EventTransformStream_A01_t01: Fail
LibTest/async/EventTransformStream/EventTransformStream_A01_t02: Fail

View file

@ -71,6 +71,13 @@ LibTest/collection/HasNextIterator/HasNextIterator_A01_t01: Fail, OK
# co19 issue #623: main() { {}; } is block and empty statement, not a map
Language/13_Statements/02_Expression_Statements_A01_t13: Fail, OK
# co19 issue #650: two argument shuffles have been refactored.
LibTest/typed_data/Float32x4/interleaveZWPairs_A01_t01: Fail # co19 issue 650
LibTest/typed_data/Float32x4/interleaveZW_A01_t01: Fail # co19 issue 650
LibTest/typed_data/Float32x4/withZWInXY_A01_t01: Fail # co19 issue 650
LibTest/typed_data/Float32x4/interleaveXY_A01_t01: Fail # co19 issue 650
LibTest/typed_data/Float32x4/interleaveXYPairs_A01_t01: Fail # co19 issue 650
# co19 issue #626: StreamTransformers have been refactored.
LibTest/async/EventTransformStream/EventTransformStream_A01_t01: Fail
LibTest/async/EventTransformStream/EventTransformStream_A01_t02: Fail

View file

@ -67,6 +67,11 @@ LibTest/isolate/SendPort/send_A02_t01: CompileTimeError # Issue 13683
LibTest/math/exp_A01_t01: Fail # Issue co19 - 44
LibTest/math/sin_A01_t01: Fail # Inherited from VM.
LibTest/math/tan_A01_t01: Fail # Issue co19 - 44
LibTest/typed_data/Float32x4/interleaveZWPairs_A01_t01: Fail # co19 issue 650
LibTest/typed_data/Float32x4/interleaveZW_A01_t01: Fail # co19 issue 650
LibTest/typed_data/Float32x4/withZWInXY_A01_t01: Fail # co19 issue 650
LibTest/typed_data/Float32x4/interleaveXY_A01_t01: Fail # co19 issue 650
LibTest/typed_data/Float32x4/interleaveXYPairs_A01_t01: Fail # co19 issue 650
[ $compiler == dart2dart && $system == windows ]

View file

@ -53,6 +53,11 @@ LibTest/typed_data/Uint16List/Uint16List_A02_t01: fail # co19-roll r576: Please
LibTest/typed_data/Uint32List/Uint32List_A02_t01: fail # co19-roll r576: Please triage this failure
LibTest/typed_data/Uint8ClampedList/Uint8ClampedList_A02_t01: fail # co19-roll r576: Please triage this failure
LibTest/typed_data/Uint8List/Uint8List_A02_t01: fail # co19-roll r576: Please triage this failure
LibTest/typed_data/Float32x4/interleaveZWPairs_A01_t01: Fail # co19 issue 650
LibTest/typed_data/Float32x4/interleaveZW_A01_t01: Fail # co19 issue 650
LibTest/typed_data/Float32x4/withZWInXY_A01_t01: Fail # co19 issue 650
LibTest/typed_data/Float32x4/interleaveXY_A01_t01: Fail # co19 issue 650
LibTest/typed_data/Float32x4/interleaveXYPairs_A01_t01: Fail # co19 issue 650
[ $compiler == dart2js && $runtime != ie9 ]
LibTest/typed_data/ByteData/ByteData_A02_t01: fail # co19-roll r576: Please triage this failure

View file

@ -57,6 +57,11 @@ LibTest/core/RegExp/Pattern_semantics/splitQueryString_A02_t01: RuntimeError # c
LibTest/core/Symbol/Symbol_A01_t03: RuntimeError # co19-roll r607: Please triage this failure
LibTest/core/Symbol/Symbol_A01_t05: RuntimeError # co19-roll r607: Please triage this failure
LibTest/typed_data/Float32x4/clamp_A01_t01: Pass, Fail # co19 issue 636
LibTest/typed_data/Float32x4/interleaveZWPairs_A01_t01: Fail # co19 issue 650
LibTest/typed_data/Float32x4/interleaveZW_A01_t01: Fail # co19 issue 650
LibTest/typed_data/Float32x4/withZWInXY_A01_t01: Fail # co19 issue 650
LibTest/typed_data/Float32x4/interleaveXY_A01_t01: Fail # co19 issue 650
LibTest/typed_data/Float32x4/interleaveXYPairs_A01_t01: Fail # co19 issue 650
[ $compiler == none && $runtime == vm ]
LibTest/typed_data/Float32x4/reciprocalSqrt_A01_t01: Pass, Fail # Issue 13398

View file

@ -15,14 +15,16 @@ void transpose(Float32x4List m) {
var m1 = m[1];
var m2 = m[2];
var m3 = m[3];
var t0 = m0.interleaveXY(m1);
var t1 = m2.interleaveXY(m3);
var t2 = m0.interleaveZW(m1);
var t3 = m2.interleaveZW(m3);
m[0] = t0.interleaveXYPairs(t1);
m[1] = t0.interleaveZWPairs(t1);
m[2] = t2.interleaveXYPairs(t3);
m[3] = t2.interleaveZWPairs(t3);
var t0 = m0.shuffleMix(m1, Float32x4.XYXY);
var t1 = m2.shuffleMix(m3, Float32x4.XYXY);
m[0] = t0.shuffleMix(t1, Float32x4.XZXZ);
m[1] = t0.shuffleMix(t1, Float32x4.YWYW);
var t2 = m0.shuffleMix(m1, Float32x4.ZWZW);
var t3 = m2.shuffleMix(m3, Float32x4.ZWZW);
m[2] = t2.shuffleMix(t3, Float32x4.XZXZ);
m[3] = t2.shuffleMix(t3, Float32x4.YWYW);
}
void testTranspose(Float32x4List m, Float32x4List r) {

View file

@ -12,7 +12,7 @@ import 'dart:typed_data';
testWithZWInXY() {
Float32x4 a = new Float32x4(1.0, 2.0, 3.0, 4.0);
Float32x4 b = new Float32x4(5.0, 6.0, 7.0, 8.0);
Float32x4 c = a.withZWInXY(b);
Float32x4 c = b.shuffleMix(a, Float32x4.ZWZW);
Expect.equals(7.0, c.x);
Expect.equals(8.0, c.y);
Expect.equals(3.0, c.z);
@ -22,7 +22,7 @@ testWithZWInXY() {
testInterleaveXY() {
Float32x4 a = new Float32x4(1.0, 2.0, 3.0, 4.0);
Float32x4 b = new Float32x4(5.0, 6.0, 7.0, 8.0);
Float32x4 c = a.interleaveXY(b);
Float32x4 c = a.shuffleMix(b, Float32x4.XYXY).shuffle(Float32x4.XZYW);
Expect.equals(1.0, c.x);
Expect.equals(5.0, c.y);
Expect.equals(2.0, c.z);
@ -32,7 +32,7 @@ testInterleaveXY() {
testInterleaveZW() {
Float32x4 a = new Float32x4(1.0, 2.0, 3.0, 4.0);
Float32x4 b = new Float32x4(5.0, 6.0, 7.0, 8.0);
Float32x4 c = a.interleaveZW(b);
Float32x4 c = a.shuffleMix(b, Float32x4.ZWZW).shuffle(Float32x4.XZYW);
Expect.equals(3.0, c.x);
Expect.equals(7.0, c.y);
Expect.equals(4.0, c.z);
@ -42,7 +42,7 @@ testInterleaveZW() {
testInterleaveXYPairs() {
Float32x4 a = new Float32x4(1.0, 2.0, 3.0, 4.0);
Float32x4 b = new Float32x4(5.0, 6.0, 7.0, 8.0);
Float32x4 c = a.interleaveXYPairs(b);
Float32x4 c = a.shuffleMix(b, Float32x4.XYXY);
Expect.equals(1.0, c.x);
Expect.equals(2.0, c.y);
Expect.equals(5.0, c.z);
@ -52,7 +52,7 @@ testInterleaveXYPairs() {
testInterleaveZWPairs() {
Float32x4 a = new Float32x4(1.0, 2.0, 3.0, 4.0);
Float32x4 b = new Float32x4(5.0, 6.0, 7.0, 8.0);
Float32x4 c = a.interleaveZWPairs(b);
Float32x4 c = a.shuffleMix(b, Float32x4.ZWZW);
Expect.equals(3.0, c.x);
Expect.equals(4.0, c.y);
Expect.equals(7.0, c.z);

View file

@ -0,0 +1,59 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// VMOptions=--optimization-counter-threshold=10
// Library tag to be able to run in html test framework.
library uint32x4_shuffle_test;
import "package:expect/expect.dart";
import 'dart:typed_data';
void testShuffle() {
var m = new Uint32x4(1, 2, 3, 4);
var c;
c = m.shuffle(Uint32x4.WZYX);
Expect.equals(4, c.x);
Expect.equals(3, c.y);
Expect.equals(2, c.z);
Expect.equals(1, c.w);
}
void testShuffleNonConstant(mask) {
var m = new Uint32x4(1, 2, 3, 4);
var c;
c = m.shuffle(mask);
if (mask == 1) {
Expect.equals(2, c.x);
Expect.equals(1, c.y);
Expect.equals(1, c.z);
Expect.equals(1, c.w);
} else {
Expect.equals(Uint32x4.YYYY + 1, mask);
Expect.equals(3, c.x);
Expect.equals(2, c.y);
Expect.equals(2, c.z);
Expect.equals(2, c.w);
}
}
void testShuffleMix() {
var m = new Uint32x4(1, 2, 3, 4);
var n = new Uint32x4(5, 6, 7, 8);
var c = m.shuffleMix(n, Uint32x4.XYXY);
Expect.equals(1, c.x);
Expect.equals(2, c.y);
Expect.equals(5, c.z);
Expect.equals(6, c.w);
}
main() {
var xxxx = Uint32x4.XXXX + 1;
var yyyy = Uint32x4.YYYY + 1;
for (int i = 0; i < 20; i++) {
testShuffle();
testShuffleNonConstant(xxxx);
testShuffleNonConstant(yyyy);
testShuffleMix();
}
}