Version 2.19.0-60.0.dev
Merge commit 'd94a1cd419d8d644516336f9bbeae2e751ecdbf1' into 'dev'
diff --git a/runtime/tests/vm/dart/causal_stacks/utils.dart b/runtime/tests/vm/dart/causal_stacks/utils.dart
index 2269e31..4356953 100644
--- a/runtime/tests/vm/dart/causal_stacks/utils.dart
+++ b/runtime/tests/vm/dart/causal_stacks/utils.dart
@@ -205,21 +205,26 @@
// Use the DWARF stack decoder if we're running in --dwarf-stack-traces mode
// and in precompiled mode (otherwise --dwarf-stack-traces has no effect).
- final decodeTrace = frames.first.startsWith('Warning:');
- if (decodeTrace) {
- Expect.isNotNull(debugInfoFilename);
- final dwarf = Dwarf.fromFile(debugInfoFilename!)!;
- frames = await Stream.fromIterable(original)
- .transform(DwarfStackTraceDecoder(dwarf))
- .where(_lineRE.hasMatch)
- .toList();
+ bool usingDwarf = false;
+ if (debugInfoFilename != null) {
+ try {
+ final dwarf = Dwarf.fromFile(debugInfoFilename)!;
+ usingDwarf = true;
+ frames = await Stream.fromIterable(original)
+ .transform(DwarfStackTraceDecoder(dwarf))
+ .where(_lineRE.hasMatch)
+ .toList();
+ } on FileSystemException {
+ // We're not running in precompiled mode, so the file doesn't exist and
+ // we can continue normally.
+ }
}
void printFrameInformation() {
print('RegExps for expected stack:');
expects.forEach((s) => print('"${s}"'));
print('');
- if (decodeTrace) {
+ if (usingDwarf) {
print('Non-symbolic actual stack:');
original.forEach(print);
print('');
diff --git a/runtime/tests/vm/dart_2/causal_stacks/utils.dart b/runtime/tests/vm/dart_2/causal_stacks/utils.dart
index d7c80d1..ec673b5 100644
--- a/runtime/tests/vm/dart_2/causal_stacks/utils.dart
+++ b/runtime/tests/vm/dart_2/causal_stacks/utils.dart
@@ -207,21 +207,26 @@
// Use the DWARF stack decoder if we're running in --dwarf-stack-traces mode
// and in precompiled mode (otherwise --dwarf-stack-traces has no effect).
- final decodeTrace = frames.first.startsWith('Warning:');
- if (decodeTrace) {
- Expect.isNotNull(debugInfoFilename);
- final dwarf = Dwarf.fromFile(debugInfoFilename);
- frames = await Stream.fromIterable(original)
- .transform(DwarfStackTraceDecoder(dwarf))
- .where(_lineRE.hasMatch)
- .toList();
+ bool usingDwarf = false;
+ if (debugInfoFilename != null) {
+ try {
+ final dwarf = Dwarf.fromFile(debugInfoFilename);
+ usingDwarf = true;
+ frames = await Stream.fromIterable(original)
+ .transform(DwarfStackTraceDecoder(dwarf))
+ .where(_lineRE.hasMatch)
+ .toList();
+ } on FileSystemException {
+ // We're not running in precompiled mode, so the file doesn't exist and
+ // we can continue normally.
+ }
}
void printFrameInformation() {
print('RegExps for expected stack:');
expects.forEach((s) => print('"${s}"'));
print('');
- if (decodeTrace) {
+ if (usingDwarf) {
print('Non-symbolic actual stack:');
original.forEach(print);
print('');
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.cc b/runtime/vm/compiler/assembler/assembler_arm64.cc
index 02122a3..64576491 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm64.cc
@@ -662,20 +662,6 @@
}
}
-void Assembler::LoadSImmediate(VRegister vd, float imms) {
- int32_t imm32 = bit_cast<int32_t, float>(imms);
- if (imm32 == 0) {
- veor(vd, vd, vd);
- } else if (constant_pool_allowed()) {
- intptr_t index = object_pool_builder().FindImmediate(imm32);
- intptr_t offset = target::ObjectPool::element_offset(index);
- LoadSFromOffset(vd, PP, offset);
- } else {
- LoadImmediate(TMP, imm32);
- fmovsr(vd, TMP);
- }
-}
-
void Assembler::LoadDImmediate(VRegister vd, double immd) {
if (fmovdi(vd, immd)) return;
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.h b/runtime/vm/compiler/assembler/assembler_arm64.h
index 56b0fda..ea47f52 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.h
+++ b/runtime/vm/compiler/assembler/assembler_arm64.h
@@ -2066,7 +2066,6 @@
LoadImmediate(reg, imm.value());
}
- void LoadSImmediate(VRegister reg, float immd);
void LoadDImmediate(VRegister reg, double immd);
void LoadQImmediate(VRegister reg, simd128_value_t immq);
diff --git a/runtime/vm/compiler/assembler/assembler_ia32.cc b/runtime/vm/compiler/assembler/assembler_ia32.cc
index 73d84a5..51c1fa9 100644
--- a/runtime/vm/compiler/assembler/assembler_ia32.cc
+++ b/runtime/vm/compiler/assembler/assembler_ia32.cc
@@ -2199,13 +2199,6 @@
addl(dest, inc_imm);
}
-void Assembler::LoadSImmediate(XmmRegister dst, float value) {
- int32_t constant = bit_cast<int32_t, float>(value);
- pushl(Immediate(constant));
- movss(dst, Address(ESP, 0));
- addl(ESP, Immediate(target::kWordSize));
-}
-
void Assembler::LoadDImmediate(XmmRegister dst, double value) {
// TODO(5410843): Need to have a code constants table.
int64_t constant = bit_cast<int64_t, double>(value);
diff --git a/runtime/vm/compiler/assembler/assembler_ia32.h b/runtime/vm/compiler/assembler/assembler_ia32.h
index 77b453b..7ef5339 100644
--- a/runtime/vm/compiler/assembler/assembler_ia32.h
+++ b/runtime/vm/compiler/assembler/assembler_ia32.h
@@ -759,7 +759,6 @@
LoadImmediate(reg, immediate.value());
}
- void LoadSImmediate(XmmRegister dst, float value);
void LoadDImmediate(XmmRegister dst, double value);
void Drop(intptr_t stack_elements);
diff --git a/runtime/vm/compiler/assembler/assembler_riscv.cc b/runtime/vm/compiler/assembler/assembler_riscv.cc
index 08a4b28..10beeac 100644
--- a/runtime/vm/compiler/assembler/assembler_riscv.cc
+++ b/runtime/vm/compiler/assembler/assembler_riscv.cc
@@ -3351,18 +3351,6 @@
}
}
-void Assembler::LoadSImmediate(FRegister reg, float imms) {
- int32_t imm = bit_cast<int32_t, float>(imms);
- if (imm == 0) {
- fmvwx(reg, ZR); // bit_cast uint32_t -> float
- } else {
- ASSERT(constant_pool_allowed());
- intptr_t index = object_pool_builder().FindImmediate(imm);
- intptr_t offset = target::ObjectPool::element_offset(index);
- LoadSFromOffset(reg, PP, offset);
- }
-}
-
void Assembler::LoadDImmediate(FRegister reg, double immd) {
int64_t imm = bit_cast<int64_t, double>(immd);
if (imm == 0) {
diff --git a/runtime/vm/compiler/assembler/assembler_riscv.h b/runtime/vm/compiler/assembler/assembler_riscv.h
index 18eeb4a..cefa220 100644
--- a/runtime/vm/compiler/assembler/assembler_riscv.h
+++ b/runtime/vm/compiler/assembler/assembler_riscv.h
@@ -432,8 +432,6 @@
void feqs(Register rd, FRegister rs1, FRegister rs2);
void flts(Register rd, FRegister rs1, FRegister rs2);
void fles(Register rd, FRegister rs1, FRegister rs2);
- void fgts(Register rd, FRegister rs1, FRegister rs2) { flts(rd, rs2, rs1); }
- void fges(Register rd, FRegister rs1, FRegister rs2) { fles(rd, rs2, rs1); }
void fclasss(Register rd, FRegister rs1);
// int32_t <- float
void fcvtws(Register rd, FRegister rs1, RoundingMode rounding = RNE);
@@ -519,8 +517,6 @@
void feqd(Register rd, FRegister rs1, FRegister rs2);
void fltd(Register rd, FRegister rs1, FRegister rs2);
void fled(Register rd, FRegister rs1, FRegister rs2);
- void fgtd(Register rd, FRegister rs1, FRegister rs2) { fltd(rd, rs2, rs1); }
- void fged(Register rd, FRegister rs1, FRegister rs2) { fled(rd, rs2, rs1); }
void fclassd(Register rd, FRegister rs1);
// int32_t <- double
void fcvtwd(Register rd, FRegister rs1, RoundingMode rounding = RNE);
@@ -1022,9 +1018,6 @@
Register index);
void LoadSFromOffset(FRegister dest, Register base, int32_t offset);
void LoadDFromOffset(FRegister dest, Register base, int32_t offset);
- void LoadSFieldFromOffset(FRegister dest, Register base, int32_t offset) {
- LoadSFromOffset(dest, base, offset - kHeapObjectTag);
- }
void LoadDFieldFromOffset(FRegister dest, Register base, int32_t offset) {
LoadDFromOffset(dest, base, offset - kHeapObjectTag);
}
@@ -1050,9 +1043,6 @@
sx(ZR, address);
}
void StoreSToOffset(FRegister src, Register base, int32_t offset);
- void StoreSFieldToOffset(FRegister src, Register base, int32_t offset) {
- StoreSToOffset(src, base, offset - kHeapObjectTag);
- }
void StoreDToOffset(FRegister src, Register base, int32_t offset);
void StoreDFieldToOffset(FRegister src, Register base, int32_t offset) {
StoreDToOffset(src, base, offset - kHeapObjectTag);
@@ -1192,7 +1182,6 @@
// Note: the function never clobbers TMP, TMP2 scratch registers.
void LoadImmediate(Register reg, intx_t imm);
- void LoadSImmediate(FRegister reg, float imms);
void LoadDImmediate(FRegister reg, double immd);
void LoadQImmediate(FRegister reg, simd128_value_t immq);
diff --git a/runtime/vm/compiler/assembler/assembler_x64.cc b/runtime/vm/compiler/assembler/assembler_x64.cc
index b7e098c..bfed044 100644
--- a/runtime/vm/compiler/assembler/assembler_x64.cc
+++ b/runtime/vm/compiler/assembler/assembler_x64.cc
@@ -1394,17 +1394,6 @@
}
}
-void Assembler::LoadSImmediate(FpuRegister dst, float immediate) {
- int32_t bits = bit_cast<int32_t>(immediate);
- if (bits == 0) {
- xorps(dst, dst);
- } else {
- intptr_t index = object_pool_builder().FindImmediate(bits);
- LoadUnboxedSingle(
- dst, PP, target::ObjectPool::element_offset(index) - kHeapObjectTag);
- }
-}
-
void Assembler::LoadDImmediate(FpuRegister dst, double immediate) {
int64_t bits = bit_cast<int64_t>(immediate);
if (bits == 0) {
diff --git a/runtime/vm/compiler/assembler/assembler_x64.h b/runtime/vm/compiler/assembler/assembler_x64.h
index d0b48f8..eafff9b 100644
--- a/runtime/vm/compiler/assembler/assembler_x64.h
+++ b/runtime/vm/compiler/assembler/assembler_x64.h
@@ -787,7 +787,6 @@
void LoadImmediate(Register reg, int32_t immediate) {
LoadImmediate(reg, Immediate(immediate));
}
- void LoadSImmediate(FpuRegister dst, float immediate);
void LoadDImmediate(FpuRegister dst, double immediate);
void LoadQImmediate(FpuRegister dst, simd128_value_t immediate);
@@ -1083,9 +1082,6 @@
movq(Address(base, offset), src);
}
- void LoadUnboxedSingle(FpuRegister dst, Register base, int32_t offset) {
- movss(dst, Address(base, offset));
- }
void LoadUnboxedDouble(FpuRegister dst, Register base, int32_t offset) {
movsd(dst, Address(base, offset));
}
diff --git a/runtime/vm/compiler/backend/block_builder.h b/runtime/vm/compiler/backend/block_builder.h
index de4c656..4a36631 100644
--- a/runtime/vm/compiler/backend/block_builder.h
+++ b/runtime/vm/compiler/backend/block_builder.h
@@ -136,8 +136,6 @@
entry_->AsJoinEntry()->InsertPhi(phi);
}
- Instruction* last() const { return current_; }
-
private:
static CompileType* TypeForRepresentation(Representation rep) {
switch (rep) {
diff --git a/runtime/vm/compiler/backend/constant_propagator.cc b/runtime/vm/compiler/backend/constant_propagator.cc
index 8e53015..8456490 100644
--- a/runtime/vm/compiler/backend/constant_propagator.cc
+++ b/runtime/vm/compiler/backend/constant_propagator.cc
@@ -872,16 +872,6 @@
}
}
-void ConstantPropagator::VisitBoolToInt(BoolToIntInstr* instr) {
- // TODO(riscv)
- SetValue(instr, non_constant_);
-}
-
-void ConstantPropagator::VisitIntToBool(IntToBoolInstr* instr) {
- // TODO(riscv)
- SetValue(instr, non_constant_);
-}
-
void ConstantPropagator::VisitInstanceOf(InstanceOfInstr* instr) {
Definition* def = instr->value()->definition();
const Object& value = def->constant_value();
@@ -1226,27 +1216,8 @@
VisitUnaryIntegerOp(instr);
}
-static bool IsIntegerOrDouble(const Object& value) {
- return value.IsInteger() || value.IsDouble();
-}
-
-static double ToDouble(const Object& value) {
- return value.IsInteger() ? Integer::Cast(value).AsDoubleValue()
- : Double::Cast(value).value();
-}
-
void ConstantPropagator::VisitUnaryDoubleOp(UnaryDoubleOpInstr* instr) {
- const Object& value = instr->value()->definition()->constant_value();
- if (IsUnknown(value)) {
- return;
- }
- if (value.IsDouble()) {
- const double result_val = Evaluator::EvaluateUnaryDoubleOp(
- ToDouble(value), instr->op_kind(), instr->representation());
- const Double& result = Double::ZoneHandle(Double::NewCanonical(result_val));
- SetValue(instr, result);
- return;
- }
+ // TODO(kmillikin): Handle unary operations.
SetValue(instr, non_constant_);
}
@@ -1302,6 +1273,11 @@
SetValue(instr, non_constant_);
}
+void ConstantPropagator::VisitDoubleToDouble(DoubleToDoubleInstr* instr) {
+ // TODO(kmillikin): Handle conversion.
+ SetValue(instr, non_constant_);
+}
+
void ConstantPropagator::VisitDoubleToFloat(DoubleToFloatInstr* instr) {
// TODO(kmillikin): Handle conversion.
SetValue(instr, non_constant_);
@@ -1312,11 +1288,6 @@
SetValue(instr, non_constant_);
}
-void ConstantPropagator::VisitFloatCompare(FloatCompareInstr* instr) {
- // TODO(riscv)
- SetValue(instr, non_constant_);
-}
-
void ConstantPropagator::VisitInvokeMathCFunction(
InvokeMathCFunctionInstr* instr) {
// TODO(kmillikin): Handle conversion.
@@ -1332,25 +1303,6 @@
SetValue(instr, non_constant_);
}
-void ConstantPropagator::VisitUnboxLane(UnboxLaneInstr* instr) {
- if (BoxLanesInstr* box = instr->value()->definition()->AsBoxLanes()) {
- const Object& value =
- box->InputAt(instr->lane())->definition()->constant_value();
- if (IsUnknown(value)) {
- return;
- }
- SetValue(instr, value);
- return;
- }
-
- SetValue(instr, non_constant_);
-}
-
-void ConstantPropagator::VisitBoxLanes(BoxLanesInstr* instr) {
- // TODO(riscv)
- SetValue(instr, non_constant_);
-}
-
void ConstantPropagator::VisitConstant(ConstantInstr* instr) {
SetValue(instr, instr->value());
}
@@ -1369,6 +1321,15 @@
UNREACHABLE();
}
+static bool IsIntegerOrDouble(const Object& value) {
+ return value.IsInteger() || value.IsDouble();
+}
+
+static double ToDouble(const Object& value) {
+ return value.IsInteger() ? Integer::Cast(value).AsDoubleValue()
+ : Double::Cast(value).value();
+}
+
void ConstantPropagator::VisitBinaryDoubleOp(BinaryDoubleOpInstr* instr) {
const Object& left = instr->left()->definition()->constant_value();
const Object& right = instr->right()->definition()->constant_value();
@@ -1382,9 +1343,8 @@
const bool both_are_integers = left.IsInteger() && right.IsInteger();
if (IsIntegerOrDouble(left) && IsIntegerOrDouble(right) &&
!both_are_integers) {
- const double result_val = Evaluator::EvaluateBinaryDoubleOp(
- ToDouble(left), ToDouble(right), instr->op_kind(),
- instr->representation());
+ const double result_val = Evaluator::EvaluateDoubleOp(
+ ToDouble(left), ToDouble(right), instr->op_kind());
const Double& result = Double::ZoneHandle(Double::NewCanonical(result_val));
SetValue(instr, result);
return;
@@ -1424,6 +1384,11 @@
SetValue(instr, non_constant_);
}
+void ConstantPropagator::VisitMathUnary(MathUnaryInstr* instr) {
+ // TODO(kmillikin): Handle Math's unary operations (sqrt, cos, sin).
+ SetValue(instr, non_constant_);
+}
+
void ConstantPropagator::VisitMathMinMax(MathMinMaxInstr* instr) {
// TODO(srdjan): Handle min and max.
SetValue(instr, non_constant_);
diff --git a/runtime/vm/compiler/backend/evaluator.cc b/runtime/vm/compiler/backend/evaluator.cc
index 2f9e3b3..9ab7d39 100644
--- a/runtime/vm/compiler/backend/evaluator.cc
+++ b/runtime/vm/compiler/backend/evaluator.cc
@@ -189,91 +189,20 @@
return result.ptr();
}
-double Evaluator::EvaluateUnaryDoubleOp(const double value,
- Token::Kind token_kind,
- Representation representation) {
- // The different set of operations for float32 and float64 is due to the
- // different set of operations made available by dart:core.double and
- // dart:typed_data.Float64x2 versus dart:typed_data.Float32x4.
- if (representation == kUnboxedDouble) {
- switch (token_kind) {
- case Token::kABS:
- return fabs(value);
- case Token::kNEGATE:
- return -value;
- case Token::kSQRT:
- return sqrt(value);
- case Token::kSQUARE:
- return value * value;
- case Token::kTRUNCATE:
- return trunc(value);
- case Token::kFLOOR:
- return floor(value);
- case Token::kCEILING:
- return ceil(value);
- default:
- UNREACHABLE();
- }
- } else {
- ASSERT(representation == kUnboxedFloat);
- switch (token_kind) {
- case Token::kABS:
- return fabsf(static_cast<float>(value));
- case Token::kNEGATE:
- return -static_cast<float>(value);
- case Token::kRECIPROCAL:
- return 1.0f / static_cast<float>(value);
- case Token::kRECIPROCAL_SQRT:
- return sqrtf(1.0f / static_cast<float>(value));
- case Token::kSQRT:
- return sqrtf(static_cast<float>(value));
- case Token::kSQUARE:
- return static_cast<float>(value) * static_cast<float>(value);
- default:
- UNREACHABLE();
- }
- }
-}
-
-double Evaluator::EvaluateBinaryDoubleOp(const double left,
- const double right,
- Token::Kind token_kind,
- Representation representation) {
- if (representation == kUnboxedDouble) {
- switch (token_kind) {
- case Token::kADD:
- return left + right;
- case Token::kSUB:
- return left - right;
- case Token::kMUL:
- return left * right;
- case Token::kDIV:
- return left / right;
- case Token::kMIN:
- return fmin(left, right);
- case Token::kMAX:
- return fmax(left, right);
- default:
- UNREACHABLE();
- }
- } else {
- ASSERT(representation == kUnboxedFloat);
- switch (token_kind) {
- case Token::kADD:
- return static_cast<float>(left) + static_cast<float>(right);
- case Token::kSUB:
- return static_cast<float>(left) - static_cast<float>(right);
- case Token::kMUL:
- return static_cast<float>(left) * static_cast<float>(right);
- case Token::kDIV:
- return static_cast<float>(left) / static_cast<float>(right);
- case Token::kMIN:
- return fminf(static_cast<float>(left), static_cast<float>(right));
- case Token::kMAX:
- return fmaxf(static_cast<float>(left), static_cast<float>(right));
- default:
- UNREACHABLE();
- }
+double Evaluator::EvaluateDoubleOp(const double left,
+ const double right,
+ Token::Kind token_kind) {
+ switch (token_kind) {
+ case Token::kADD:
+ return left + right;
+ case Token::kSUB:
+ return left - right;
+ case Token::kMUL:
+ return left * right;
+ case Token::kDIV:
+ return left / right;
+ default:
+ UNREACHABLE();
}
}
diff --git a/runtime/vm/compiler/backend/evaluator.h b/runtime/vm/compiler/backend/evaluator.h
index afd05ed..dca583a 100644
--- a/runtime/vm/compiler/backend/evaluator.h
+++ b/runtime/vm/compiler/backend/evaluator.h
@@ -44,16 +44,10 @@
Representation representation,
Thread* thread);
- // Evaluates a unary double operation and returns the result.
- static double EvaluateUnaryDoubleOp(const double value,
- Token::Kind token_kind,
- Representation representation);
-
// Evaluates a binary double operation and returns the result.
- static double EvaluateBinaryDoubleOp(const double left,
- const double right,
- Token::Kind token_kind,
- Representation representation);
+ static double EvaluateDoubleOp(const double left,
+ const double right,
+ Token::Kind token_kind);
// Returns whether the value is an int64, and returns the int64 value
// through the result parameter.
diff --git a/runtime/vm/compiler/backend/flow_graph.cc b/runtime/vm/compiler/backend/flow_graph.cc
index d167f2d..95691ce 100644
--- a/runtime/vm/compiler/backend/flow_graph.cc
+++ b/runtime/vm/compiler/backend/flow_graph.cc
@@ -220,7 +220,6 @@
case kUnboxedInt64:
return value.IsInteger();
- case kUnboxedFloat:
case kUnboxedDouble:
return value.IsInteger() || value.IsDouble();
@@ -239,13 +238,11 @@
return op;
}
- if (((representation == kUnboxedFloat) ||
- (representation == kUnboxedDouble)) &&
- value.IsInteger()) {
- // Convert the boxed constant from int to float/double.
+ if (representation == kUnboxedDouble && value.IsInteger()) {
+ // Convert the boxed constant from int to double.
return GetConstant(Double::Handle(Double::NewCanonical(
Integer::Cast(value).AsDoubleValue())),
- representation);
+ kUnboxedDouble);
}
return GetConstant(value, representation);
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.cc b/runtime/vm/compiler/backend/flow_graph_compiler.cc
index b0a50c6..6355ea9 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.cc
@@ -395,9 +395,6 @@
case kUnboxedUint32:
src_kind = CatchEntryMove::SourceKind::kUint32Slot;
break;
- case kUnboxedFloat:
- src_kind = CatchEntryMove::SourceKind::kFloatSlot;
- break;
case kUnboxedDouble:
src_kind = CatchEntryMove::SourceKind::kDoubleSlot;
break;
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index 6be93b4..e7f9172 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -547,8 +547,7 @@
while (true) {
Definition* orig;
if (def->IsConstraint() || def->IsBox() || def->IsUnbox() ||
- def->IsIntConverter() || def->IsFloatToDouble() ||
- def->IsDoubleToFloat()) {
+ def->IsIntConverter()) {
orig = def->InputAt(0)->definition();
} else {
orig = def->OriginalDefinition();
@@ -2132,26 +2131,32 @@
}
Definition* DoubleToFloatInstr::Canonicalize(FlowGraph* flow_graph) {
+#ifdef DEBUG
+ // Must only be used in Float32 StoreIndexedInstr, FloatToDoubleInstr,
+ // Phis introduce by load forwarding, or MaterializeObject for
+ // eliminated Float32 array.
+ ASSERT(env_use_list() == NULL);
+ for (Value* use = input_use_list(); use != NULL; use = use->next_use()) {
+ ASSERT(use->instruction()->IsPhi() ||
+ use->instruction()->IsFloatToDouble() ||
+ (use->instruction()->IsStoreIndexed() &&
+ (use->instruction()->AsStoreIndexed()->class_id() ==
+ kTypedDataFloat32ArrayCid)) ||
+ (use->instruction()->IsMaterializeObject() &&
+ (use->instruction()->AsMaterializeObject()->cls().id() ==
+ kTypedDataFloat32ArrayCid)));
+ }
+#endif
if (!HasUses()) return NULL;
if (value()->definition()->IsFloatToDouble()) {
// F2D(D2F(v)) == v.
return value()->definition()->AsFloatToDouble()->value()->definition();
}
- if (value()->BindsToConstant()) {
- double narrowed_val =
- static_cast<float>(Double::Cast(value()->BoundConstant()).value());
- return flow_graph->GetConstant(
- Double::ZoneHandle(Double::NewCanonical(narrowed_val)), kUnboxedFloat);
- }
return this;
}
Definition* FloatToDoubleInstr::Canonicalize(FlowGraph* flow_graph) {
- if (!HasUses()) return NULL;
- if (value()->BindsToConstant()) {
- return flow_graph->GetConstant(value()->BoundConstant(), kUnboxedDouble);
- }
- return this;
+ return HasUses() ? this : NULL;
}
Definition* BinaryDoubleOpInstr::Canonicalize(FlowGraph* flow_graph) {
@@ -2171,11 +2176,11 @@
if ((op_kind() == Token::kMUL) &&
(left()->definition() == right()->definition())) {
- UnaryDoubleOpInstr* square = new UnaryDoubleOpInstr(
- Token::kSQUARE, new Value(left()->definition()), DeoptimizationTarget(),
- speculative_mode_, representation());
- flow_graph->InsertBefore(this, square, env(), FlowGraph::kValue);
- return square;
+ MathUnaryInstr* math_unary = new MathUnaryInstr(
+ MathUnaryInstr::kDoubleSquare, new Value(left()->definition()),
+ DeoptimizationTarget());
+ flow_graph->InsertBefore(this, math_unary, env(), FlowGraph::kValue);
+ return math_unary;
}
return this;
@@ -2616,6 +2621,13 @@
return HasUses() ? this : NULL;
}
+// A math unary instruction has a side effect (exception
+// thrown) if the argument is not a number.
+// TODO(srdjan): eliminate if has no uses and input is guaranteed to be number.
+Definition* MathUnaryInstr::Canonicalize(FlowGraph* flow_graph) {
+ return this;
+}
+
bool LoadFieldInstr::TryEvaluateLoad(const Object& instance,
const Slot& field,
Object* result) {
@@ -2980,30 +2992,12 @@
if ((unbox_defn != NULL) &&
(unbox_defn->representation() == from_representation()) &&
(unbox_defn->value()->Type()->ToCid() == Type()->ToCid())) {
- if (from_representation() == kUnboxedFloat) {
- // This is a narrowing conversion.
- return this;
- }
return unbox_defn->value()->definition();
}
return this;
}
-Definition* BoxLanesInstr::Canonicalize(FlowGraph* flow_graph) {
- return HasUses() ? this : NULL;
-}
-
-Definition* UnboxLaneInstr::Canonicalize(FlowGraph* flow_graph) {
- if (!HasUses()) return NULL;
-
- if (BoxLanesInstr* box = value()->definition()->AsBoxLanes()) {
- return box->InputAt(lane())->definition();
- }
-
- return this;
-}
-
bool BoxIntegerInstr::ValueFitsSmi() const {
Range* range = value()->definition()->range();
return RangeUtils::Fits(range, RangeBoundary::kRangeBoundarySmi);
@@ -3060,28 +3054,11 @@
Definition* UnboxInstr::Canonicalize(FlowGraph* flow_graph) {
if (!HasUses() && !CanDeoptimize()) return NULL;
+ // Fold away Unbox<rep>(Box<rep>(v)).
BoxInstr* box_defn = value()->definition()->AsBox();
- if (box_defn != NULL) {
- // Fold away Unbox<rep>(Box<rep>(v)).
- if (box_defn->from_representation() == representation()) {
- return box_defn->value()->definition();
- }
-
- if ((box_defn->from_representation() == kUnboxedDouble) &&
- (representation() == kUnboxedFloat)) {
- Definition* replacement = new DoubleToFloatInstr(
- box_defn->value()->CopyWithType(), DeoptId::kNone);
- flow_graph->InsertBefore(this, replacement, NULL, FlowGraph::kValue);
- return replacement;
- }
-
- if ((box_defn->from_representation() == kUnboxedFloat) &&
- (representation() == kUnboxedDouble)) {
- Definition* replacement = new FloatToDoubleInstr(
- box_defn->value()->CopyWithType(), DeoptId::kNone);
- flow_graph->InsertBefore(this, replacement, NULL, FlowGraph::kValue);
- return replacement;
- }
+ if ((box_defn != NULL) &&
+ (box_defn->from_representation() == representation())) {
+ return box_defn->value()->definition();
}
if (representation() == kUnboxedDouble && value()->BindsToConstant()) {
@@ -3096,22 +3073,6 @@
}
}
- if (representation() == kUnboxedFloat && value()->BindsToConstant()) {
- const Object& val = value()->BoundConstant();
- if (val.IsInteger()) {
- double narrowed_val =
- static_cast<float>(Integer::Cast(val).AsDoubleValue());
- return flow_graph->GetConstant(
- Double::ZoneHandle(Double::NewCanonical(narrowed_val)),
- kUnboxedFloat);
- } else if (val.IsDouble()) {
- double narrowed_val = static_cast<float>(Double::Cast(val).value());
- return flow_graph->GetConstant(
- Double::ZoneHandle(Double::NewCanonical(narrowed_val)),
- kUnboxedFloat);
- }
- }
-
return this;
}
@@ -6470,6 +6431,19 @@
return kLibcPowRuntimeEntry;
}
+const char* MathUnaryInstr::KindToCString(MathUnaryKind kind) {
+ switch (kind) {
+ case kIllegal:
+ return "illegal";
+ case kSqrt:
+ return "sqrt";
+ case kDoubleSquare:
+ return "double-square";
+ }
+ UNREACHABLE();
+ return "";
+}
+
TruncDivModInstr::TruncDivModInstr(Value* lhs, Value* rhs, intptr_t deopt_id)
: TemplateDefinition(deopt_id) {
SetInputAt(0, lhs);
diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h
index d4df4c7..af9f8b1 100644
--- a/runtime/vm/compiler/backend/il.h
+++ b/runtime/vm/compiler/backend/il.h
@@ -451,8 +451,6 @@
M(LoadStaticField, _) \
M(StoreStaticField, kNoGC) \
M(BooleanNegate, kNoGC) \
- M(BoolToInt, kNoGC) \
- M(IntToBool, kNoGC) \
M(InstanceOf, _) \
M(CreateArray, _) \
M(AllocateObject, _) \
@@ -476,9 +474,9 @@
M(Int64ToDouble, kNoGC) \
M(DoubleToInteger, _) \
M(DoubleToSmi, kNoGC) \
+ M(DoubleToDouble, kNoGC) \
M(DoubleToFloat, kNoGC) \
M(FloatToDouble, kNoGC) \
- M(FloatCompare, kNoGC) \
M(CheckClass, kNoGC) \
M(CheckClassId, kNoGC) \
M(CheckSmi, kNoGC) \
@@ -489,6 +487,7 @@
M(CheckEitherNonSmi, kNoGC) \
M(BinaryDoubleOp, kNoGC) \
M(DoubleTestOp, kNoGC) \
+ M(MathUnary, kNoGC) \
M(MathMinMax, kNoGC) \
M(Box, _) \
M(Unbox, kNoGC) \
@@ -516,8 +515,6 @@
M(TestSmi, kNoGC) \
M(TestCids, kNoGC) \
M(ExtractNthOutput, kNoGC) \
- M(UnboxLane, kNoGC) \
- M(BoxLanes, _) \
M(BinaryUint32Op, kNoGC) \
M(ShiftUint32Op, kNoGC) \
M(SpeculativeShiftUint32Op, kNoGC) \
@@ -6254,58 +6251,6 @@
DISALLOW_COPY_AND_ASSIGN(BooleanNegateInstr);
};
-// bool ? -1 : 0
-class BoolToIntInstr : public TemplateDefinition<1, NoThrow> {
- public:
- explicit BoolToIntInstr(Value* value) {
- ASSERT(value->definition()->representation() == kTagged);
- SetInputAt(0, value);
- }
-
- DECLARE_INSTRUCTION(BoolToInt)
- virtual CompileType ComputeType() const;
-
- Value* value() const { return inputs_[0]; }
-
- virtual Representation RequiredInputRepresentation(intptr_t idx) const {
- return kTagged;
- }
- virtual Representation representation() const { return kUnboxedInt32; }
-
- virtual bool ComputeCanDeoptimize() const { return false; }
-
- virtual bool HasUnknownSideEffects() const { return false; }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(BoolToIntInstr);
-};
-
-// int == 0 ? false : true
-class IntToBoolInstr : public TemplateDefinition<1, NoThrow> {
- public:
- explicit IntToBoolInstr(Value* value) {
- ASSERT(value->definition()->representation() == kUnboxedInt32);
- SetInputAt(0, value);
- }
-
- DECLARE_INSTRUCTION(IntToBool)
- virtual CompileType ComputeType() const;
-
- Value* value() const { return inputs_[0]; }
-
- virtual Representation RequiredInputRepresentation(intptr_t idx) const {
- return kUnboxedInt32;
- }
- virtual Representation representation() const { return kTagged; }
-
- virtual bool ComputeCanDeoptimize() const { return false; }
-
- virtual bool HasUnknownSideEffects() const { return false; }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(IntToBoolInstr);
-};
-
class InstanceOfInstr : public TemplateDefinition<3, Throws> {
public:
InstanceOfInstr(const InstructionSource& source,
@@ -7545,6 +7490,60 @@
IsBoxInt64() || IsUnboxInt64();
}
+class MathUnaryInstr : public TemplateDefinition<1, NoThrow, Pure> {
+ public:
+ enum MathUnaryKind {
+ kIllegal,
+ kSqrt,
+ kDoubleSquare,
+ };
+ MathUnaryInstr(MathUnaryKind kind, Value* value, intptr_t deopt_id)
+ : TemplateDefinition(deopt_id), kind_(kind) {
+ SetInputAt(0, value);
+ }
+
+ Value* value() const { return inputs_[0]; }
+ MathUnaryKind kind() const { return kind_; }
+
+ virtual bool ComputeCanDeoptimize() const { return false; }
+
+ virtual Representation representation() const { return kUnboxedDouble; }
+
+ virtual Representation RequiredInputRepresentation(intptr_t idx) const {
+ ASSERT(idx == 0);
+ return kUnboxedDouble;
+ }
+
+ virtual SpeculativeMode SpeculativeModeOfInput(intptr_t idx) const {
+ ASSERT(idx == 0);
+ return kNotSpeculative;
+ }
+
+ 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 GetDeoptId();
+ }
+
+ DECLARE_INSTRUCTION(MathUnary)
+ virtual CompileType ComputeType() const;
+
+ virtual bool AttributesEqual(const Instruction& other) const {
+ return kind() == other.AsMathUnary()->kind();
+ }
+
+ Definition* Canonicalize(FlowGraph* flow_graph);
+
+ static const char* KindToCString(MathUnaryKind kind);
+
+ PRINT_OPERANDS_TO_SUPPORT
+
+ private:
+ const MathUnaryKind kind_;
+
+ DISALLOW_COPY_AND_ASSIGN(MathUnaryInstr);
+};
+
// Calls into the runtime and performs a case-insensitive comparison of the
// UTF16 strings (i.e. TwoByteString or ExternalTwoByteString) located at
// str[lhs_index:lhs_index + length] and str[rhs_index:rhs_index + length].
@@ -7664,15 +7663,11 @@
Value* right,
intptr_t deopt_id,
const InstructionSource& source,
- SpeculativeMode speculative_mode = kGuardInputs,
- Representation representation = kUnboxedDouble)
+ SpeculativeMode speculative_mode = kGuardInputs)
: TemplateDefinition(source, deopt_id),
op_kind_(op_kind),
token_pos_(source.token_pos),
- speculative_mode_(speculative_mode),
- representation_(representation) {
- ASSERT((representation == kUnboxedFloat) ||
- (representation == kUnboxedDouble));
+ speculative_mode_(speculative_mode) {
SetInputAt(0, left);
SetInputAt(1, right);
}
@@ -7686,11 +7681,11 @@
virtual bool ComputeCanDeoptimize() const { return false; }
- virtual Representation representation() const { return representation_; }
+ virtual Representation representation() const { return kUnboxedDouble; }
virtual Representation RequiredInputRepresentation(intptr_t idx) const {
ASSERT((idx == 0) || (idx == 1));
- return representation_;
+ return kUnboxedDouble;
}
virtual SpeculativeMode SpeculativeModeOfInput(intptr_t index) const {
@@ -7713,15 +7708,13 @@
virtual bool AttributesEqual(const Instruction& other) const {
auto const other_bin_op = other.AsBinaryDoubleOp();
return (op_kind() == other_bin_op->op_kind()) &&
- (speculative_mode_ == other_bin_op->speculative_mode_) &&
- (representation_ == other_bin_op->representation_);
+ (speculative_mode_ == other_bin_op->speculative_mode_);
}
private:
const Token::Kind op_kind_;
const TokenPosition token_pos_;
const SpeculativeMode speculative_mode_;
- const Representation representation_;
DISALLOW_COPY_AND_ASSIGN(BinaryDoubleOpInstr);
};
@@ -8304,19 +8297,17 @@
DISALLOW_COPY_AND_ASSIGN(SpeculativeShiftUint32OpInstr);
};
+// Handles only NEGATE.
class UnaryDoubleOpInstr : public TemplateDefinition<1, NoThrow, Pure> {
public:
UnaryDoubleOpInstr(Token::Kind op_kind,
Value* value,
intptr_t deopt_id,
- SpeculativeMode speculative_mode = kGuardInputs,
- Representation representation = kUnboxedDouble)
+ SpeculativeMode speculative_mode = kGuardInputs)
: TemplateDefinition(deopt_id),
op_kind_(op_kind),
- speculative_mode_(speculative_mode),
- representation_(representation) {
- ASSERT((representation == kUnboxedFloat) ||
- (representation == kUnboxedDouble));
+ speculative_mode_(speculative_mode) {
+ ASSERT(op_kind == Token::kNEGATE);
SetInputAt(0, value);
}
@@ -8334,11 +8325,11 @@
return GetDeoptId();
}
- virtual Representation representation() const { return representation_; }
+ virtual Representation representation() const { return kUnboxedDouble; }
virtual Representation RequiredInputRepresentation(intptr_t idx) const {
ASSERT(idx == 0);
- return representation_;
+ return kUnboxedDouble;
}
virtual SpeculativeMode SpeculativeModeOfInput(intptr_t index) const {
@@ -8346,8 +8337,7 @@
}
virtual bool AttributesEqual(const Instruction& other) const {
- return (speculative_mode_ == other.AsUnaryDoubleOp()->speculative_mode_) &&
- (representation_ == other.AsUnaryDoubleOp()->representation_);
+ return speculative_mode_ == other.AsUnaryDoubleOp()->speculative_mode_;
}
PRINT_OPERANDS_TO_SUPPORT
@@ -8355,7 +8345,6 @@
private:
const Token::Kind op_kind_;
const SpeculativeMode speculative_mode_;
- const Representation representation_;
DISALLOW_COPY_AND_ASSIGN(UnaryDoubleOpInstr);
};
@@ -8585,6 +8574,51 @@
DISALLOW_COPY_AND_ASSIGN(DoubleToSmiInstr);
};
+class DoubleToDoubleInstr : public TemplateDefinition<1, NoThrow, Pure> {
+ public:
+ DoubleToDoubleInstr(Value* value,
+ MethodRecognizer::Kind recognized_kind,
+ intptr_t deopt_id)
+ : TemplateDefinition(deopt_id), recognized_kind_(recognized_kind) {
+ ASSERT((recognized_kind == MethodRecognizer::kDoubleTruncateToDouble) ||
+ (recognized_kind == MethodRecognizer::kDoubleFloorToDouble) ||
+ (recognized_kind == MethodRecognizer::kDoubleCeilToDouble));
+ SetInputAt(0, value);
+ }
+
+ Value* value() const { return inputs_[0]; }
+
+ MethodRecognizer::Kind recognized_kind() const { return recognized_kind_; }
+
+ DECLARE_INSTRUCTION(DoubleToDouble)
+ virtual CompileType ComputeType() const;
+
+ virtual bool ComputeCanDeoptimize() const { return false; }
+
+ virtual Representation representation() const { return kUnboxedDouble; }
+
+ virtual Representation RequiredInputRepresentation(intptr_t idx) const {
+ ASSERT(idx == 0);
+ return kUnboxedDouble;
+ }
+
+ virtual SpeculativeMode SpeculativeModeOfInput(intptr_t idx) const {
+ ASSERT(idx == 0);
+ return kNotSpeculative;
+ }
+
+ virtual intptr_t DeoptimizationTarget() const { return GetDeoptId(); }
+
+ virtual bool AttributesEqual(const Instruction& other) const {
+ return other.AsDoubleToDouble()->recognized_kind() == recognized_kind();
+ }
+
+ private:
+ const MethodRecognizer::Kind recognized_kind_;
+
+ DISALLOW_COPY_AND_ASSIGN(DoubleToDoubleInstr);
+};
+
class DoubleToFloatInstr : public TemplateDefinition<1, NoThrow, Pure> {
public:
DoubleToFloatInstr(Value* value,
@@ -8657,42 +8691,6 @@
DISALLOW_COPY_AND_ASSIGN(FloatToDoubleInstr);
};
-// left op right ? -1 : 0
-class FloatCompareInstr : public TemplateDefinition<2, NoThrow, Pure> {
- public:
- FloatCompareInstr(Token::Kind op_kind, Value* left, Value* right)
- : op_kind_(op_kind) {
- SetInputAt(0, left);
- SetInputAt(1, right);
- }
-
- Value* left() const { return inputs_[0]; }
- Value* right() const { return inputs_[1]; }
-
- Token::Kind op_kind() const { return op_kind_; }
-
- DECLARE_INSTRUCTION(FloatCompare)
-
- virtual CompileType ComputeType() const;
-
- virtual bool ComputeCanDeoptimize() const { return false; }
-
- virtual Representation representation() const { return kUnboxedInt32; }
-
- virtual Representation RequiredInputRepresentation(intptr_t idx) const {
- return kUnboxedFloat;
- }
-
- virtual bool AttributesEqual(const Instruction& other) const {
- return other.AsFloatCompare()->op_kind() == op_kind();
- }
-
- private:
- const Token::Kind op_kind_;
-
- DISALLOW_COPY_AND_ASSIGN(FloatCompareInstr);
-};
-
// TODO(sjindel): Replace with FFICallInstr.
class InvokeMathCFunctionInstr : public PureDefinition {
public:
@@ -8805,136 +8803,6 @@
DISALLOW_COPY_AND_ASSIGN(ExtractNthOutputInstr);
};
-class UnboxLaneInstr : public TemplateDefinition<1, NoThrow, Pure> {
- public:
- UnboxLaneInstr(Value* value,
- intptr_t n,
- Representation definition_rep,
- intptr_t definition_cid)
- : lane_(n),
- definition_rep_(definition_rep),
- definition_cid_(definition_cid) {
- SetInputAt(0, value);
- }
-
- Value* value() const { return inputs_[0]; }
-
- DECLARE_INSTRUCTION(UnboxLane)
-
- virtual CompileType ComputeType() const;
- virtual bool ComputeCanDeoptimize() const { return false; }
-
- intptr_t lane() const { return lane_; }
-
- virtual Representation representation() const { return definition_rep_; }
-
- virtual Representation RequiredInputRepresentation(intptr_t idx) const {
- ASSERT(idx == 0);
- return kTagged;
- }
-
- virtual bool AttributesEqual(const Instruction& other) const {
- auto const other_split = other.AsUnboxLane();
- return (other_split->representation() == representation()) &&
- (other_split->lane() == lane());
- }
-
- Definition* Canonicalize(FlowGraph* flow_graph);
-
- PRINT_OPERANDS_TO_SUPPORT
-
- private:
- const intptr_t lane_;
- const Representation definition_rep_;
- const intptr_t definition_cid_;
- DISALLOW_COPY_AND_ASSIGN(UnboxLaneInstr);
-};
-
-class BoxLanesInstr : public TemplateDefinition<4, NoThrow, Pure> {
- public:
- BoxLanesInstr(Representation from_representation, Value* x, Value* y)
- : from_representation_(from_representation) {
- ASSERT(from_representation == kUnboxedDouble);
- ASSERT(x->definition()->representation() == from_representation);
- ASSERT(y->definition()->representation() == from_representation);
- SetInputAt(0, x);
- SetInputAt(1, y);
- }
- BoxLanesInstr(Representation from_representation,
- Value* x,
- Value* y,
- Value* z,
- Value* w)
- : from_representation_(from_representation) {
- ASSERT((from_representation == kUnboxedInt32) ||
- (from_representation == kUnboxedFloat));
- ASSERT(x->definition()->representation() == from_representation);
- ASSERT(y->definition()->representation() == from_representation);
- ASSERT(z->definition()->representation() == from_representation);
- ASSERT(w->definition()->representation() == from_representation);
- SetInputAt(0, x);
- SetInputAt(1, y);
- SetInputAt(2, z);
- SetInputAt(3, w);
- }
-
- intptr_t InputCount() const {
- switch (from_representation_) {
- case kUnboxedDouble:
- return 2;
- case kUnboxedFloat:
- return 4;
- case kUnboxedInt32:
- return 4;
- default:
- UNREACHABLE();
- return 0;
- }
- }
- Value* x() const { return inputs_[0]; }
- Value* y() const { return inputs_[1]; }
- Value* z() const {
- ASSERT((from_representation() == kUnboxedInt32) ||
- (from_representation() == kUnboxedFloat));
- return inputs_[2];
- }
- Value* w() const {
- ASSERT((from_representation() == kUnboxedInt32) ||
- (from_representation() == kUnboxedFloat));
- return inputs_[3];
- }
- Representation from_representation() const { return from_representation_; }
-
- DECLARE_INSTRUCTION(BoxLanes)
- virtual CompileType ComputeType() const;
-
- virtual bool ComputeCanDeoptimize() const { return false; }
- virtual intptr_t DeoptimizationTarget() const { return DeoptId::kNone; }
-
- virtual Representation RequiredInputRepresentation(intptr_t idx) const {
- ASSERT(idx == 0 || idx == 1 || idx == 2 || idx == 3);
- return from_representation();
- }
-
- virtual bool AttributesEqual(const Instruction& other) const {
- return other.AsBoxLanes()->from_representation() == from_representation();
- }
-
- Definition* Canonicalize(FlowGraph* flow_graph);
-
- virtual TokenPosition token_pos() const { return TokenPosition::kBox; }
-
- virtual SpeculativeMode SpeculativeModeOfInput(intptr_t index) const {
- return kNotSpeculative;
- }
-
- PRINT_OPERANDS_TO_SUPPORT
-
- private:
- const Representation from_representation_;
- DISALLOW_COPY_AND_ASSIGN(BoxLanesInstr);
-};
-
class TruncDivModInstr : public TemplateDefinition<2, NoThrow, Pure> {
public:
TruncDivModInstr(Value* lhs, Value* rhs, intptr_t deopt_id);
diff --git a/runtime/vm/compiler/backend/il_arm.cc b/runtime/vm/compiler/backend/il_arm.cc
index 0e131fa..e4bc74b 100644
--- a/runtime/vm/compiler/backend/il_arm.cc
+++ b/runtime/vm/compiler/backend/il_arm.cc
@@ -698,10 +698,11 @@
}
} else if (destination.IsFpuRegister()) {
const DRegister dst = EvenDRegisterOf(destination.fpu_reg());
- if (representation() == kUnboxedFloat) {
- __ LoadSImmediate(EvenSRegisterOf(dst), Double::Cast(value_).value());
+ if (Utils::DoublesBitEqual(Double::Cast(value_).value(), 0.0) &&
+ TargetCPUFeatures::neon_supported()) {
+ QRegister qdst = destination.fpu_reg();
+ __ veorq(qdst, qdst, qdst);
} else {
- ASSERT(representation() == kUnboxedDouble);
ASSERT(tmp != kNoRegister);
__ LoadDImmediate(dst, Double::Cast(value_).value(), tmp);
}
@@ -5703,6 +5704,33 @@
#undef DEFINE_EMIT
+LocationSummary* MathUnaryInstr::MakeLocationSummary(Zone* zone,
+ bool opt) const {
+ ASSERT((kind() == MathUnaryInstr::kSqrt) ||
+ (kind() == MathUnaryInstr::kDoubleSquare));
+ const intptr_t kNumInputs = 1;
+ const intptr_t kNumTemps = 0;
+ LocationSummary* summary = new (zone)
+ LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+ summary->set_in(0, Location::RequiresFpuRegister());
+ summary->set_out(0, Location::RequiresFpuRegister());
+ return summary;
+}
+
+void MathUnaryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ if (kind() == MathUnaryInstr::kSqrt) {
+ const DRegister val = EvenDRegisterOf(locs()->in(0).fpu_reg());
+ const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg());
+ __ vsqrtd(result, val);
+ } else if (kind() == MathUnaryInstr::kDoubleSquare) {
+ const DRegister val = EvenDRegisterOf(locs()->in(0).fpu_reg());
+ const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg());
+ __ vmuld(result, val, val);
+ } else {
+ UNREACHABLE();
+ }
+}
+
LocationSummary* CaseInsensitiveCompareInstr::MakeLocationSummary(
Zone* zone,
bool opt) const {
@@ -5855,22 +5883,9 @@
}
void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- ASSERT(representation() == kUnboxedDouble);
const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg());
const DRegister value = EvenDRegisterOf(locs()->in(0).fpu_reg());
- switch (op_kind()) {
- case Token::kNEGATE:
- __ vnegd(result, value);
- break;
- case Token::kSQRT:
- __ vsqrtd(result, value);
- break;
- case Token::kSQUARE:
- __ vmuld(result, value, value);
- break;
- default:
- UNREACHABLE();
- }
+ __ vnegd(result, value);
}
LocationSummary* Int32ToDoubleInstr::MakeLocationSummary(Zone* zone,
@@ -5985,6 +6000,16 @@
__ SmiTag(result);
}
+LocationSummary* DoubleToDoubleInstr::MakeLocationSummary(Zone* zone,
+ bool opt) const {
+ UNIMPLEMENTED();
+ return NULL;
+}
+
+void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ UNIMPLEMENTED();
+}
+
LocationSummary* DoubleToFloatInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
const intptr_t kNumInputs = 1;
@@ -6023,16 +6048,6 @@
__ vcvtds(result, value);
}
-LocationSummary* FloatCompareInstr::MakeLocationSummary(Zone* zone,
- bool opt) const {
- UNREACHABLE();
- return NULL;
-}
-
-void FloatCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNREACHABLE();
-}
-
LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
ASSERT((InputCount() == 1) || (InputCount() == 2));
@@ -6283,26 +6298,6 @@
}
}
-LocationSummary* UnboxLaneInstr::MakeLocationSummary(Zone* zone,
- bool opt) const {
- UNREACHABLE();
- return NULL;
-}
-
-void UnboxLaneInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNREACHABLE();
-}
-
-LocationSummary* BoxLanesInstr::MakeLocationSummary(Zone* zone,
- bool opt) const {
- UNREACHABLE();
- return NULL;
-}
-
-void BoxLanesInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNREACHABLE();
-}
-
LocationSummary* TruncDivModInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
const intptr_t kNumInputs = 2;
@@ -7582,26 +7577,6 @@
compiler::Operand(compiler::target::ObjectAlignment::kBoolValueMask));
}
-LocationSummary* BoolToIntInstr::MakeLocationSummary(Zone* zone,
- bool opt) const {
- UNREACHABLE();
- return NULL;
-}
-
-void BoolToIntInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNREACHABLE();
-}
-
-LocationSummary* IntToBoolInstr::MakeLocationSummary(Zone* zone,
- bool opt) const {
- UNREACHABLE();
- return NULL;
-}
-
-void IntToBoolInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNREACHABLE();
-}
-
LocationSummary* AllocateObjectInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
const intptr_t kNumInputs = (type_arguments() != nullptr) ? 1 : 0;
diff --git a/runtime/vm/compiler/backend/il_arm64.cc b/runtime/vm/compiler/backend/il_arm64.cc
index e61557a..ca277fb 100644
--- a/runtime/vm/compiler/backend/il_arm64.cc
+++ b/runtime/vm/compiler/backend/il_arm64.cc
@@ -625,12 +625,6 @@
} else if (destination.IsFpuRegister()) {
const VRegister dst = destination.fpu_reg();
__ LoadDImmediate(dst, Double::Cast(value_).value());
- if (representation() == kUnboxedFloat) {
- __ LoadSImmediate(dst, Double::Cast(value_).value());
- } else {
- ASSERT(representation() == kUnboxedDouble);
- __ LoadDImmediate(dst, Double::Cast(value_).value());
- }
} else if (destination.IsDoubleStackSlot()) {
const intptr_t dest_offset = destination.ToStackSlotOffset();
if (Utils::DoublesBitEqual(Double::Cast(value_).value(), 0.0)) {
@@ -4802,6 +4796,33 @@
#undef DEFINE_EMIT
+LocationSummary* MathUnaryInstr::MakeLocationSummary(Zone* zone,
+ bool opt) const {
+ ASSERT((kind() == MathUnaryInstr::kSqrt) ||
+ (kind() == MathUnaryInstr::kDoubleSquare));
+ const intptr_t kNumInputs = 1;
+ const intptr_t kNumTemps = 0;
+ LocationSummary* summary = new (zone)
+ LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+ summary->set_in(0, Location::RequiresFpuRegister());
+ summary->set_out(0, Location::RequiresFpuRegister());
+ return summary;
+}
+
+void MathUnaryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ if (kind() == MathUnaryInstr::kSqrt) {
+ const VRegister val = locs()->in(0).fpu_reg();
+ const VRegister result = locs()->out(0).fpu_reg();
+ __ fsqrtd(result, val);
+ } else if (kind() == MathUnaryInstr::kDoubleSquare) {
+ const VRegister val = locs()->in(0).fpu_reg();
+ const VRegister result = locs()->out(0).fpu_reg();
+ __ fmuld(result, val, val);
+ } else {
+ UNREACHABLE();
+ }
+}
+
LocationSummary* CaseInsensitiveCompareInstr::MakeLocationSummary(
Zone* zone,
bool opt) const {
@@ -4954,22 +4975,9 @@
}
void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- ASSERT(representation() == kUnboxedDouble);
const VRegister result = locs()->out(0).fpu_reg();
const VRegister value = locs()->in(0).fpu_reg();
- switch (op_kind()) {
- case Token::kNEGATE:
- __ fnegd(result, value);
- break;
- case Token::kSQRT:
- __ fsqrtd(result, value);
- break;
- case Token::kSQUARE:
- __ fmuld(result, value, value);
- break;
- default:
- UNREACHABLE();
- }
+ __ fnegd(result, value);
}
LocationSummary* Int32ToDoubleInstr::MakeLocationSummary(Zone* zone,
@@ -5118,6 +5126,16 @@
__ SmiTag(result);
}
+LocationSummary* DoubleToDoubleInstr::MakeLocationSummary(Zone* zone,
+ bool opt) const {
+ UNIMPLEMENTED();
+ return NULL;
+}
+
+void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ UNIMPLEMENTED();
+}
+
LocationSummary* DoubleToFloatInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
const intptr_t kNumInputs = 1;
@@ -5152,16 +5170,6 @@
__ fcvtds(result, value);
}
-LocationSummary* FloatCompareInstr::MakeLocationSummary(Zone* zone,
- bool opt) const {
- UNREACHABLE();
- return NULL;
-}
-
-void FloatCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNREACHABLE();
-}
-
LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
ASSERT((InputCount() == 1) || (InputCount() == 2));
@@ -5364,26 +5372,6 @@
}
}
-LocationSummary* UnboxLaneInstr::MakeLocationSummary(Zone* zone,
- bool opt) const {
- UNREACHABLE();
- return NULL;
-}
-
-void UnboxLaneInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNREACHABLE();
-}
-
-LocationSummary* BoxLanesInstr::MakeLocationSummary(Zone* zone,
- bool opt) const {
- UNREACHABLE();
- return NULL;
-}
-
-void BoxLanesInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNREACHABLE();
-}
-
LocationSummary* TruncDivModInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
const intptr_t kNumInputs = 2;
@@ -6687,26 +6675,6 @@
compiler::Immediate(compiler::target::ObjectAlignment::kBoolValueMask));
}
-LocationSummary* BoolToIntInstr::MakeLocationSummary(Zone* zone,
- bool opt) const {
- UNREACHABLE();
- return NULL;
-}
-
-void BoolToIntInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNREACHABLE();
-}
-
-LocationSummary* IntToBoolInstr::MakeLocationSummary(Zone* zone,
- bool opt) const {
- UNREACHABLE();
- return NULL;
-}
-
-void IntToBoolInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNREACHABLE();
-}
-
LocationSummary* AllocateObjectInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
const intptr_t kNumInputs = (type_arguments() != nullptr) ? 1 : 0;
diff --git a/runtime/vm/compiler/backend/il_ia32.cc b/runtime/vm/compiler/backend/il_ia32.cc
index 4d24aa2..b84f33e 100644
--- a/runtime/vm/compiler/backend/il_ia32.cc
+++ b/runtime/vm/compiler/backend/il_ia32.cc
@@ -421,23 +421,18 @@
__ LoadObjectSafely(destination.reg(), value_);
}
} else if (destination.IsFpuRegister()) {
- if (representation() == kUnboxedFloat) {
- __ LoadSImmediate(destination.fpu_reg(),
- static_cast<float>(Double::Cast(value_).value()));
+ const double value_as_double = Double::Cast(value_).value();
+ uword addr = FindDoubleConstant(value_as_double);
+ if (addr == 0) {
+ __ pushl(EAX);
+ __ LoadObject(EAX, value_);
+ __ movsd(destination.fpu_reg(),
+ compiler::FieldAddress(EAX, Double::value_offset()));
+ __ popl(EAX);
+ } else if (Utils::DoublesBitEqual(value_as_double, 0.0)) {
+ __ xorps(destination.fpu_reg(), destination.fpu_reg());
} else {
- const double value_as_double = Double::Cast(value_).value();
- uword addr = FindDoubleConstant(value_as_double);
- if (addr == 0) {
- __ pushl(EAX);
- __ LoadObject(EAX, value_);
- __ movsd(destination.fpu_reg(),
- compiler::FieldAddress(EAX, Double::value_offset()));
- __ popl(EAX);
- } else if (Utils::DoublesBitEqual(value_as_double, 0.0)) {
- __ xorps(destination.fpu_reg(), destination.fpu_reg());
- } else {
- __ movsd(destination.fpu_reg(), compiler::Address::Absolute(addr));
- }
+ __ movsd(destination.fpu_reg(), compiler::Address::Absolute(addr));
}
} else if (destination.IsDoubleStackSlot()) {
const double value_as_double = Double::Cast(value_).value();
@@ -4822,6 +4817,35 @@
#undef DEFINE_EMIT
+LocationSummary* MathUnaryInstr::MakeLocationSummary(Zone* zone,
+ bool opt) const {
+ ASSERT((kind() == MathUnaryInstr::kSqrt) ||
+ (kind() == MathUnaryInstr::kDoubleSquare));
+ const intptr_t kNumInputs = 1;
+ const intptr_t kNumTemps = 0;
+ LocationSummary* summary = new (zone)
+ LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+ summary->set_in(0, Location::RequiresFpuRegister());
+ if (kind() == MathUnaryInstr::kDoubleSquare) {
+ summary->set_out(0, Location::SameAsFirstInput());
+ } else {
+ summary->set_out(0, Location::RequiresFpuRegister());
+ }
+ return summary;
+}
+
+void MathUnaryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ if (kind() == MathUnaryInstr::kSqrt) {
+ __ sqrtsd(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg());
+ } else if (kind() == MathUnaryInstr::kDoubleSquare) {
+ XmmRegister value_reg = locs()->in(0).fpu_reg();
+ __ mulsd(value_reg, value_reg);
+ ASSERT(value_reg == locs()->out(0).fpu_reg());
+ } else {
+ UNREACHABLE();
+ }
+}
+
LocationSummary* CaseInsensitiveCompareInstr::MakeLocationSummary(
Zone* zone,
bool opt) const {
@@ -4977,31 +5001,9 @@
}
void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- ASSERT(representation() == kUnboxedDouble);
XmmRegister value = locs()->in(0).fpu_reg();
ASSERT(locs()->out(0).fpu_reg() == value);
- switch (op_kind()) {
- case Token::kNEGATE:
- __ DoubleNegate(value);
- break;
- case Token::kSQRT:
- __ sqrtsd(value, value);
- break;
- case Token::kSQUARE:
- __ mulsd(value, value);
- break;
- case Token::kTRUNCATE:
- __ roundsd(value, value, compiler::Assembler::kRoundToZero);
- break;
- case Token::kFLOOR:
- __ roundsd(value, value, compiler::Assembler::kRoundDown);
- break;
- case Token::kCEILING:
- __ roundsd(value, value, compiler::Assembler::kRoundUp);
- break;
- default:
- UNREACHABLE();
- }
+ __ DoubleNegate(value);
}
LocationSummary* Int32ToDoubleInstr::MakeLocationSummary(Zone* zone,
@@ -5124,6 +5126,35 @@
__ SmiTag(result);
}
+LocationSummary* DoubleToDoubleInstr::MakeLocationSummary(Zone* zone,
+ bool opt) const {
+ const intptr_t kNumInputs = 1;
+ const intptr_t kNumTemps = 0;
+ LocationSummary* result = new (zone)
+ LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+ result->set_in(0, Location::RequiresFpuRegister());
+ result->set_out(0, Location::RequiresFpuRegister());
+ return result;
+}
+
+void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ XmmRegister value = locs()->in(0).fpu_reg();
+ XmmRegister result = locs()->out(0).fpu_reg();
+ switch (recognized_kind()) {
+ case MethodRecognizer::kDoubleTruncateToDouble:
+ __ roundsd(result, value, compiler::Assembler::kRoundToZero);
+ break;
+ case MethodRecognizer::kDoubleFloorToDouble:
+ __ roundsd(result, value, compiler::Assembler::kRoundDown);
+ break;
+ case MethodRecognizer::kDoubleCeilToDouble:
+ __ roundsd(result, value, compiler::Assembler::kRoundUp);
+ break;
+ default:
+ UNREACHABLE();
+ }
+}
+
LocationSummary* DoubleToFloatInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
const intptr_t kNumInputs = 1;
@@ -5154,16 +5185,6 @@
__ cvtss2sd(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg());
}
-LocationSummary* FloatCompareInstr::MakeLocationSummary(Zone* zone,
- bool opt) const {
- UNREACHABLE();
- return NULL;
-}
-
-void FloatCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNREACHABLE();
-}
-
LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
ASSERT((InputCount() == 1) || (InputCount() == 2));
@@ -5390,26 +5411,6 @@
}
}
-LocationSummary* UnboxLaneInstr::MakeLocationSummary(Zone* zone,
- bool opt) const {
- UNREACHABLE();
- return NULL;
-}
-
-void UnboxLaneInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNREACHABLE();
-}
-
-LocationSummary* BoxLanesInstr::MakeLocationSummary(Zone* zone,
- bool opt) const {
- UNREACHABLE();
- return NULL;
-}
-
-void BoxLanesInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNREACHABLE();
-}
-
LocationSummary* TruncDivModInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
const intptr_t kNumInputs = 2;
@@ -6661,26 +6662,6 @@
compiler::target::ObjectAlignment::kBoolValueMask));
}
-LocationSummary* BoolToIntInstr::MakeLocationSummary(Zone* zone,
- bool opt) const {
- UNREACHABLE();
- return NULL;
-}
-
-void BoolToIntInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNREACHABLE();
-}
-
-LocationSummary* IntToBoolInstr::MakeLocationSummary(Zone* zone,
- bool opt) const {
- UNREACHABLE();
- return NULL;
-}
-
-void IntToBoolInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNREACHABLE();
-}
-
LocationSummary* AllocateObjectInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
const intptr_t kNumInputs = (type_arguments() != nullptr) ? 1 : 0;
diff --git a/runtime/vm/compiler/backend/il_printer.cc b/runtime/vm/compiler/backend/il_printer.cc
index da9c0c9..05b7050 100644
--- a/runtime/vm/compiler/backend/il_printer.cc
+++ b/runtime/vm/compiler/backend/il_printer.cc
@@ -484,9 +484,7 @@
range_->PrintTo(f);
}
- if (representation() != kNoRepresentation && representation() != kTagged) {
- f->Printf(" %s", RepresentationToCString(representation()));
- } else if (type_ != NULL) {
+ if (type_ != NULL) {
f->AddString(" ");
type_->PrintTo(f);
}
@@ -555,6 +553,10 @@
buffer[pos] = '\0';
f->Printf("#%s\\n...", buffer);
}
+
+ if (representation() != kNoRepresentation && representation() != kTagged) {
+ f->Printf(" %s", RepresentationToCString(representation()));
+ }
}
void ConstraintInstr::PrintOperandsTo(BaseTextBuffer* f) const {
@@ -908,6 +910,11 @@
TemplateAllocation::PrintOperandsTo(f);
}
+void MathUnaryInstr::PrintOperandsTo(BaseTextBuffer* f) const {
+ f->Printf("'%s', ", MathUnaryInstr::KindToCString(kind()));
+ value()->PrintTo(f);
+}
+
void TruncDivModInstr::PrintOperandsTo(BaseTextBuffer* f) const {
Definition::PrintOperandsTo(f);
}
@@ -917,15 +924,6 @@
Definition::PrintOperandsTo(f);
}
-void UnboxLaneInstr::PrintOperandsTo(BaseTextBuffer* f) const {
- Definition::PrintOperandsTo(f);
- f->Printf(", lane %" Pd, lane());
-}
-
-void BoxLanesInstr::PrintOperandsTo(BaseTextBuffer* f) const {
- Definition::PrintOperandsTo(f);
-}
-
void UnaryIntegerOpInstr::PrintOperandsTo(BaseTextBuffer* f) const {
f->Printf("%s, ", Token::Str(op_kind()));
value()->PrintTo(f);
diff --git a/runtime/vm/compiler/backend/il_riscv.cc b/runtime/vm/compiler/backend/il_riscv.cc
index 2222f9b..041f180 100644
--- a/runtime/vm/compiler/backend/il_riscv.cc
+++ b/runtime/vm/compiler/backend/il_riscv.cc
@@ -715,12 +715,7 @@
}
} else if (destination.IsFpuRegister()) {
const FRegister dst = destination.fpu_reg();
- if (representation() == kUnboxedFloat) {
- __ LoadSImmediate(dst, Double::Cast(value_).value());
- } else {
- ASSERT(representation() == kUnboxedDouble);
- __ LoadDImmediate(dst, Double::Cast(value_).value());
- }
+ __ LoadDImmediate(dst, Double::Cast(value_).value());
} else if (destination.IsDoubleStackSlot()) {
const intptr_t dest_offset = destination.ToStackSlotOffset();
#if XLEN == 32
@@ -1203,7 +1198,7 @@
__ CompareImmediate(TMP, 0);
return NE;
case Token::kGT:
- __ fgtd(TMP, left, right);
+ __ fltd(TMP, right, left);
__ CompareImmediate(TMP, 0);
return NE;
case Token::kLTE:
@@ -1211,7 +1206,7 @@
__ CompareImmediate(TMP, 0);
return NE;
case Token::kGTE:
- __ fged(TMP, left, right);
+ __ fled(TMP, right, left);
__ CompareImmediate(TMP, 0);
return NE;
default:
@@ -3368,11 +3363,9 @@
__ LoadDFieldFromOffset(result, temp, Double::value_offset());
break;
case kFloat32x4Cid:
- __ Comment("UnboxedFloat32x4LoadFieldInstr");
UNIMPLEMENTED();
break;
case kFloat64x2Cid:
- __ Comment("UnboxedFloat64x2LoadFieldInstr");
UNIMPLEMENTED();
break;
default:
@@ -4441,16 +4434,6 @@
}
#endif
- case kUnboxedFloat: {
- const FRegister result = locs()->out(0).fpu_reg();
- __ SmiUntag(TMP, box);
-#if XLEN == 32
- __ fcvtsw(result, TMP);
-#elif XLEN == 64
- __ fcvtsl(result, TMP);
-#endif
- break;
- }
case kUnboxedDouble: {
const FRegister result = locs()->out(0).fpu_reg();
__ SmiUntag(TMP, box);
@@ -4825,53 +4808,21 @@
const FRegister left = locs()->in(0).fpu_reg();
const FRegister right = locs()->in(1).fpu_reg();
const FRegister result = locs()->out(0).fpu_reg();
- if (representation() == kUnboxedDouble) {
- switch (op_kind()) {
- case Token::kADD:
- __ faddd(result, left, right);
- break;
- case Token::kSUB:
- __ fsubd(result, left, right);
- break;
- case Token::kMUL:
- __ fmuld(result, left, right);
- break;
- case Token::kDIV:
- __ fdivd(result, left, right);
- break;
- case Token::kMIN:
- __ fmind(result, left, right);
- break;
- case Token::kMAX:
- __ fmaxd(result, left, right);
- break;
- default:
- UNREACHABLE();
- }
- } else {
- ASSERT(representation() == kUnboxedFloat);
- switch (op_kind()) {
- case Token::kADD:
- __ fadds(result, left, right);
- break;
- case Token::kSUB:
- __ fsubs(result, left, right);
- break;
- case Token::kMUL:
- __ fmuls(result, left, right);
- break;
- case Token::kDIV:
- __ fdivs(result, left, right);
- break;
- case Token::kMIN:
- __ fmins(result, left, right);
- break;
- case Token::kMAX:
- __ fmaxs(result, left, right);
- break;
- default:
- UNREACHABLE();
- }
+ switch (op_kind()) {
+ case Token::kADD:
+ __ faddd(result, left, right);
+ break;
+ case Token::kSUB:
+ __ fsubd(result, left, right);
+ break;
+ case Token::kMUL:
+ __ fmuld(result, left, right);
+ break;
+ case Token::kDIV:
+ __ fdivd(result, left, right);
+ break;
+ default:
+ UNREACHABLE();
}
}
@@ -4902,13 +4853,259 @@
return kind() == Token::kEQ ? NOT_ZERO : ZERO;
}
+// SIMD
+
+#define DEFINE_EMIT(Name, Args) \
+ static void Emit##Name(FlowGraphCompiler* compiler, SimdOpInstr* instr, \
+ PP_APPLY(PP_UNPACK, Args))
+
+#define SIMD_OP_FLOAT_ARITH(V, Name, op) \
+ V(Float32x4##Name, op##s) \
+ V(Float64x2##Name, op##d)
+
+#define SIMD_OP_SIMPLE_BINARY(V) \
+ SIMD_OP_FLOAT_ARITH(V, Add, vadd) \
+ SIMD_OP_FLOAT_ARITH(V, Sub, vsub) \
+ SIMD_OP_FLOAT_ARITH(V, Mul, vmul) \
+ SIMD_OP_FLOAT_ARITH(V, Div, vdiv) \
+ SIMD_OP_FLOAT_ARITH(V, Min, vmin) \
+ SIMD_OP_FLOAT_ARITH(V, Max, vmax) \
+ V(Int32x4Add, vaddw) \
+ V(Int32x4Sub, vsubw) \
+ V(Int32x4BitAnd, vand) \
+ V(Int32x4BitOr, vorr) \
+ V(Int32x4BitXor, veor) \
+ V(Float32x4Equal, vceqs) \
+ V(Float32x4GreaterThan, vcgts) \
+ V(Float32x4GreaterThanOrEqual, vcges)
+
+DEFINE_EMIT(SimdBinaryOp, (FRegister result, FRegister left, FRegister right)) {
+ UNIMPLEMENTED();
+}
+
+#define SIMD_OP_SIMPLE_UNARY(V) \
+ SIMD_OP_FLOAT_ARITH(V, Sqrt, vsqrt) \
+ SIMD_OP_FLOAT_ARITH(V, Negate, vneg) \
+ SIMD_OP_FLOAT_ARITH(V, Abs, vabs) \
+ V(Float32x4Reciprocal, VRecps) \
+ V(Float32x4ReciprocalSqrt, VRSqrts)
+
+DEFINE_EMIT(SimdUnaryOp, (FRegister result, FRegister value)) {
+ UNIMPLEMENTED();
+}
+
+DEFINE_EMIT(Simd32x4GetSignMask,
+ (Register out, FRegister value, Temp<Register> temp)) {
+ UNIMPLEMENTED();
+}
+
+DEFINE_EMIT(
+ Float32x4FromDoubles,
+ (FRegister r, FRegister v0, FRegister v1, FRegister v2, FRegister v3)) {
+ UNIMPLEMENTED();
+}
+
+DEFINE_EMIT(
+ Float32x4Clamp,
+ (FRegister result, FRegister value, FRegister lower, FRegister upper)) {
+ UNIMPLEMENTED();
+}
+
+DEFINE_EMIT(
+ Float64x2Clamp,
+ (FRegister result, FRegister value, FRegister lower, FRegister upper)) {
+ UNIMPLEMENTED();
+}
+
+DEFINE_EMIT(Float32x4With,
+ (FRegister result, FRegister replacement, FRegister value)) {
+ UNIMPLEMENTED();
+}
+
+DEFINE_EMIT(Simd32x4ToSimd32x4, (SameAsFirstInput, FRegister value)) {
+ // TODO(dartbug.com/30949) these operations are essentially nop and should
+ // not generate any code. They should be removed from the graph before
+ // code generation.
+}
+
+DEFINE_EMIT(SimdZero, (FRegister v)) {
+ UNIMPLEMENTED();
+}
+
+DEFINE_EMIT(Float64x2GetSignMask, (Register out, FRegister value)) {
+ UNIMPLEMENTED();
+}
+
+DEFINE_EMIT(Float64x2With,
+ (SameAsFirstInput, FRegister left, FRegister right)) {
+ UNIMPLEMENTED();
+}
+
+DEFINE_EMIT(
+ Int32x4FromInts,
+ (FRegister result, Register v0, Register v1, Register v2, Register v3)) {
+ UNIMPLEMENTED();
+}
+
+DEFINE_EMIT(Int32x4FromBools,
+ (FRegister result,
+ Register v0,
+ Register v1,
+ Register v2,
+ Register v3,
+ Temp<Register> temp)) {
+ UNIMPLEMENTED();
+}
+
+DEFINE_EMIT(Int32x4GetFlag, (Register result, FRegister value)) {
+ UNIMPLEMENTED();
+}
+
+DEFINE_EMIT(Int32x4Select,
+ (FRegister out,
+ FRegister mask,
+ FRegister trueValue,
+ FRegister falseValue,
+ Temp<FRegister> temp)) {
+ UNIMPLEMENTED();
+}
+
+DEFINE_EMIT(Int32x4WithFlag,
+ (SameAsFirstInput, FRegister mask, Register flag)) {
+ UNIMPLEMENTED();
+}
+
+// Map SimdOpInstr::Kind-s to corresponding emit functions. Uses the following
+// format:
+//
+// CASE(OpA) CASE(OpB) ____(Emitter) - Emitter is used to emit OpA and OpB.
+// SIMPLE(OpA) - Emitter with name OpA is used to emit OpA.
+//
+#define SIMD_OP_VARIANTS(CASE, ____) \
+ SIMD_OP_SIMPLE_BINARY(CASE) \
+ CASE(Float32x4ShuffleMix) \
+ CASE(Int32x4ShuffleMix) \
+ CASE(Float32x4NotEqual) \
+ CASE(Float32x4LessThan) \
+ CASE(Float32x4LessThanOrEqual) \
+ CASE(Float32x4Scale) \
+ CASE(Float64x2FromDoubles) \
+ CASE(Float64x2Scale) \
+ ____(SimdBinaryOp) \
+ SIMD_OP_SIMPLE_UNARY(CASE) \
+ CASE(Float32x4GetX) \
+ CASE(Float32x4GetY) \
+ CASE(Float32x4GetZ) \
+ CASE(Float32x4GetW) \
+ CASE(Int32x4Shuffle) \
+ CASE(Float32x4Shuffle) \
+ CASE(Float32x4Splat) \
+ CASE(Float64x2GetX) \
+ CASE(Float64x2GetY) \
+ CASE(Float64x2Splat) \
+ CASE(Float64x2ToFloat32x4) \
+ CASE(Float32x4ToFloat64x2) \
+ ____(SimdUnaryOp) \
+ CASE(Float32x4GetSignMask) \
+ CASE(Int32x4GetSignMask) \
+ ____(Simd32x4GetSignMask) \
+ CASE(Float32x4FromDoubles) \
+ ____(Float32x4FromDoubles) \
+ CASE(Float32x4Zero) \
+ CASE(Float64x2Zero) \
+ ____(SimdZero) \
+ CASE(Float32x4Clamp) \
+ ____(Float32x4Clamp) \
+ CASE(Float64x2Clamp) \
+ ____(Float64x2Clamp) \
+ CASE(Float32x4WithX) \
+ CASE(Float32x4WithY) \
+ CASE(Float32x4WithZ) \
+ CASE(Float32x4WithW) \
+ ____(Float32x4With) \
+ CASE(Float32x4ToInt32x4) \
+ CASE(Int32x4ToFloat32x4) \
+ ____(Simd32x4ToSimd32x4) \
+ CASE(Float64x2GetSignMask) \
+ ____(Float64x2GetSignMask) \
+ CASE(Float64x2WithX) \
+ CASE(Float64x2WithY) \
+ ____(Float64x2With) \
+ CASE(Int32x4FromInts) \
+ ____(Int32x4FromInts) \
+ CASE(Int32x4FromBools) \
+ ____(Int32x4FromBools) \
+ CASE(Int32x4GetFlagX) \
+ CASE(Int32x4GetFlagY) \
+ CASE(Int32x4GetFlagZ) \
+ CASE(Int32x4GetFlagW) \
+ ____(Int32x4GetFlag) \
+ CASE(Int32x4Select) \
+ ____(Int32x4Select) \
+ CASE(Int32x4WithFlagX) \
+ CASE(Int32x4WithFlagY) \
+ CASE(Int32x4WithFlagZ) \
+ CASE(Int32x4WithFlagW) \
+ ____(Int32x4WithFlag)
+
LocationSummary* SimdOpInstr::MakeLocationSummary(Zone* zone, bool opt) const {
+ switch (kind()) {
+#define CASE(Name, ...) case k##Name:
+#define EMIT(Name) \
+ return MakeLocationSummaryFromEmitter(zone, this, &Emit##Name);
+ SIMD_OP_VARIANTS(CASE, EMIT)
+#undef CASE
+#undef EMIT
+ case kIllegalSimdOp:
+ UNREACHABLE();
+ break;
+ }
UNREACHABLE();
return NULL;
}
void SimdOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNREACHABLE();
+ switch (kind()) {
+#define CASE(Name, ...) case k##Name:
+#define EMIT(Name) \
+ InvokeEmitter(compiler, this, &Emit##Name); \
+ break;
+ SIMD_OP_VARIANTS(CASE, EMIT)
+#undef CASE
+#undef EMIT
+ case kIllegalSimdOp:
+ UNREACHABLE();
+ break;
+ }
+}
+
+#undef DEFINE_EMIT
+
+LocationSummary* MathUnaryInstr::MakeLocationSummary(Zone* zone,
+ bool opt) const {
+ ASSERT((kind() == MathUnaryInstr::kSqrt) ||
+ (kind() == MathUnaryInstr::kDoubleSquare));
+ const intptr_t kNumInputs = 1;
+ const intptr_t kNumTemps = 0;
+ LocationSummary* summary = new (zone)
+ LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+ summary->set_in(0, Location::RequiresFpuRegister());
+ summary->set_out(0, Location::RequiresFpuRegister());
+ return summary;
+}
+
+void MathUnaryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ if (kind() == MathUnaryInstr::kSqrt) {
+ const FRegister val = locs()->in(0).fpu_reg();
+ const FRegister result = locs()->out(0).fpu_reg();
+ __ fsqrtd(result, val);
+ } else if (kind() == MathUnaryInstr::kDoubleSquare) {
+ const FRegister val = locs()->in(0).fpu_reg();
+ const FRegister result = locs()->out(0).fpu_reg();
+ __ fmuld(result, val, val);
+ } else {
+ UNREACHABLE();
+ }
}
LocationSummary* CaseInsensitiveCompareInstr::MakeLocationSummary(
@@ -5052,53 +5249,7 @@
void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
const FRegister result = locs()->out(0).fpu_reg();
const FRegister value = locs()->in(0).fpu_reg();
- if (representation() == kUnboxedDouble) {
- switch (op_kind()) {
- case Token::kABS:
- __ fabsd(result, value);
- break;
- case Token::kNEGATE:
- __ fnegd(result, value);
- break;
- case Token::kSQRT:
- __ fsqrtd(result, value);
- break;
- case Token::kSQUARE:
- __ fmuld(result, value, value);
- break;
- default:
- UNREACHABLE();
- }
- } else {
- ASSERT(representation() == kUnboxedFloat);
- switch (op_kind()) {
- case Token::kABS:
- __ fabss(result, value);
- break;
- case Token::kNEGATE:
- __ fnegs(result, value);
- break;
- case Token::kRECIPROCAL:
- __ li(TMP, 1);
- __ fcvtsw(FTMP, TMP);
- __ fdivs(result, FTMP, value);
- break;
- case Token::kRECIPROCAL_SQRT:
- __ li(TMP, 1);
- __ fcvtsw(FTMP, TMP);
- __ fdivs(result, FTMP, value);
- __ fsqrts(result, result);
- break;
- case Token::kSQRT:
- __ fsqrts(result, value);
- break;
- case Token::kSQUARE:
- __ fmuls(result, value, value);
- break;
- default:
- UNREACHABLE();
- }
- }
+ __ fnegd(result, value);
}
LocationSummary* Int32ToDoubleInstr::MakeLocationSummary(Zone* zone,
@@ -5246,6 +5397,16 @@
__ bne(TMP, TMP2, deopt);
}
+LocationSummary* DoubleToDoubleInstr::MakeLocationSummary(Zone* zone,
+ bool opt) const {
+ UNIMPLEMENTED();
+ return NULL;
+}
+
+void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ UNIMPLEMENTED();
+}
+
LocationSummary* DoubleToFloatInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
const intptr_t kNumInputs = 1;
@@ -5280,45 +5441,6 @@
__ fcvtds(result, value);
}
-LocationSummary* FloatCompareInstr::MakeLocationSummary(Zone* zone,
- bool opt) const {
- const intptr_t kNumInputs = 2;
- const intptr_t kNumTemps = 0;
- LocationSummary* result = new (zone)
- LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
- result->set_in(0, Location::RequiresFpuRegister());
- result->set_in(1, Location::RequiresFpuRegister());
- result->set_out(0, Location::RequiresRegister());
- return result;
-}
-
-void FloatCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- const FRegister lhs = locs()->in(0).fpu_reg();
- const FRegister rhs = locs()->in(1).fpu_reg();
- const Register result = locs()->out(0).reg();
-
- switch (op_kind()) {
- case Token::kEQ:
- __ feqs(result, lhs, rhs); // lhs op rhs ? 1 : 0
- break;
- case Token::kLT:
- __ flts(result, lhs, rhs);
- break;
- case Token::kLTE:
- __ fles(result, lhs, rhs);
- break;
- case Token::kGT:
- __ fgts(result, lhs, rhs);
- break;
- case Token::kGTE:
- __ fges(result, lhs, rhs);
- break;
- default:
- UNREACHABLE();
- }
- __ neg(result, result); // lhs op rhs ? -1 : 0
-}
-
LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
ASSERT((InputCount() == 1) || (InputCount() == 2));
@@ -5400,119 +5522,6 @@
}
}
-LocationSummary* UnboxLaneInstr::MakeLocationSummary(Zone* zone,
- bool opt) const {
- const intptr_t kNumInputs = 1;
- LocationSummary* summary =
- new (zone) LocationSummary(zone, kNumInputs, 0, LocationSummary::kNoCall);
- summary->set_in(0, Location::RequiresRegister());
- switch (representation()) {
- case kUnboxedDouble:
- case kUnboxedFloat:
- summary->set_out(0, Location::RequiresFpuRegister());
- break;
- case kUnboxedInt32:
- summary->set_out(0, Location::RequiresRegister());
- break;
- default:
- UNREACHABLE();
- }
- return summary;
-}
-
-void UnboxLaneInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- Register in = locs()->in(0).reg();
- switch (representation()) {
- case kUnboxedDouble:
- __ fld(locs()->out(0).fpu_reg(),
- compiler::FieldAddress(
- in, compiler::target::Float64x2::value_offset() +
- lane() * sizeof(double)));
- break;
- case kUnboxedFloat:
- __ flw(locs()->out(0).fpu_reg(),
- compiler::FieldAddress(
- in, compiler::target::Float32x4::value_offset() +
- lane() * sizeof(float)));
- break;
- case kUnboxedInt32:
- __ lw(
- locs()->out(0).reg(),
- compiler::FieldAddress(in, compiler::target::Int32x4::value_offset() +
- lane() * sizeof(int32_t)));
- break;
- default:
- UNREACHABLE();
- }
-}
-
-LocationSummary* BoxLanesInstr::MakeLocationSummary(Zone* zone,
- bool opt) const {
- const intptr_t kNumInputs = InputCount();
- LocationSummary* summary = new (zone)
- LocationSummary(zone, kNumInputs, 0, LocationSummary::kCallOnSlowPath);
- switch (from_representation()) {
- case kUnboxedDouble:
- summary->set_in(0, Location::RequiresFpuRegister());
- summary->set_in(1, Location::RequiresFpuRegister());
- break;
- case kUnboxedFloat:
- summary->set_in(0, Location::RequiresFpuRegister());
- summary->set_in(1, Location::RequiresFpuRegister());
- summary->set_in(2, Location::RequiresFpuRegister());
- summary->set_in(3, Location::RequiresFpuRegister());
- break;
- case kUnboxedInt32:
- summary->set_in(0, Location::RequiresRegister());
- summary->set_in(1, Location::RequiresRegister());
- summary->set_in(2, Location::RequiresRegister());
- summary->set_in(3, Location::RequiresRegister());
- break;
- default:
- UNREACHABLE();
- }
- summary->set_out(0, Location::RequiresRegister());
- return summary;
-}
-
-void BoxLanesInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- Register result = locs()->out(0).reg();
- switch (from_representation()) {
- case kUnboxedDouble:
- BoxAllocationSlowPath::Allocate(compiler, this,
- compiler->float64x2_class(), result, TMP);
- for (intptr_t i = 0; i < 2; i++) {
- __ fsd(locs()->in(i).fpu_reg(),
- compiler::FieldAddress(
- result, compiler::target::Float64x2::value_offset() +
- i * sizeof(double)));
- }
- break;
- case kUnboxedFloat:
- BoxAllocationSlowPath::Allocate(compiler, this,
- compiler->float32x4_class(), result, TMP);
- for (intptr_t i = 0; i < 4; i++) {
- __ fsw(locs()->in(i).fpu_reg(),
- compiler::FieldAddress(
- result, compiler::target::Float32x4::value_offset() +
- i * sizeof(float)));
- }
- break;
- case kUnboxedInt32:
- BoxAllocationSlowPath::Allocate(compiler, this, compiler->int32x4_class(),
- result, TMP);
- for (intptr_t i = 0; i < 4; i++) {
- __ sw(locs()->in(i).reg(),
- compiler::FieldAddress(result,
- compiler::target::Int32x4::value_offset() +
- i * sizeof(int32_t)));
- }
- break;
- default:
- UNREACHABLE();
- }
-}
-
LocationSummary* TruncDivModInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
const intptr_t kNumInputs = 2;
@@ -7606,36 +7615,6 @@
__ xori(result, input, compiler::target::ObjectAlignment::kBoolValueMask);
}
-LocationSummary* BoolToIntInstr::MakeLocationSummary(Zone* zone,
- bool opt) const {
- return LocationSummary::Make(zone, 1, Location::RequiresRegister(),
- LocationSummary::kNoCall);
-}
-
-void BoolToIntInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- const Register input = locs()->in(0).reg();
- const Register result = locs()->out(0).reg();
- __ LoadObject(TMP, Bool::True());
- __ xor_(TMP, TMP, input);
- __ seqz(TMP, TMP);
- __ neg(result, TMP);
-}
-
-LocationSummary* IntToBoolInstr::MakeLocationSummary(Zone* zone,
- bool opt) const {
- return LocationSummary::Make(zone, 1, Location::RequiresRegister(),
- LocationSummary::kNoCall);
-}
-
-void IntToBoolInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- const Register input = locs()->in(0).reg();
- const Register result = locs()->out(0).reg();
- __ seqz(result, input);
- __ slli(result, result, kBoolValueBitPosition);
- __ add(result, result, NULL_REG);
- __ addi(result, result, kTrueOffsetFromNull);
-}
-
LocationSummary* AllocateObjectInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
const intptr_t kNumInputs = (type_arguments() != nullptr) ? 1 : 0;
diff --git a/runtime/vm/compiler/backend/il_x64.cc b/runtime/vm/compiler/backend/il_x64.cc
index c91ed77..b7bca3f 100644
--- a/runtime/vm/compiler/backend/il_x64.cc
+++ b/runtime/vm/compiler/backend/il_x64.cc
@@ -567,12 +567,7 @@
__ LoadObject(destination.reg(), value_);
}
} else if (destination.IsFpuRegister()) {
- if (representation() == kUnboxedFloat) {
- __ LoadSImmediate(destination.fpu_reg(), Double::Cast(value_).value());
- } else {
- ASSERT(representation() == kUnboxedDouble);
- __ LoadDImmediate(destination.fpu_reg(), Double::Cast(value_).value());
- }
+ __ LoadDImmediate(destination.fpu_reg(), Double::Cast(value_).value());
} else if (destination.IsDoubleStackSlot()) {
__ LoadDImmediate(FpuTMP, Double::Cast(value_).value());
__ movsd(LocationToStackSlotAddress(destination), FpuTMP);
@@ -5048,6 +5043,35 @@
#undef DEFINE_EMIT
+LocationSummary* MathUnaryInstr::MakeLocationSummary(Zone* zone,
+ bool opt) const {
+ ASSERT((kind() == MathUnaryInstr::kSqrt) ||
+ (kind() == MathUnaryInstr::kDoubleSquare));
+ const intptr_t kNumInputs = 1;
+ const intptr_t kNumTemps = 0;
+ LocationSummary* summary = new (zone)
+ LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+ summary->set_in(0, Location::RequiresFpuRegister());
+ if (kind() == MathUnaryInstr::kDoubleSquare) {
+ summary->set_out(0, Location::SameAsFirstInput());
+ } else {
+ summary->set_out(0, Location::RequiresFpuRegister());
+ }
+ return summary;
+}
+
+void MathUnaryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ if (kind() == MathUnaryInstr::kSqrt) {
+ __ sqrtsd(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg());
+ } else if (kind() == MathUnaryInstr::kDoubleSquare) {
+ XmmRegister value_reg = locs()->in(0).fpu_reg();
+ __ mulsd(value_reg, value_reg);
+ ASSERT(value_reg == locs()->out(0).fpu_reg());
+ } else {
+ UNREACHABLE();
+ }
+}
+
LocationSummary* CaseInsensitiveCompareInstr::MakeLocationSummary(
Zone* zone,
bool opt) const {
@@ -5105,39 +5129,14 @@
LocationSummary* summary = new (zone)
LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
summary->set_in(0, Location::RequiresFpuRegister());
- summary->set_out(0, Location::RequiresFpuRegister());
+ summary->set_out(0, Location::SameAsFirstInput());
return summary;
}
void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- ASSERT(representation() == kUnboxedDouble);
- XmmRegister result = locs()->out(0).fpu_reg();
XmmRegister value = locs()->in(0).fpu_reg();
- switch (op_kind()) {
- case Token::kNEGATE:
- __ DoubleNegate(result, value);
- break;
- case Token::kSQRT:
- __ sqrtsd(result, value);
- break;
- case Token::kSQUARE:
- if (result != value) {
- __ movsd(result, value);
- }
- __ mulsd(result, value);
- break;
- case Token::kTRUNCATE:
- __ roundsd(result, value, compiler::Assembler::kRoundToZero);
- break;
- case Token::kFLOOR:
- __ roundsd(result, value, compiler::Assembler::kRoundDown);
- break;
- case Token::kCEILING:
- __ roundsd(result, value, compiler::Assembler::kRoundUp);
- break;
- default:
- UNREACHABLE();
- }
+ ASSERT(locs()->out(0).fpu_reg() == value);
+ __ DoubleNegate(value, value);
}
LocationSummary* MathMinMaxInstr::MakeLocationSummary(Zone* zone,
@@ -5362,6 +5361,40 @@
__ SmiTag(result);
}
+LocationSummary* DoubleToDoubleInstr::MakeLocationSummary(Zone* zone,
+ bool opt) const {
+ const intptr_t kNumInputs = 1;
+ const intptr_t kNumTemps = 0;
+ LocationSummary* result = new (zone)
+ LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+ result->set_in(0, Location::RequiresFpuRegister());
+ result->set_out(0, Location::RequiresFpuRegister());
+ return result;
+}
+
+void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ XmmRegister value = locs()->in(0).fpu_reg();
+ XmmRegister result = locs()->out(0).fpu_reg();
+ if (value != result) {
+ // Clear full register to avoid false dependency due to
+ // a partial access to XMM register in roundsd instruction.
+ __ xorps(result, result);
+ }
+ switch (recognized_kind()) {
+ case MethodRecognizer::kDoubleTruncateToDouble:
+ __ roundsd(result, value, compiler::Assembler::kRoundToZero);
+ break;
+ case MethodRecognizer::kDoubleFloorToDouble:
+ __ roundsd(result, value, compiler::Assembler::kRoundDown);
+ break;
+ case MethodRecognizer::kDoubleCeilToDouble:
+ __ roundsd(result, value, compiler::Assembler::kRoundUp);
+ break;
+ default:
+ UNREACHABLE();
+ }
+}
+
LocationSummary* DoubleToFloatInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
const intptr_t kNumInputs = 1;
@@ -5392,16 +5425,6 @@
__ cvtss2sd(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg());
}
-LocationSummary* FloatCompareInstr::MakeLocationSummary(Zone* zone,
- bool opt) const {
- UNREACHABLE();
- return NULL;
-}
-
-void FloatCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNREACHABLE();
-}
-
LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
// Calling convention on x64 uses XMM0 and XMM1 to pass the first two
@@ -5627,26 +5650,6 @@
}
}
-LocationSummary* UnboxLaneInstr::MakeLocationSummary(Zone* zone,
- bool opt) const {
- UNREACHABLE();
- return NULL;
-}
-
-void UnboxLaneInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNREACHABLE();
-}
-
-LocationSummary* BoxLanesInstr::MakeLocationSummary(Zone* zone,
- bool opt) const {
- UNREACHABLE();
- return NULL;
-}
-
-void BoxLanesInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNREACHABLE();
-}
-
LocationSummary* TruncDivModInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
const intptr_t kNumInputs = 2;
@@ -7009,26 +7012,6 @@
compiler::target::ObjectAlignment::kBoolValueMask));
}
-LocationSummary* BoolToIntInstr::MakeLocationSummary(Zone* zone,
- bool opt) const {
- UNREACHABLE();
- return NULL;
-}
-
-void BoolToIntInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNREACHABLE();
-}
-
-LocationSummary* IntToBoolInstr::MakeLocationSummary(Zone* zone,
- bool opt) const {
- UNREACHABLE();
- return NULL;
-}
-
-void IntToBoolInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNREACHABLE();
-}
-
LocationSummary* AllocateObjectInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
const intptr_t kNumInputs = (type_arguments() != nullptr) ? 1 : 0;
diff --git a/runtime/vm/compiler/backend/inliner.cc b/runtime/vm/compiler/backend/inliner.cc
index 7fdd085..dd8279d 100644
--- a/runtime/vm/compiler/backend/inliner.cc
+++ b/runtime/vm/compiler/backend/inliner.cc
@@ -78,7 +78,6 @@
"Max. number of inlined calls per depth");
DEFINE_FLAG(bool, print_inlining_tree, false, "Print inlining tree");
-DECLARE_FLAG(bool, enable_simd_inline);
DECLARE_FLAG(int, max_deoptimization_counter_threshold);
DECLARE_FLAG(bool, print_flow_graph);
DECLARE_FLAG(bool, print_flow_graph_optimized);
@@ -808,8 +807,7 @@
for (intptr_t i = 0; i < defns->length(); ++i) {
ConstantInstr* constant = (*defns)[i]->AsConstant();
if (constant != nullptr && constant->HasUses()) {
- constant->ReplaceUsesWith(caller_graph->GetConstant(
- constant->value(), constant->representation()));
+ constant->ReplaceUsesWith(caller_graph->GetConstant(constant->value()));
}
}
@@ -817,8 +815,7 @@
for (intptr_t i = 0; i < defns->length(); ++i) {
ConstantInstr* constant = (*defns)[i]->AsConstant();
if (constant != nullptr && constant->HasUses()) {
- constant->ReplaceUsesWith(caller_graph->GetConstant(
- constant->value(), constant->representation()));
+ constant->ReplaceUsesWith(caller_graph->GetConstant(constant->value()));
}
SpecialParameterInstr* param = (*defns)[i]->AsSpecialParameter();
@@ -3540,585 +3537,6 @@
return true;
}
-class SimdLowering : public ValueObject {
- public:
- SimdLowering(FlowGraph* flow_graph,
- Instruction* call,
- GraphEntryInstr* graph_entry,
- FunctionEntryInstr** entry,
- Instruction** last,
- Definition** result)
- : flow_graph_(flow_graph),
- call_(call),
- graph_entry_(graph_entry),
- entry_(entry),
- last_(last),
- result_(result) {
- *entry_ = new (zone())
- FunctionEntryInstr(graph_entry_, flow_graph_->allocate_block_id(),
- call_->GetBlock()->try_index(), call_->deopt_id());
- *last = *entry_;
- }
-
- bool TryInline(MethodRecognizer::Kind kind) {
- switch (kind) {
- // ==== Int32x4 ====
- case MethodRecognizer::kInt32x4FromInts:
- UnboxScalar(0, kUnboxedInt32, 4);
- UnboxScalar(1, kUnboxedInt32, 4);
- UnboxScalar(2, kUnboxedInt32, 4);
- UnboxScalar(3, kUnboxedInt32, 4);
- Gather(4);
- BoxVector(kUnboxedInt32, 4);
- return true;
- case MethodRecognizer::kInt32x4FromBools:
- UnboxBool(0, 4);
- UnboxBool(1, 4);
- UnboxBool(2, 4);
- UnboxBool(3, 4);
- Gather(4);
- BoxVector(kUnboxedInt32, 4);
- return true;
- case MethodRecognizer::kInt32x4GetFlagX:
- UnboxVector(0, kUnboxedInt32, kMintCid, 4);
- IntToBool();
- Return(0);
- return true;
- case MethodRecognizer::kInt32x4GetFlagY:
- UnboxVector(0, kUnboxedInt32, kMintCid, 4);
- IntToBool();
- Return(1);
- return true;
- case MethodRecognizer::kInt32x4GetFlagZ:
- UnboxVector(0, kUnboxedInt32, kMintCid, 4);
- IntToBool();
- Return(2);
- return true;
- case MethodRecognizer::kInt32x4GetFlagW:
- UnboxVector(0, kUnboxedInt32, kMintCid, 4);
- IntToBool();
- Return(3);
- return true;
- case MethodRecognizer::kInt32x4WithFlagX:
- UnboxVector(0, kUnboxedInt32, kMintCid, 4);
- UnboxBool(1, 4);
- With(0);
- BoxVector(kUnboxedInt32, 4);
- return true;
- case MethodRecognizer::kInt32x4WithFlagY:
- UnboxVector(0, kUnboxedInt32, kMintCid, 4);
- UnboxBool(1, 4);
- With(1);
- BoxVector(kUnboxedInt32, 4);
- return true;
- case MethodRecognizer::kInt32x4WithFlagZ:
- UnboxVector(0, kUnboxedInt32, kMintCid, 4);
- UnboxBool(1, 4);
- With(2);
- BoxVector(kUnboxedInt32, 4);
- return true;
- case MethodRecognizer::kInt32x4WithFlagW:
- UnboxVector(0, kUnboxedInt32, kMintCid, 4);
- UnboxBool(1, 4);
- With(3);
- BoxVector(kUnboxedInt32, 4);
- return true;
- case MethodRecognizer::kInt32x4Shuffle: {
- Definition* mask_definition =
- call_->ArgumentAt(call_->ArgumentCount() - 1);
- intptr_t mask = 0;
- if (!CheckMask(mask_definition, &mask)) {
- return false;
- }
- UnboxVector(0, kUnboxedInt32, kMintCid, 4);
- Shuffle(mask);
- BoxVector(kUnboxedInt32, 4);
- return true;
- }
- case MethodRecognizer::kInt32x4ShuffleMix: {
- Definition* mask_definition =
- call_->ArgumentAt(call_->ArgumentCount() - 1);
- intptr_t mask = 0;
- if (!CheckMask(mask_definition, &mask)) {
- return false;
- }
- UnboxVector(0, kUnboxedInt32, kMintCid, 4);
- UnboxVector(1, kUnboxedInt32, kMintCid, 4);
- ShuffleMix(mask);
- BoxVector(kUnboxedInt32, 4);
- return true;
- }
- case MethodRecognizer::kInt32x4GetSignMask:
- case MethodRecognizer::kInt32x4Select:
- // TODO(riscv)
- return false;
-
- // ==== Float32x4 ====
- case MethodRecognizer::kFloat32x4Abs:
- Float32x4Unary(Token::kABS);
- return true;
- case MethodRecognizer::kFloat32x4Negate:
- Float32x4Unary(Token::kNEGATE);
- return true;
- case MethodRecognizer::kFloat32x4Sqrt:
- Float32x4Unary(Token::kSQRT);
- return true;
- case MethodRecognizer::kFloat32x4Reciprocal:
- Float32x4Unary(Token::kRECIPROCAL);
- return true;
- case MethodRecognizer::kFloat32x4ReciprocalSqrt:
- Float32x4Unary(Token::kRECIPROCAL_SQRT);
- return true;
- case MethodRecognizer::kFloat32x4GetSignMask:
- // TODO(riscv)
- return false;
- case MethodRecognizer::kFloat32x4Equal:
- Float32x4Compare(Token::kEQ);
- return true;
- case MethodRecognizer::kFloat32x4GreaterThan:
- Float32x4Compare(Token::kGT);
- return true;
- case MethodRecognizer::kFloat32x4GreaterThanOrEqual:
- Float32x4Compare(Token::kGTE);
- return true;
- case MethodRecognizer::kFloat32x4LessThan:
- Float32x4Compare(Token::kLT);
- return true;
- case MethodRecognizer::kFloat32x4LessThanOrEqual:
- Float32x4Compare(Token::kLTE);
- return true;
- case MethodRecognizer::kFloat32x4Add:
- Float32x4Binary(Token::kADD);
- return true;
- case MethodRecognizer::kFloat32x4Sub:
- Float32x4Binary(Token::kSUB);
- return true;
- case MethodRecognizer::kFloat32x4Mul:
- Float32x4Binary(Token::kMUL);
- return true;
- case MethodRecognizer::kFloat32x4Div:
- Float32x4Binary(Token::kDIV);
- return true;
- case MethodRecognizer::kFloat32x4Min:
- Float32x4Binary(Token::kMIN);
- return true;
- case MethodRecognizer::kFloat32x4Max:
- Float32x4Binary(Token::kMAX);
- return true;
- case MethodRecognizer::kFloat32x4Scale:
- UnboxVector(0, kUnboxedFloat, kDoubleCid, 4);
- UnboxScalar(1, kUnboxedFloat, 4);
- BinaryDoubleOp(Token::kMUL, kUnboxedFloat, 4);
- BoxVector(kUnboxedFloat, 4);
- return true;
- case MethodRecognizer::kFloat32x4Splat:
- UnboxScalar(0, kUnboxedFloat, 4);
- Splat(4);
- BoxVector(kUnboxedFloat, 4);
- return true;
- case MethodRecognizer::kFloat32x4WithX:
- UnboxVector(0, kUnboxedFloat, kDoubleCid, 4);
- UnboxScalar(1, kUnboxedFloat, 4);
- With(0);
- BoxVector(kUnboxedFloat, 4);
- return true;
- case MethodRecognizer::kFloat32x4WithY:
- UnboxVector(0, kUnboxedFloat, kDoubleCid, 4);
- UnboxScalar(1, kUnboxedFloat, 4);
- With(1);
- BoxVector(kUnboxedFloat, 4);
- return true;
- case MethodRecognizer::kFloat32x4WithZ:
- UnboxVector(0, kUnboxedFloat, kDoubleCid, 4);
- UnboxScalar(1, kUnboxedFloat, 4);
- With(2);
- BoxVector(kUnboxedFloat, 4);
- return true;
- case MethodRecognizer::kFloat32x4WithW:
- UnboxVector(0, kUnboxedFloat, kDoubleCid, 4);
- UnboxScalar(1, kUnboxedFloat, 4);
- With(3);
- BoxVector(kUnboxedFloat, 4);
- return true;
- case MethodRecognizer::kFloat32x4Zero:
- UnboxDoubleZero(kUnboxedFloat, 4);
- BoxVector(kUnboxedFloat, 4);
- return true;
- case MethodRecognizer::kFloat32x4FromDoubles:
- UnboxScalar(0, kUnboxedFloat, 4);
- UnboxScalar(1, kUnboxedFloat, 4);
- UnboxScalar(2, kUnboxedFloat, 4);
- UnboxScalar(3, kUnboxedFloat, 4);
- Gather(4);
- BoxVector(kUnboxedFloat, 4);
- return true;
- case MethodRecognizer::kFloat32x4GetX:
- UnboxVector(0, kUnboxedFloat, kDoubleCid, 4);
- BoxScalar(0, kUnboxedFloat);
- return true;
- case MethodRecognizer::kFloat32x4GetY:
- UnboxVector(0, kUnboxedFloat, kDoubleCid, 4);
- BoxScalar(1, kUnboxedFloat);
- return true;
- case MethodRecognizer::kFloat32x4GetZ:
- UnboxVector(0, kUnboxedFloat, kDoubleCid, 4);
- BoxScalar(2, kUnboxedFloat);
- return true;
- case MethodRecognizer::kFloat32x4GetW:
- UnboxVector(0, kUnboxedFloat, kDoubleCid, 4);
- BoxScalar(3, kUnboxedFloat);
- return true;
- case MethodRecognizer::kFloat32x4Shuffle: {
- Definition* mask_definition =
- call_->ArgumentAt(call_->ArgumentCount() - 1);
- intptr_t mask = 0;
- if (!CheckMask(mask_definition, &mask)) {
- return false;
- }
- UnboxVector(0, kUnboxedFloat, kDoubleCid, 4);
- Shuffle(mask);
- BoxVector(kUnboxedFloat, 4);
- return true;
- }
- case MethodRecognizer::kFloat32x4ShuffleMix: {
- Definition* mask_definition =
- call_->ArgumentAt(call_->ArgumentCount() - 1);
- intptr_t mask = 0;
- if (!CheckMask(mask_definition, &mask)) {
- return false;
- }
- UnboxVector(0, kUnboxedFloat, kDoubleCid, 4);
- UnboxVector(1, kUnboxedFloat, kDoubleCid, 4);
- ShuffleMix(mask);
- BoxVector(kUnboxedFloat, 4);
- return true;
- }
-
- // ==== Float64x2 ====
- case MethodRecognizer::kFloat64x2Abs:
- Float64x2Unary(Token::kABS);
- return true;
- case MethodRecognizer::kFloat64x2Negate:
- Float64x2Unary(Token::kNEGATE);
- return true;
- case MethodRecognizer::kFloat64x2Sqrt:
- Float64x2Unary(Token::kSQRT);
- return true;
- case MethodRecognizer::kFloat64x2Add:
- Float64x2Binary(Token::kADD);
- return true;
- case MethodRecognizer::kFloat64x2Sub:
- Float64x2Binary(Token::kSUB);
- return true;
- case MethodRecognizer::kFloat64x2Mul:
- Float64x2Binary(Token::kMUL);
- return true;
- case MethodRecognizer::kFloat64x2Div:
- Float64x2Binary(Token::kDIV);
- return true;
- case MethodRecognizer::kFloat64x2Min:
- Float64x2Binary(Token::kMIN);
- return true;
- case MethodRecognizer::kFloat64x2Max:
- Float64x2Binary(Token::kMAX);
- return true;
- case MethodRecognizer::kFloat64x2Scale:
- UnboxVector(0, kUnboxedDouble, kDoubleCid, 2);
- UnboxScalar(1, kUnboxedDouble, 2);
- BinaryDoubleOp(Token::kMUL, kUnboxedDouble, 2);
- BoxVector(kUnboxedDouble, 2);
- return true;
- case MethodRecognizer::kFloat64x2Splat:
- UnboxScalar(0, kUnboxedDouble, 2);
- Splat(2);
- BoxVector(kUnboxedDouble, 2);
- return true;
- case MethodRecognizer::kFloat64x2WithX:
- UnboxVector(0, kUnboxedDouble, kDoubleCid, 2);
- UnboxScalar(1, kUnboxedDouble, 2);
- With(0);
- BoxVector(kUnboxedDouble, 2);
- return true;
- case MethodRecognizer::kFloat64x2WithY:
- UnboxVector(0, kUnboxedDouble, kDoubleCid, 2);
- UnboxScalar(1, kUnboxedDouble, 2);
- With(1);
- BoxVector(kUnboxedDouble, 2);
- return true;
- case MethodRecognizer::kFloat64x2Zero:
- UnboxDoubleZero(kUnboxedDouble, 2);
- BoxVector(kUnboxedDouble, 2);
- return true;
- case MethodRecognizer::kFloat64x2FromDoubles:
- UnboxScalar(0, kUnboxedDouble, 2);
- UnboxScalar(1, kUnboxedDouble, 2);
- Gather(2);
- BoxVector(kUnboxedDouble, 2);
- return true;
- case MethodRecognizer::kFloat64x2GetX:
- UnboxVector(0, kUnboxedDouble, kDoubleCid, 2);
- BoxScalar(0, kUnboxedDouble);
- return true;
- case MethodRecognizer::kFloat64x2GetY:
- UnboxVector(0, kUnboxedDouble, kDoubleCid, 2);
- BoxScalar(1, kUnboxedDouble);
- return true;
-
- // Mixed
- case MethodRecognizer::kFloat32x4ToFloat64x2: {
- UnboxVector(0, kUnboxedFloat, kDoubleCid, 4, 1);
- Float32x4ToFloat64x2();
- BoxVector(kUnboxedDouble, 2);
- return true;
- }
- case MethodRecognizer::kFloat64x2ToFloat32x4: {
- UnboxVector(0, kUnboxedDouble, kDoubleCid, 2, 1);
- Float64x2ToFloat32x4();
- BoxVector(kUnboxedFloat, 4);
- return true;
- }
- case MethodRecognizer::kInt32x4ToFloat32x4:
- UnboxVector(0, kUnboxedInt32, kMintCid, 4, 1);
- Int32x4ToFloat32x4();
- BoxVector(kUnboxedFloat, 4);
- return true;
- case MethodRecognizer::kFloat32x4ToInt32x4:
- UnboxVector(0, kUnboxedFloat, kDoubleCid, 4, 1);
- Float32x4ToInt32x4();
- BoxVector(kUnboxedInt32, 4);
- return true;
- default:
- return false;
- }
- }
-
- private:
- void Float32x4Unary(Token::Kind op) {
- UnboxVector(0, kUnboxedFloat, kDoubleCid, 4);
- UnaryDoubleOp(op, kUnboxedFloat, 4);
- BoxVector(kUnboxedFloat, 4);
- }
- void Float32x4Binary(Token::Kind op) {
- UnboxVector(0, kUnboxedFloat, kDoubleCid, 4);
- UnboxVector(1, kUnboxedFloat, kDoubleCid, 4);
- BinaryDoubleOp(op, kUnboxedFloat, 4);
- BoxVector(kUnboxedFloat, 4);
- }
- void Float32x4Compare(Token::Kind op) {
- UnboxVector(0, kUnboxedFloat, kDoubleCid, 4);
- UnboxVector(1, kUnboxedFloat, kDoubleCid, 4);
- FloatCompare(op);
- BoxVector(kUnboxedInt32, 4);
- }
- void Float64x2Unary(Token::Kind op) {
- UnboxVector(0, kUnboxedDouble, kDoubleCid, 2);
- UnaryDoubleOp(op, kUnboxedDouble, 2);
- BoxVector(kUnboxedDouble, 2);
- }
- void Float64x2Binary(Token::Kind op) {
- UnboxVector(0, kUnboxedDouble, kDoubleCid, 2);
- UnboxVector(1, kUnboxedDouble, kDoubleCid, 2);
- BinaryDoubleOp(op, kUnboxedDouble, 2);
- BoxVector(kUnboxedDouble, 2);
- }
-
- void UnboxVector(intptr_t i,
- Representation rep,
- intptr_t cid,
- intptr_t n,
- intptr_t type_args = 0) {
- Definition* arg = call_->ArgumentAt(i + type_args);
- if (CompilerState::Current().is_aot()) {
- // Add null-checks in case of the arguments are known to be compatible
- // but they are possibly nullable.
- // By inserting the null-check, we can allow the unbox instruction later
- // inserted to be non-speculative.
- arg = AddDefinition(new (zone()) CheckNullInstr(
- new (zone()) Value(arg), Symbols::SecondArg(), call_->deopt_id(),
- call_->source(), CheckNullInstr::kArgumentError));
- }
- for (intptr_t lane = 0; lane < n; lane++) {
- in_[i][lane] = AddDefinition(
- new (zone()) UnboxLaneInstr(new (zone()) Value(arg), lane, rep, cid));
- }
- }
-
- void UnboxScalar(intptr_t i,
- Representation rep,
- intptr_t n,
- intptr_t type_args = 0) {
- Definition* arg = call_->ArgumentAt(i + type_args);
- if (CompilerState::Current().is_aot()) {
- // Add null-checks in case of the arguments are known to be compatible
- // but they are possibly nullable.
- // By inserting the null-check, we can allow the unbox instruction later
- // inserted to be non-speculative.
- arg = AddDefinition(new (zone()) CheckNullInstr(
- new (zone()) Value(arg), Symbols::SecondArg(), call_->deopt_id(),
- call_->source(), CheckNullInstr::kArgumentError));
- }
- Definition* unbox = AddDefinition(
- UnboxInstr::Create(rep, new (zone()) Value(arg), DeoptId::kNone,
- Instruction::kNotSpeculative));
- for (intptr_t lane = 0; lane < n; lane++) {
- in_[i][lane] = unbox;
- }
- }
-
- void UnboxBool(intptr_t i, intptr_t n) {
- Definition* unbox = AddDefinition(new (zone()) BoolToIntInstr(
- call_->ArgumentValueAt(i)->CopyWithType(zone())));
- for (intptr_t lane = 0; lane < n; lane++) {
- in_[i][lane] = unbox;
- }
- }
-
- void UnboxDoubleZero(Representation rep, intptr_t n) {
- Definition* zero = flow_graph_->GetConstant(
- Double::ZoneHandle(Double::NewCanonical(0.0)), rep);
- for (intptr_t lane = 0; lane < n; lane++) {
- op_[lane] = zero;
- }
- }
-
- void UnaryDoubleOp(Token::Kind op, Representation rep, intptr_t n) {
- for (intptr_t lane = 0; lane < n; lane++) {
- op_[lane] = AddDefinition(new (zone()) UnaryDoubleOpInstr(
- op, new (zone()) Value(in_[0][lane]), call_->deopt_id(),
- Instruction::kNotSpeculative, rep));
- }
- }
-
- void BinaryDoubleOp(Token::Kind op, Representation rep, intptr_t n) {
- for (intptr_t lane = 0; lane < n; lane++) {
- op_[lane] = AddDefinition(new (zone()) BinaryDoubleOpInstr(
- op, new (zone()) Value(in_[0][lane]),
- new (zone()) Value(in_[1][lane]), call_->deopt_id(), call_->source(),
- Instruction::kNotSpeculative, rep));
- }
- }
-
- void FloatCompare(Token::Kind op) {
- for (intptr_t lane = 0; lane < 4; lane++) {
- op_[lane] = AddDefinition(
- new (zone()) FloatCompareInstr(op, new (zone()) Value(in_[0][lane]),
- new (zone()) Value(in_[1][lane])));
- }
- }
-
- void With(intptr_t i) {
- for (intptr_t lane = 0; lane < 4; lane++) {
- op_[lane] = in_[0][lane];
- }
- op_[i] = in_[1][0];
- }
- void Splat(intptr_t n) {
- for (intptr_t lane = 0; lane < n; lane++) {
- op_[lane] = in_[0][0];
- }
- }
- void Gather(intptr_t n) {
- for (intptr_t lane = 0; lane < n; lane++) {
- op_[lane] = in_[lane][0];
- }
- }
- void Shuffle(intptr_t mask) {
- op_[0] = in_[0][(mask >> 0) & 3];
- op_[1] = in_[0][(mask >> 2) & 3];
- op_[2] = in_[0][(mask >> 4) & 3];
- op_[3] = in_[0][(mask >> 6) & 3];
- }
- void ShuffleMix(intptr_t mask) {
- op_[0] = in_[0][(mask >> 0) & 3];
- op_[1] = in_[0][(mask >> 2) & 3];
- op_[2] = in_[1][(mask >> 4) & 3];
- op_[3] = in_[1][(mask >> 6) & 3];
- }
- void Float32x4ToFloat64x2() {
- for (intptr_t lane = 0; lane < 2; lane++) {
- op_[lane] = AddDefinition(new (zone()) FloatToDoubleInstr(
- new (zone()) Value(in_[0][lane]), DeoptId::kNone));
- }
- }
- void Float64x2ToFloat32x4() {
- for (intptr_t lane = 0; lane < 2; lane++) {
- op_[lane] = AddDefinition(new (zone()) DoubleToFloatInstr(
- new (zone()) Value(in_[0][lane]), DeoptId::kNone));
- }
- Definition* zero = flow_graph_->GetConstant(
- Double::ZoneHandle(Double::NewCanonical(0.0)), kUnboxedFloat);
- op_[2] = zero;
- op_[3] = zero;
- }
- void Int32x4ToFloat32x4() {
- for (intptr_t lane = 0; lane < 4; lane++) {
- op_[lane] = AddDefinition(new (zone()) BitCastInstr(
- kUnboxedInt32, kUnboxedFloat, new (zone()) Value(in_[0][lane])));
- }
- }
- void Float32x4ToInt32x4() {
- for (intptr_t lane = 0; lane < 4; lane++) {
- op_[lane] = AddDefinition(new (zone()) BitCastInstr(
- kUnboxedFloat, kUnboxedInt32, new (zone()) Value(in_[0][lane])));
- }
- }
- void IntToBool() {
- for (intptr_t lane = 0; lane < 4; lane++) {
- op_[lane] = AddDefinition(
- new (zone()) IntToBoolInstr(new (zone()) Value(in_[0][lane])));
- }
- }
-
- void BoxVector(Representation rep, intptr_t n) {
- Definition* box;
- if (n == 2) {
- box = new (zone()) BoxLanesInstr(rep, new (zone()) Value(op_[0]),
- new (zone()) Value(op_[1]));
- } else {
- ASSERT(n == 4);
- box = new (zone()) BoxLanesInstr(
- rep, new (zone()) Value(op_[0]), new (zone()) Value(op_[1]),
- new (zone()) Value(op_[2]), new (zone()) Value(op_[3]));
- }
- Done(AddDefinition(box));
- }
-
- void BoxScalar(intptr_t lane, Representation rep) {
- Definition* box = BoxInstr::Create(rep, new (zone()) Value(in_[0][lane]));
- Done(AddDefinition(box));
- }
-
- void Return(intptr_t lane) { Done(op_[lane]); }
-
- void Done(Definition* result) {
- // InheritDeoptTarget also inherits environment (which may add 'entry' into
- // env_use_list()), so InheritDeoptTarget should be done only after decided
- // to inline.
- (*entry_)->InheritDeoptTarget(zone(), call_);
- *result_ = result;
- }
-
- Definition* AddDefinition(Definition* def) {
- *last_ = flow_graph_->AppendTo(
- *last_, def, call_->deopt_id() != DeoptId::kNone ? call_->env() : NULL,
- FlowGraph::kValue);
- return def;
- }
- Zone* zone() { return flow_graph_->zone(); }
-
- FlowGraph* flow_graph_;
- Instruction* call_;
- GraphEntryInstr* graph_entry_;
- FunctionEntryInstr** entry_;
- Instruction** last_;
- Definition** result_;
-
- // First index is the argment number, second index is the lane number.
- Definition* in_[4][4];
- // Index is the lane number.
- Definition* op_[4];
-};
-
static bool InlineSimdOp(FlowGraph* flow_graph,
bool is_dynamic_call,
Instruction* call,
@@ -4128,6 +3546,9 @@
FunctionEntryInstr** entry,
Instruction** last,
Definition** result) {
+ if (!ShouldInlineSimd()) {
+ return false;
+ }
if (is_dynamic_call && call->ArgumentCount() > 1) {
// Issue(dartbug.com/37737): Dynamic invocation forwarders have the
// same recognized kind as the method they are forwarding to.
@@ -4142,19 +3563,6 @@
return false;
}
- if (!FLAG_enable_simd_inline) {
- return false;
- }
-
- if (!FlowGraphCompiler::SupportsUnboxedSimd128()) {
-#if defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
- SimdLowering lowering(flow_graph, call, graph_entry, entry, last, result);
- return lowering.TryInline(kind);
-#else
- UNREACHABLE();
-#endif
- }
-
*entry =
new (Z) FunctionEntryInstr(graph_entry, flow_graph->allocate_block_id(),
call->GetBlock()->try_index(), DeoptId::kNone);
diff --git a/runtime/vm/compiler/backend/type_propagator.cc b/runtime/vm/compiler/backend/type_propagator.cc
index f4e263b..b9804d5 100644
--- a/runtime/vm/compiler/backend/type_propagator.cc
+++ b/runtime/vm/compiler/backend/type_propagator.cc
@@ -1323,14 +1323,6 @@
return CompileType::Bool();
}
-CompileType BoolToIntInstr::ComputeType() const {
- return CompileType::Int();
-}
-
-CompileType IntToBoolInstr::ComputeType() const {
- return CompileType::Bool();
-}
-
CompileType InstanceOfInstr::ComputeType() const {
return CompileType::Bool();
}
@@ -1762,6 +1754,10 @@
return CompileType::FromCid(simd_op_result_cids[kind()]);
}
+CompileType MathUnaryInstr::ComputeType() const {
+ return CompileType::FromCid(kDoubleCid);
+}
+
CompileType MathMinMaxInstr::ComputeType() const {
return CompileType::FromCid(result_cid_);
}
@@ -1815,20 +1811,6 @@
}
}
-CompileType BoxLanesInstr::ComputeType() const {
- switch (from_representation()) {
- case kUnboxedFloat:
- return CompileType::FromCid(kFloat32x4Cid);
- case kUnboxedDouble:
- return CompileType::FromCid(kFloat64x2Cid);
- case kUnboxedInt32:
- return CompileType::FromCid(kInt32x4Cid);
- default:
- UNREACHABLE();
- return CompileType::Dynamic();
- }
-}
-
CompileType Int32ToDoubleInstr::ComputeType() const {
return CompileType::FromCid(kDoubleCid);
}
@@ -1841,12 +1823,12 @@
return CompileType::FromCid(kDoubleCid);
}
-CompileType FloatToDoubleInstr::ComputeType() const {
+CompileType DoubleToDoubleInstr::ComputeType() const {
return CompileType::FromCid(kDoubleCid);
}
-CompileType FloatCompareInstr::ComputeType() const {
- return CompileType::Int();
+CompileType FloatToDoubleInstr::ComputeType() const {
+ return CompileType::FromCid(kDoubleCid);
}
CompileType DoubleToFloatInstr::ComputeType() const {
@@ -1866,10 +1848,6 @@
return CompileType::FromCid(definition_cid_);
}
-CompileType UnboxLaneInstr::ComputeType() const {
- return CompileType::FromCid(definition_cid_);
-}
-
static AbstractTypePtr ExtractElementTypeFromArrayType(
const AbstractType& array_type) {
if (array_type.IsTypeParameter()) {
diff --git a/runtime/vm/compiler/frontend/base_flow_graph_builder.cc b/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
index c48dc65..7cd28de 100644
--- a/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
+++ b/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
@@ -1244,6 +1244,15 @@
return Fragment(instr);
}
+Fragment BaseFlowGraphBuilder::DoubleToDouble(
+ MethodRecognizer::Kind recognized_kind) {
+ Value* value = Pop();
+ auto* instr =
+ new (Z) DoubleToDoubleInstr(value, recognized_kind, GetNextDeoptId());
+ Push(instr);
+ return Fragment(instr);
+}
+
Fragment BaseFlowGraphBuilder::DoubleToInteger(
MethodRecognizer::Kind recognized_kind) {
Value* value = Pop();
@@ -1253,10 +1262,9 @@
return Fragment(instr);
}
-Fragment BaseFlowGraphBuilder::UnaryDoubleOp(Token::Kind op) {
+Fragment BaseFlowGraphBuilder::MathUnary(MathUnaryInstr::MathUnaryKind kind) {
Value* value = Pop();
- auto* instr = new (Z) UnaryDoubleOpInstr(op, value, GetNextDeoptId(),
- Instruction::kNotSpeculative);
+ auto* instr = new (Z) MathUnaryInstr(kind, value, GetNextDeoptId());
Push(instr);
return Fragment(instr);
}
diff --git a/runtime/vm/compiler/frontend/base_flow_graph_builder.h b/runtime/vm/compiler/frontend/base_flow_graph_builder.h
index 0632510..a91212e 100644
--- a/runtime/vm/compiler/frontend/base_flow_graph_builder.h
+++ b/runtime/vm/compiler/frontend/base_flow_graph_builder.h
@@ -455,13 +455,18 @@
Fragment InvokeMathCFunction(MethodRecognizer::Kind recognized_kind,
intptr_t num_inputs);
+ // Pops double value and converts it to double as specified
+ // by the recognized method (kDoubleTruncateToDouble,
+ // kDoubleFloorToDouble or kDoubleCeilToDouble).
+ Fragment DoubleToDouble(MethodRecognizer::Kind recognized_kind);
+
// Pops double value and converts it to int as specified
// by the recognized method (kDoubleToInteger,
// kDoubleFloorToInt or kDoubleCeilToInt).
Fragment DoubleToInteger(MethodRecognizer::Kind recognized_kind);
// Pops double value and applies unary math operation.
- Fragment UnaryDoubleOp(Token::Kind op);
+ Fragment MathUnary(MathUnaryInstr::MathUnaryKind kind);
// Records coverage for this position, if the current VM mode supports it.
Fragment RecordCoverage(TokenPosition position);
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc
index b1cc2ff..1e3707e 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.cc
+++ b/runtime/vm/compiler/frontend/kernel_to_il.cc
@@ -1634,26 +1634,14 @@
((kind == MethodRecognizer::kDoubleTruncateToDouble) ||
(kind == MethodRecognizer::kDoubleFloorToDouble) ||
(kind == MethodRecognizer::kDoubleCeilToDouble))) {
- switch (kind) {
- case MethodRecognizer::kDoubleTruncateToDouble:
- body += UnaryDoubleOp(Token::kTRUNCATE);
- break;
- case MethodRecognizer::kDoubleFloorToDouble:
- body += UnaryDoubleOp(Token::kFLOOR);
- break;
- case MethodRecognizer::kDoubleCeilToDouble:
- body += UnaryDoubleOp(Token::kCEILING);
- break;
- default:
- UNREACHABLE();
- }
+ body += DoubleToDouble(kind);
} else {
body += InvokeMathCFunction(kind, function.NumParameters());
}
} break;
case MethodRecognizer::kMathSqrt: {
body += LoadLocal(parsed_function_->RawParameterVariable(0));
- body += UnaryDoubleOp(Token::kSQRT);
+ body += MathUnary(MathUnaryInstr::kSqrt);
} break;
case MethodRecognizer::kFinalizerBase_setIsolate:
ASSERT_EQUAL(function.NumParameters(), 1);
diff --git a/runtime/vm/deferred_objects.cc b/runtime/vm/deferred_objects.cc
index de229ac..b64d7dd 100644
--- a/runtime/vm/deferred_objects.cc
+++ b/runtime/vm/deferred_objects.cc
@@ -395,9 +395,15 @@
static_cast<uint64_t>(Integer::Cast(value).AsInt64Value()));
break;
case kTypedDataFloat32ArrayCid:
+ // Although element of Float32 array is represented with Double,
+ // it is already converted to 32-bit float via DoubleToFloat
+ // instruction before it was stored.
+ // Reinterpret double value as float to get the value back.
typed_data.SetFloat32(
element_offset,
- static_cast<float>(Double::Cast(value).value()));
+ bit_cast<float, uint32_t>(
+ static_cast<uint32_t>(bit_cast<uint64_t, double>(
+ Double::Cast(value).value()))));
break;
case kTypedDataFloat64ArrayCid:
typed_data.SetFloat64(element_offset,
diff --git a/runtime/vm/deopt_instructions.cc b/runtime/vm/deopt_instructions.cc
index 497c453..20eec15 100644
--- a/runtime/vm/deopt_instructions.cc
+++ b/runtime/vm/deopt_instructions.cc
@@ -232,7 +232,6 @@
case DeoptInstr::kInt32x4:
case DeoptInstr::kFloat64x2:
case DeoptInstr::kWord:
- case DeoptInstr::kFloat:
case DeoptInstr::kDouble:
case DeoptInstr::kMint:
case DeoptInstr::kMintPair:
@@ -669,12 +668,6 @@
DISALLOW_COPY_AND_ASSIGN(DeoptFpuInstr);
};
-typedef DeoptFpuInstr<DeoptInstr::kFloat,
- CatchEntryMove::SourceKind::kFloatSlot,
- float,
- DoublePtr>
- DeoptFloatInstr;
-
typedef DeoptFpuInstr<DeoptInstr::kDouble,
CatchEntryMove::SourceKind::kDoubleSlot,
double,
@@ -909,8 +902,6 @@
switch (kind) {
case kWord:
return new DeoptWordInstr(source_index);
- case kFloat:
- return new DeoptFloatInstr(source_index);
case kDouble:
return new DeoptDoubleInstr(source_index);
case kMint:
@@ -954,8 +945,6 @@
switch (kind) {
case kWord:
return "word";
- case kFloat:
- return "float";
case kDouble:
return "double";
case kMint:
@@ -1138,9 +1127,6 @@
new (zone()) DeoptUint32Instr(ToCpuRegisterSource(source_loc));
break;
case kUnboxedFloat:
- deopt_instr = new (zone()) DeoptFloatInstr(
- ToFpuRegisterSource(source_loc, Location::kDoubleStackSlot));
- break;
case kUnboxedDouble:
deopt_instr = new (zone()) DeoptDoubleInstr(
ToFpuRegisterSource(source_loc, Location::kDoubleStackSlot));
diff --git a/runtime/vm/deopt_instructions.h b/runtime/vm/deopt_instructions.h
index ccfff06..cbd15c2 100644
--- a/runtime/vm/deopt_instructions.h
+++ b/runtime/vm/deopt_instructions.h
@@ -82,15 +82,7 @@
return cpu_registers_[reg];
}
- float FpuRegisterValueAsFloat(FpuRegister reg) const {
- ASSERT(FlowGraphCompiler::SupportsUnboxedDoubles());
- ASSERT(fpu_registers_ != NULL);
- ASSERT(reg >= 0);
- ASSERT(reg < kNumberOfFpuRegisters);
- return *reinterpret_cast<float*>(&fpu_registers_[reg]);
- }
-
- double FpuRegisterValueAsDouble(FpuRegister reg) const {
+ double FpuRegisterValue(FpuRegister reg) const {
ASSERT(FlowGraphCompiler::SupportsUnboxedDoubles());
ASSERT(fpu_registers_ != NULL);
ASSERT(reg >= 0);
@@ -167,11 +159,6 @@
idx, reinterpret_cast<ObjectPtr*>(slot), deferred_slots_);
}
- void DeferMaterialization(float value, DoublePtr* slot) {
- deferred_slots_ = new DeferredDouble(
- value, reinterpret_cast<ObjectPtr*>(slot), deferred_slots_);
- }
-
void DeferMaterialization(double value, DoublePtr* slot) {
deferred_slots_ = new DeferredDouble(
value, reinterpret_cast<ObjectPtr*>(slot), deferred_slots_);
@@ -280,7 +267,6 @@
kRetAddress,
kConstant,
kWord,
- kFloat,
kDouble,
kFloat32x4,
kFloat64x2,
@@ -372,16 +358,9 @@
};
template <>
-struct RegisterReader<FpuRegister, float> {
- static double Read(DeoptContext* context, FpuRegister reg) {
- return context->FpuRegisterValueAsFloat(reg);
- }
-};
-
-template <>
struct RegisterReader<FpuRegister, double> {
static double Read(DeoptContext* context, FpuRegister reg) {
- return context->FpuRegisterValueAsDouble(reg);
+ return context->FpuRegisterValue(reg);
}
};
diff --git a/runtime/vm/exceptions.cc b/runtime/vm/exceptions.cc
index 0d71595..23e9aa2 100644
--- a/runtime/vm/exceptions.cc
+++ b/runtime/vm/exceptions.cc
@@ -237,10 +237,6 @@
value = *TaggedSlotAt(fp, move.src_slot());
break;
- case CatchEntryMove::SourceKind::kFloatSlot:
- value = Double::New(*SlotAt<float>(fp, move.src_slot()));
- break;
-
case CatchEntryMove::SourceKind::kDoubleSlot:
value = Double::New(*SlotAt<double>(fp, move.src_slot()));
break;
@@ -373,11 +369,6 @@
Utils::SNPrint(from, ARRAY_SIZE(from), "fp[%" Pd "]", src_slot());
break;
- case SourceKind::kFloatSlot:
- Utils::SNPrint(from, ARRAY_SIZE(from), "f32 [fp + %" Pd "]",
- src_slot() * compiler::target::kWordSize);
- break;
-
case SourceKind::kDoubleSlot:
Utils::SNPrint(from, ARRAY_SIZE(from), "f64 [fp + %" Pd "]",
src_slot() * compiler::target::kWordSize);
diff --git a/runtime/vm/exceptions.h b/runtime/vm/exceptions.h
index f87201d..89090a6 100644
--- a/runtime/vm/exceptions.h
+++ b/runtime/vm/exceptions.h
@@ -147,7 +147,6 @@
enum class SourceKind {
kConstant,
kTaggedSlot,
- kFloatSlot,
kDoubleSlot,
kFloat32x4Slot,
kFloat64x2Slot,
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index af9539d..3b988bd 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -1739,13 +1739,6 @@
// how the vm_tag (kEmbedderTagId) can be set, these tags need to
// move to the OSThread structure.
set_user_tag(UserTags::kDefaultUserTag);
-
- if (group()->obfuscate()) {
- OS::PrintErr(
- "Warning: This VM has been configured to obfuscate symbol information "
- "which violates the Dart standard.\n"
- " See dartbug.com/30524 for more information.\n");
- }
}
#undef REUSABLE_HANDLE_SCOPE_INIT
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 4af9fe1..e7c7b72 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -25948,12 +25948,6 @@
isolate_instructions_image.instructions_relocated_address();
auto const vm_relocated_address =
vm_instructions_image.instructions_relocated_address();
- // The Dart standard requires the output of StackTrace.toString to include
- // all pending activations with precise source locations (i.e., to expand
- // inlined frames and provide line and column numbers).
- buffer.Printf(
- "Warning: This VM has been configured to produce stack traces "
- "that violate the Dart standard.\n");
// This prologue imitates Android's debuggerd to make it possible to paste
// the stack trace into ndk-stack.
buffer.Printf(
diff --git a/runtime/vm/token.cc b/runtime/vm/token.cc
index ad55e39..ba33707 100644
--- a/runtime/vm/token.cc
+++ b/runtime/vm/token.cc
@@ -56,8 +56,6 @@
case Token::kSHL:
case Token::kSHR:
case Token::kUSHR:
- case Token::kMAX:
- case Token::kMIN:
return true;
default:
return false;
@@ -65,21 +63,7 @@
}
bool Token::IsUnaryArithmeticOperator(Token::Kind token) {
- switch (token) {
- case Token::kBIT_NOT:
- case Token::kNEGATE:
- case Token::kABS:
- case Token::kSQRT:
- case Token::kSQUARE:
- case Token::kRECIPROCAL:
- case Token::kRECIPROCAL_SQRT:
- case Token::kTRUNCATE:
- case Token::kFLOOR:
- case Token::kCEILING:
- return true;
- default:
- return false;
- }
+ return (token == kBIT_NOT) || (token == kNEGATE);
}
bool Token::IsBinaryBitwiseOperator(Token::Kind token) {
diff --git a/runtime/vm/token.h b/runtime/vm/token.h
index 174af7d..e2fc074 100644
--- a/runtime/vm/token.h
+++ b/runtime/vm/token.h
@@ -140,17 +140,7 @@
TOK(kSCRIPTTAG, "#!", 0, kNoAttribute) \
\
/* Support for optimized code */ \
- TOK(kREM, "rem", 0, kNoAttribute) \
- TOK(kABS, "abs", 0, kNoAttribute) \
- TOK(kSQRT, "sqrt", 0, kNoAttribute) \
- TOK(kMIN, "min", 0, kNoAttribute) \
- TOK(kMAX, "max", 0, kNoAttribute) \
- TOK(kRECIPROCAL, "reciprocal", 0, kNoAttribute) \
- TOK(kRECIPROCAL_SQRT, "reciprocal-sqrt", 0, kNoAttribute) \
- TOK(kSQUARE, "square", 0, kNoAttribute) \
- TOK(kTRUNCATE, "truncate", 0, kNoAttribute) \
- TOK(kFLOOR, "floor", 0, kNoAttribute) \
- TOK(kCEILING, "ceiling", 0, kNoAttribute)
+ TOK(kREM, "", 0, kNoAttribute)
// List of keywords. The list must be alphabetically ordered. The
// keyword recognition code depends on the ordering.
diff --git a/sdk/lib/typed_data/typed_data.dart b/sdk/lib/typed_data/typed_data.dart
index 661b998..7dce112 100644
--- a/sdk/lib/typed_data/typed_data.dart
+++ b/sdk/lib/typed_data/typed_data.dart
@@ -2456,75 +2456,21 @@
Float32x4 operator /(Float32x4 other);
/// Relational less than.
- ///
- /// Equivalent to:
- ///
- /// ```
- /// Int32x4(this.x < other.x ? -1 : 0,
- /// this.y < other.y ? -1 : 0,
- /// this.z < other.z ? -1 : 0,
- /// this.w < other.w ? -1 : 0);
- /// ```
Int32x4 lessThan(Float32x4 other);
/// Relational less than or equal.
- ///
- /// Equivalent to:
- ///
- /// ```
- /// Int32x4(this.x <= other.x ? -1 : 0,
- /// this.y <= other.y ? -1 : 0,
- /// this.z <= other.z ? -1 : 0,
- /// this.w <= other.w ? -1 : 0);
- /// ```
Int32x4 lessThanOrEqual(Float32x4 other);
/// Relational greater than.
- ///
- /// Equivalent to:
- ///
- /// ```
- /// Int32x4(this.x > other.x ? -1 : 0,
- /// this.y > other.y ? -1 : 0,
- /// this.z > other.z ? -1 : 0,
- /// this.w > other.w ? -1 : 0);
- /// ```
Int32x4 greaterThan(Float32x4 other);
/// Relational greater than or equal.
- ///
- /// Equivalent to:
- ///
- /// ```
- /// Int32x4(this.x >= other.x ? -1 : 0,
- /// this.y >= other.y ? -1 : 0,
- /// this.z >= other.z ? -1 : 0,
- /// this.w >= other.w ? -1 : 0);
- /// ```
Int32x4 greaterThanOrEqual(Float32x4 other);
/// Relational equal.
- ///
- /// Equivalent to:
- ///
- /// ```
- /// Int32x4(this.x == other.x ? -1 : 0,
- /// this.y == other.y ? -1 : 0,
- /// this.z == other.z ? -1 : 0,
- /// this.w == other.w ? -1 : 0);
- /// ```
Int32x4 equal(Float32x4 other);
/// Relational not-equal.
- ///
- /// Equivalent to:
- ///
- /// ```
- /// Int32x4(this.x != other.x ? -1 : 0,
- /// this.y != other.y ? -1 : 0,
- /// this.z != other.z ? -1 : 0,
- /// this.w != other.w ? -1 : 0);
- /// ```
Int32x4 notEqual(Float32x4 other);
/// Returns a copy of [this] each lane being scaled by [s].
@@ -2856,14 +2802,7 @@
/// The lanes are "x", "y", "z", and "w" respectively.
abstract class Int32x4 {
external factory Int32x4(int x, int y, int z, int w);
-
- /// Equivalent to:
- ///
- /// ```
- /// Int32x4(x ? -1 : 0, y ? -1 : 0, z ? -1 : 0, w ? -1 : 0)
- /// ```
external factory Int32x4.bool(bool x, bool y, bool z, bool w);
-
external factory Int32x4.fromFloat32x4Bits(Float32x4 x);
/// The bit-wise or operator.
diff --git a/tools/VERSION b/tools/VERSION
index a7d80de..98ebbad 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 19
PATCH 0
-PRERELEASE 59
+PRERELEASE 60
PRERELEASE_PATCH 0
\ No newline at end of file