diff --git a/runtime/vm/compiler/assembler/assembler_arm64.cc b/runtime/vm/compiler/assembler/assembler_arm64.cc index 02122a3b74c..645764916a4 100644 --- a/runtime/vm/compiler/assembler/assembler_arm64.cc +++ b/runtime/vm/compiler/assembler/assembler_arm64.cc @@ -662,20 +662,6 @@ void Assembler::LoadImmediate(Register reg, int64_t imm) { } } -void Assembler::LoadSImmediate(VRegister vd, float imms) { - int32_t imm32 = bit_cast(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 56b0fda9f88..ea47f526a7c 100644 --- a/runtime/vm/compiler/assembler/assembler_arm64.h +++ b/runtime/vm/compiler/assembler/assembler_arm64.h @@ -2066,7 +2066,6 @@ class Assembler : public AssemblerBase { 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 73d84a51af2..51c1fa90ac7 100644 --- a/runtime/vm/compiler/assembler/assembler_ia32.cc +++ b/runtime/vm/compiler/assembler/assembler_ia32.cc @@ -2199,13 +2199,6 @@ void Assembler::IncrementSmiField(const Address& dest, int32_t increment) { addl(dest, inc_imm); } -void Assembler::LoadSImmediate(XmmRegister dst, float value) { - int32_t constant = bit_cast(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(value); diff --git a/runtime/vm/compiler/assembler/assembler_ia32.h b/runtime/vm/compiler/assembler/assembler_ia32.h index 77b453b83ea..7ef533939fe 100644 --- a/runtime/vm/compiler/assembler/assembler_ia32.h +++ b/runtime/vm/compiler/assembler/assembler_ia32.h @@ -759,7 +759,6 @@ class Assembler : public AssemblerBase { 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 08a4b28ac50..10beeacbef8 100644 --- a/runtime/vm/compiler/assembler/assembler_riscv.cc +++ b/runtime/vm/compiler/assembler/assembler_riscv.cc @@ -3351,18 +3351,6 @@ void Assembler::LoadImmediate(Register reg, intx_t imm) { } } -void Assembler::LoadSImmediate(FRegister reg, float imms) { - int32_t imm = bit_cast(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(immd); if (imm == 0) { diff --git a/runtime/vm/compiler/assembler/assembler_riscv.h b/runtime/vm/compiler/assembler/assembler_riscv.h index 18eeb4a75cb..cefa2201ecb 100644 --- a/runtime/vm/compiler/assembler/assembler_riscv.h +++ b/runtime/vm/compiler/assembler/assembler_riscv.h @@ -432,8 +432,6 @@ class MicroAssembler : public AssemblerBase { 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 @@ class MicroAssembler : public AssemblerBase { 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 @@ class Assembler : public MicroAssembler { 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 @@ class Assembler : public MicroAssembler { 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 @@ class Assembler : public MicroAssembler { // 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 b7e098c908e..bfed0448f3c 100644 --- a/runtime/vm/compiler/assembler/assembler_x64.cc +++ b/runtime/vm/compiler/assembler/assembler_x64.cc @@ -1394,17 +1394,6 @@ void Assembler::MoveImmediate(const Address& dst, const Immediate& imm) { } } -void Assembler::LoadSImmediate(FpuRegister dst, float immediate) { - int32_t bits = bit_cast(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(immediate); if (bits == 0) { diff --git a/runtime/vm/compiler/assembler/assembler_x64.h b/runtime/vm/compiler/assembler/assembler_x64.h index d0b48f8ac6b..eafff9bbe37 100644 --- a/runtime/vm/compiler/assembler/assembler_x64.h +++ b/runtime/vm/compiler/assembler/assembler_x64.h @@ -787,7 +787,6 @@ class Assembler : public AssemblerBase { 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 @@ class Assembler : public AssemblerBase { 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 de4c6569bad..4a366314880 100644 --- a/runtime/vm/compiler/backend/block_builder.h +++ b/runtime/vm/compiler/backend/block_builder.h @@ -136,8 +136,6 @@ class BlockBuilder : public ValueObject { 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 8e530157994..8456490502a 100644 --- a/runtime/vm/compiler/backend/constant_propagator.cc +++ b/runtime/vm/compiler/backend/constant_propagator.cc @@ -872,16 +872,6 @@ void ConstantPropagator::VisitBooleanNegate(BooleanNegateInstr* instr) { } } -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 @@ void ConstantPropagator::VisitUnarySmiOp(UnarySmiOpInstr* instr) { 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 @@ void ConstantPropagator::VisitDoubleToSmi(DoubleToSmiInstr* instr) { 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 @@ void ConstantPropagator::VisitFloatToDouble(FloatToDoubleInstr* instr) { 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 @@ void ConstantPropagator::VisitExtractNthOutput(ExtractNthOutputInstr* instr) { 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 @@ void ConstantPropagator::VisitMaterializeObject(MaterializeObjectInstr* instr) { 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 @@ void ConstantPropagator::VisitBinaryDoubleOp(BinaryDoubleOpInstr* instr) { 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 @@ void ConstantPropagator::VisitSimdOp(SimdOpInstr* instr) { 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 2f9e3b33432..9ab7d3977e2 100644 --- a/runtime/vm/compiler/backend/evaluator.cc +++ b/runtime/vm/compiler/backend/evaluator.cc @@ -189,91 +189,20 @@ IntegerPtr Evaluator::BitLengthEvaluate(const Object& value, 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(value)); - case Token::kNEGATE: - return -static_cast(value); - case Token::kRECIPROCAL: - return 1.0f / static_cast(value); - case Token::kRECIPROCAL_SQRT: - return sqrtf(1.0f / static_cast(value)); - case Token::kSQRT: - return sqrtf(static_cast(value)); - case Token::kSQUARE: - return static_cast(value) * static_cast(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(left) + static_cast(right); - case Token::kSUB: - return static_cast(left) - static_cast(right); - case Token::kMUL: - return static_cast(left) * static_cast(right); - case Token::kDIV: - return static_cast(left) / static_cast(right); - case Token::kMIN: - return fminf(static_cast(left), static_cast(right)); - case Token::kMAX: - return fmaxf(static_cast(left), static_cast(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 afd05ed65af..dca583ace15 100644 --- a/runtime/vm/compiler/backend/evaluator.h +++ b/runtime/vm/compiler/backend/evaluator.h @@ -44,16 +44,10 @@ class Evaluator : public AllStatic { 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 d167f2de8cd..95691ce80ab 100644 --- a/runtime/vm/compiler/backend/flow_graph.cc +++ b/runtime/vm/compiler/backend/flow_graph.cc @@ -220,7 +220,6 @@ bool FlowGraph::IsConstantRepresentable(const Object& value, case kUnboxedInt64: return value.IsInteger(); - case kUnboxedFloat: case kUnboxedDouble: return value.IsInteger() || value.IsDouble(); @@ -239,13 +238,11 @@ Definition* FlowGraph::TryCreateConstantReplacementFor(Definition* op, 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 b0a50c6d117..6355ea91feb 100644 --- a/runtime/vm/compiler/backend/flow_graph_compiler.cc +++ b/runtime/vm/compiler/backend/flow_graph_compiler.cc @@ -395,9 +395,6 @@ static CatchEntryMove CatchEntryMoveFor(compiler::Assembler* assembler, 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 6be93b4425b..e7f9172b1db 100644 --- a/runtime/vm/compiler/backend/il.cc +++ b/runtime/vm/compiler/backend/il.cc @@ -547,8 +547,7 @@ Definition* Definition::OriginalDefinitionIgnoreBoxingAndConstraints() { 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 @@ static Definition* CanonicalizeCommutativeDoubleArithmetic(Token::Kind op, } 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(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 @@ Definition* BinaryDoubleOpInstr::Canonicalize(FlowGraph* flow_graph) { 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 @@ Definition* ConstantInstr::Canonicalize(FlowGraph* flow_graph) { 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 @@ Definition* BoxInstr::Canonicalize(FlowGraph* flow_graph) { 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* BoxInt64Instr::Canonicalize(FlowGraph* flow_graph) { Definition* UnboxInstr::Canonicalize(FlowGraph* flow_graph) { if (!HasUses() && !CanDeoptimize()) return NULL; + // Fold away Unbox(Box(v)). BoxInstr* box_defn = value()->definition()->AsBox(); - if (box_defn != NULL) { - // Fold away Unbox(Box(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 @@ Definition* UnboxInstr::Canonicalize(FlowGraph* flow_graph) { } } - if (representation() == kUnboxedFloat && value()->BindsToConstant()) { - const Object& val = value()->BoundConstant(); - if (val.IsInteger()) { - double narrowed_val = - static_cast(Integer::Cast(val).AsDoubleValue()); - return flow_graph->GetConstant( - Double::ZoneHandle(Double::NewCanonical(narrowed_val)), - kUnboxedFloat); - } else if (val.IsDouble()) { - double narrowed_val = static_cast(Double::Cast(val).value()); - return flow_graph->GetConstant( - Double::ZoneHandle(Double::NewCanonical(narrowed_val)), - kUnboxedFloat); - } - } - return this; } @@ -6470,6 +6431,19 @@ const RuntimeEntry& InvokeMathCFunctionInstr::TargetFunction() const { 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 d4df4c76919..af9f8b14a25 100644 --- a/runtime/vm/compiler/backend/il.h +++ b/runtime/vm/compiler/backend/il.h @@ -451,8 +451,6 @@ struct InstrAttrs { M(LoadStaticField, _) \ M(StoreStaticField, kNoGC) \ M(BooleanNegate, kNoGC) \ - M(BoolToInt, kNoGC) \ - M(IntToBool, kNoGC) \ M(InstanceOf, _) \ M(CreateArray, _) \ M(AllocateObject, _) \ @@ -476,9 +474,9 @@ struct InstrAttrs { 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 @@ struct InstrAttrs { M(CheckEitherNonSmi, kNoGC) \ M(BinaryDoubleOp, kNoGC) \ M(DoubleTestOp, kNoGC) \ + M(MathUnary, kNoGC) \ M(MathMinMax, kNoGC) \ M(Box, _) \ M(Unbox, kNoGC) \ @@ -516,8 +515,6 @@ struct InstrAttrs { 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 @@ class BooleanNegateInstr : public TemplateDefinition<1, NoThrow> { 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 @@ bool Definition::IsInt64Definition() { 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 @@ class BinaryDoubleOpInstr : public TemplateDefinition<2, NoThrow, Pure> { 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 @@ class BinaryDoubleOpInstr : public TemplateDefinition<2, NoThrow, Pure> { 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 @@ class BinaryDoubleOpInstr : public TemplateDefinition<2, NoThrow, Pure> { 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 @@ class SpeculativeShiftUint32OpInstr : public ShiftIntegerOpInstr { 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 @@ class UnaryDoubleOpInstr : public TemplateDefinition<1, NoThrow, Pure> { 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 @@ class UnaryDoubleOpInstr : public TemplateDefinition<1, NoThrow, Pure> { } 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 @@ class UnaryDoubleOpInstr : public TemplateDefinition<1, NoThrow, Pure> { private: const Token::Kind op_kind_; const SpeculativeMode speculative_mode_; - const Representation representation_; DISALLOW_COPY_AND_ASSIGN(UnaryDoubleOpInstr); }; @@ -8585,6 +8574,51 @@ class DoubleToSmiInstr : public TemplateDefinition<1, NoThrow, Pure> { 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 @@ class FloatToDoubleInstr : public TemplateDefinition<1, NoThrow, Pure> { 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 @@ class ExtractNthOutputInstr : public TemplateDefinition<1, NoThrow, Pure> { 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 0e131fa8c1e..e4bc74bb1d3 100644 --- a/runtime/vm/compiler/backend/il_arm.cc +++ b/runtime/vm/compiler/backend/il_arm.cc @@ -698,10 +698,11 @@ void ConstantInstr::EmitMoveToLocation(FlowGraphCompiler* compiler, } } 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 @@ void SimdOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { #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 @@ LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary(Zone* zone, } 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 @@ void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { __ 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 @@ void FloatToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { __ 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 @@ void ExtractNthOutputInstr::EmitNativeCode(FlowGraphCompiler* compiler) { } } -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 @@ void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 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 e61557a5e9c..ca277fb4942 100644 --- a/runtime/vm/compiler/backend/il_arm64.cc +++ b/runtime/vm/compiler/backend/il_arm64.cc @@ -625,12 +625,6 @@ void ConstantInstr::EmitMoveToLocation(FlowGraphCompiler* compiler, } 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 @@ void SimdOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { #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 @@ LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary(Zone* zone, } 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 @@ void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { __ 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 @@ void FloatToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { __ 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 @@ void ExtractNthOutputInstr::EmitNativeCode(FlowGraphCompiler* compiler) { } } -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 @@ void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 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 4d24aa2620d..b84f33e94c3 100644 --- a/runtime/vm/compiler/backend/il_ia32.cc +++ b/runtime/vm/compiler/backend/il_ia32.cc @@ -421,23 +421,18 @@ void ConstantInstr::EmitMoveToLocation(FlowGraphCompiler* compiler, __ LoadObjectSafely(destination.reg(), value_); } } else if (destination.IsFpuRegister()) { - if (representation() == kUnboxedFloat) { - __ LoadSImmediate(destination.fpu_reg(), - static_cast(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 @@ void SimdOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { #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 @@ LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary(Zone* zone, } 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 @@ void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { __ 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 @@ void FloatToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { __ 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 @@ void ExtractNthOutputInstr::EmitNativeCode(FlowGraphCompiler* compiler) { } } -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 @@ void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 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 da9c0c9339f..05b70509015 100644 --- a/runtime/vm/compiler/backend/il_printer.cc +++ b/runtime/vm/compiler/backend/il_printer.cc @@ -484,9 +484,7 @@ void Definition::PrintTo(BaseTextBuffer* f) const { 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 @@ void ConstantInstr::PrintOperandsTo(BaseTextBuffer* f) const { 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 @@ void AllocateUninitializedContextInstr::PrintOperandsTo( 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 @@ void ExtractNthOutputInstr::PrintOperandsTo(BaseTextBuffer* f) const { 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 2222f9b4cc5..041f1803a75 100644 --- a/runtime/vm/compiler/backend/il_riscv.cc +++ b/runtime/vm/compiler/backend/il_riscv.cc @@ -715,12 +715,7 @@ void ConstantInstr::EmitMoveToLocation(FlowGraphCompiler* compiler, } } 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 @@ static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler, __ 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 @@ static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler, __ 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 @@ void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { __ LoadDFieldFromOffset(result, temp, Double::value_offset()); break; case kFloat32x4Cid: - __ Comment("UnboxedFloat32x4LoadFieldInstr"); UNIMPLEMENTED(); break; case kFloat64x2Cid: - __ Comment("UnboxedFloat64x2LoadFieldInstr"); UNIMPLEMENTED(); break; default: @@ -4441,16 +4434,6 @@ void UnboxInstr::EmitSmiConversion(FlowGraphCompiler* compiler) { } #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 @@ void BinaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 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 @@ Condition DoubleTestOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, 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 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 temp)) { + UNIMPLEMENTED(); +} + +DEFINE_EMIT(Int32x4GetFlag, (Register result, FRegister value)) { + UNIMPLEMENTED(); +} + +DEFINE_EMIT(Int32x4Select, + (FRegister out, + FRegister mask, + FRegister trueValue, + FRegister falseValue, + Temp 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 @@ LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary(Zone* zone, 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 @@ void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { __ 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 @@ void FloatToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { __ 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 @@ void ExtractNthOutputInstr::EmitNativeCode(FlowGraphCompiler* compiler) { } } -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 @@ void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { __ 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 c91ed777ac9..b7bca3f40aa 100644 --- a/runtime/vm/compiler/backend/il_x64.cc +++ b/runtime/vm/compiler/backend/il_x64.cc @@ -567,12 +567,7 @@ void ConstantInstr::EmitMoveToLocation(FlowGraphCompiler* compiler, __ 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 @@ void SimdOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { #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* UnaryDoubleOpInstr::MakeLocationSummary(Zone* zone, 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 @@ void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { __ 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 @@ void FloatToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { __ 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 @@ void ExtractNthOutputInstr::EmitNativeCode(FlowGraphCompiler* compiler) { } } -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 @@ void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 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 7fdd0858227..dd8279d85de 100644 --- a/runtime/vm/compiler/backend/inliner.cc +++ b/runtime/vm/compiler/backend/inliner.cc @@ -78,7 +78,6 @@ DEFINE_FLAG(int, "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 @@ static void ReplaceParameterStubs(Zone* zone, 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 @@ static void ReplaceParameterStubs(Zone* zone, 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 @@ static bool CheckMask(Definition* definition, intptr_t* mask_ptr) { 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 @@ static bool InlineSimdOp(FlowGraph* flow_graph, 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 @@ static bool InlineSimdOp(FlowGraph* flow_graph, 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 f4e263ba45b..b9804d5cb47 100644 --- a/runtime/vm/compiler/backend/type_propagator.cc +++ b/runtime/vm/compiler/backend/type_propagator.cc @@ -1323,14 +1323,6 @@ CompileType BooleanNegateInstr::ComputeType() const { 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 @@ CompileType SimdOpInstr::ComputeType() const { 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 BoxInstr::ComputeType() const { } } -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 @@ CompileType Int64ToDoubleInstr::ComputeType() const { 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 @@ CompileType ExtractNthOutputInstr::ComputeType() const { 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 c48dc65b8ec..7cd28de698f 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 @@ Fragment BaseFlowGraphBuilder::InvokeMathCFunction( 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 @@ Fragment BaseFlowGraphBuilder::DoubleToInteger( 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 06325108ab8..a91212e4f1e 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 @@ class BaseFlowGraphBuilder { 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 b1cc2ff3836..1e3707ed993 100644 --- a/runtime/vm/compiler/frontend/kernel_to_il.cc +++ b/runtime/vm/compiler/frontend/kernel_to_il.cc @@ -1634,26 +1634,14 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfRecognizedMethod( ((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 de229ac26bb..b64d7dd2a48 100644 --- a/runtime/vm/deferred_objects.cc +++ b/runtime/vm/deferred_objects.cc @@ -395,9 +395,15 @@ void DeferredObject::Fill() { static_cast(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(Double::Cast(value).value())); + bit_cast( + static_cast(bit_cast( + 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 497c4532a27..20eec15af80 100644 --- a/runtime/vm/deopt_instructions.cc +++ b/runtime/vm/deopt_instructions.cc @@ -232,7 +232,6 @@ static bool IsObjectInstruction(DeoptInstr::Kind kind) { 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 @@ class DeoptFpuInstr : public DeoptInstr { DISALLOW_COPY_AND_ASSIGN(DeoptFpuInstr); }; -typedef DeoptFpuInstr - DeoptFloatInstr; - typedef DeoptFpuInstr= 0); - ASSERT(reg < kNumberOfFpuRegisters); - return *reinterpret_cast(&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 @@ class DeoptContext : public MallocAllocated { idx, reinterpret_cast(slot), deferred_slots_); } - void DeferMaterialization(float value, DoublePtr* slot) { - deferred_slots_ = new DeferredDouble( - value, reinterpret_cast(slot), deferred_slots_); - } - void DeferMaterialization(double value, DoublePtr* slot) { deferred_slots_ = new DeferredDouble( value, reinterpret_cast(slot), deferred_slots_); @@ -280,7 +267,6 @@ class DeoptInstr : public ZoneAllocated { kRetAddress, kConstant, kWord, - kFloat, kDouble, kFloat32x4, kFloat64x2, @@ -371,17 +357,10 @@ struct RegisterReader { } }; -template <> -struct RegisterReader { - static double Read(DeoptContext* context, FpuRegister reg) { - return context->FpuRegisterValueAsFloat(reg); - } -}; - template <> struct RegisterReader { 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 0d715957587..23e9aa240c9 100644 --- a/runtime/vm/exceptions.cc +++ b/runtime/vm/exceptions.cc @@ -237,10 +237,6 @@ class ExceptionHandlerFinder : public StackResource { value = *TaggedSlotAt(fp, move.src_slot()); break; - case CatchEntryMove::SourceKind::kFloatSlot: - value = Double::New(*SlotAt(fp, move.src_slot())); - break; - case CatchEntryMove::SourceKind::kDoubleSlot: value = Double::New(*SlotAt(fp, move.src_slot())); break; @@ -373,11 +369,6 @@ const char* CatchEntryMove::ToCString() const { 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 f87201d4842..89090a67ef5 100644 --- a/runtime/vm/exceptions.h +++ b/runtime/vm/exceptions.h @@ -147,7 +147,6 @@ class CatchEntryMove { enum class SourceKind { kConstant, kTaggedSlot, - kFloatSlot, kDoubleSlot, kFloat32x4Slot, kFloat64x2Slot, diff --git a/runtime/vm/token.cc b/runtime/vm/token.cc index ad55e3916d4..ba33707a27a 100644 --- a/runtime/vm/token.cc +++ b/runtime/vm/token.cc @@ -56,8 +56,6 @@ bool Token::IsBinaryArithmeticOperator(Token::Kind token) { 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::IsBinaryArithmeticOperator(Token::Kind token) { } 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 174af7dd68c..e2fc07442c7 100644 --- a/runtime/vm/token.h +++ b/runtime/vm/token.h @@ -140,17 +140,7 @@ namespace dart { 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 661b9981201..7dce1129667 100644 --- a/sdk/lib/typed_data/typed_data.dart +++ b/sdk/lib/typed_data/typed_data.dart @@ -2456,75 +2456,21 @@ abstract class Float32x4 { 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 @@ abstract class Float32x4 { /// 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.