diff --git a/runtime/vm/flow_graph_optimizer.cc b/runtime/vm/flow_graph_optimizer.cc index e161f28dd31..d78a9112eed 100644 --- a/runtime/vm/flow_graph_optimizer.cc +++ b/runtime/vm/flow_graph_optimizer.cc @@ -274,6 +274,16 @@ static void RemovePushArguments(InstanceCallInstr* call) { } +static void RemovePushArguments(StaticCallInstr* call) { + // Remove original push arguments. + for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { + PushArgumentInstr* push = call->ArgumentAt(i); + push->ReplaceUsesWith(push->value()->definition()); + push->RemoveFromGraph(); + } +} + + // Returns true if all targets are the same. // TODO(srdjan): if targets are native use their C_function to compare. static bool HasOneTarget(const ICData& ic_data) { @@ -774,11 +784,13 @@ void FlowGraphOptimizer::VisitInstanceCall(InstanceCallInstr* instr) { } -void FlowGraphOptimizer::VisitStaticCall(StaticCallInstr* instr) { +void FlowGraphOptimizer::VisitStaticCall(StaticCallInstr* call) { MethodRecognizer::Kind recognized_kind = - MethodRecognizer::RecognizeKind(instr->function()); + MethodRecognizer::RecognizeKind(call->function()); if (recognized_kind == MethodRecognizer::kMathSqrt) { - instr->set_recognized(MethodRecognizer::kMathSqrt); + MathSqrtInstr* sqrt = new MathSqrtInstr(call->ArgumentAt(0)->value(), call); + call->ReplaceWith(sqrt, current_iterator()); + RemovePushArguments(call); } } diff --git a/runtime/vm/intermediate_language.cc b/runtime/vm/intermediate_language.cc index a3b0c89415a..66c90a56c81 100644 --- a/runtime/vm/intermediate_language.cc +++ b/runtime/vm/intermediate_language.cc @@ -1059,6 +1059,11 @@ RawAbstractType* UnboxedDoubleBinaryOpInstr::CompileType() const { } +RawAbstractType* MathSqrtInstr::CompileType() const { + return Type::Double(); +} + + RawAbstractType* UnboxDoubleInstr::CompileType() const { return Type::null(); } @@ -1468,18 +1473,12 @@ LocationSummary* StaticCallInstr::MakeLocationSummary() const { void StaticCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { - Label done; - if (recognized() == MethodRecognizer::kMathSqrt) { - compiler->GenerateInlinedMathSqrt(&done); - // Falls through to static call when operand type is not double or smi. - } compiler->GenerateStaticCall(deopt_id(), token_pos(), function(), ArgumentCount(), argument_names(), locs()); - __ Bind(&done); } diff --git a/runtime/vm/intermediate_language.h b/runtime/vm/intermediate_language.h index 2146042f275..a197184c9b1 100644 --- a/runtime/vm/intermediate_language.h +++ b/runtime/vm/intermediate_language.h @@ -239,6 +239,7 @@ class EmbeddedArray { M(Constant) \ M(CheckEitherNonSmi) \ M(UnboxedDoubleBinaryOp) \ + M(MathSqrt) \ M(UnboxDouble) \ M(BoxDouble) \ M(CheckArrayBound) \ @@ -436,6 +437,7 @@ FOR_EACH_INSTRUCTION(INSTRUCTION_TYPE_CHECK) // Classes that set deopt_id_. friend class UnboxDoubleInstr; friend class UnboxedDoubleBinaryOpInstr; + friend class MathSqrtInstr; friend class CheckClassInstr; friend class CheckSmiInstr; friend class CheckArrayBoundInstr; @@ -1984,8 +1986,7 @@ class StaticCallInstr : public TemplateDefinition<0> { : token_pos_(token_pos), function_(function), argument_names_(argument_names), - arguments_(arguments), - recognized_(MethodRecognizer::kUnknown) { + arguments_(arguments) { ASSERT(function.IsZoneHandle()); ASSERT(argument_names.IsZoneHandle()); } @@ -2003,9 +2004,6 @@ class StaticCallInstr : public TemplateDefinition<0> { return (*arguments_)[index]; } - MethodRecognizer::Kind recognized() const { return recognized_; } - void set_recognized(MethodRecognizer::Kind kind) { recognized_ = kind; } - virtual void PrintOperandsTo(BufferFormatter* f) const; virtual bool CanDeoptimize() const { return true; } @@ -2016,7 +2014,6 @@ class StaticCallInstr : public TemplateDefinition<0> { const Function& function_; const Array& argument_names_; ZoneGrowableArray* arguments_; - MethodRecognizer::Kind recognized_; DISALLOW_COPY_AND_ASSIGN(StaticCallInstr); }; @@ -2854,6 +2851,49 @@ class UnboxDoubleInstr : public TemplateDefinition<1> { }; +class MathSqrtInstr : public TemplateDefinition<1> { + public: + MathSqrtInstr(Value* value, StaticCallInstr* instance_call) { + ASSERT(value != NULL); + inputs_[0] = value; + deopt_id_ = instance_call->deopt_id(); + } + + Value* value() const { return inputs_[0]; } + + virtual bool CanDeoptimize() const { return false; } + virtual bool HasSideEffect() const { return false; } + + virtual bool AttributesEqual(Definition* other) const { + return true; + } + + // The output is not an instance but when it is boxed it becomes double. + virtual intptr_t ResultCid() const { return kDoubleCid; } + + virtual Representation representation() const { + return kUnboxedDouble; + } + + virtual Representation RequiredInputRepresentation(intptr_t idx) const { + ASSERT(idx == 0); + return kUnboxedDouble; + } + + virtual intptr_t DeoptimizationTarget() const { + // Direct access since this instuction cannot deoptimize, and the deopt-id + // was inherited from another instuction that could deoptimize. + return deopt_id_; + } + + DECLARE_INSTRUCTION(MathSqrt) + virtual RawAbstractType* CompileType() const; + + private: + DISALLOW_COPY_AND_ASSIGN(MathSqrtInstr); +}; + + class UnboxedDoubleBinaryOpInstr : public TemplateDefinition<2> { public: UnboxedDoubleBinaryOpInstr(Token::Kind op_kind, diff --git a/runtime/vm/intermediate_language_ia32.cc b/runtime/vm/intermediate_language_ia32.cc index c28234b65b0..3e3b0b97228 100644 --- a/runtime/vm/intermediate_language_ia32.cc +++ b/runtime/vm/intermediate_language_ia32.cc @@ -1979,6 +1979,22 @@ void UnboxedDoubleBinaryOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { } +LocationSummary* MathSqrtInstr::MakeLocationSummary() const { + const intptr_t kNumInputs = 1; + const intptr_t kNumTemps = 0; + LocationSummary* summary = + new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); + summary->set_in(0, Location::RequiresXmmRegister()); + summary->set_out(Location::RequiresXmmRegister()); + return summary; +} + + +void MathSqrtInstr::EmitNativeCode(FlowGraphCompiler* compiler) { + __ sqrtsd(locs()->out().xmm_reg(), locs()->in(0).xmm_reg()); +} + + LocationSummary* UnarySmiOpInstr::MakeLocationSummary() const { const intptr_t kNumInputs = 1; const intptr_t kNumTemps = 0; diff --git a/runtime/vm/intermediate_language_x64.cc b/runtime/vm/intermediate_language_x64.cc index 7b65bb2e0f9..5dbe92ed630 100644 --- a/runtime/vm/intermediate_language_x64.cc +++ b/runtime/vm/intermediate_language_x64.cc @@ -2006,6 +2006,22 @@ void UnboxedDoubleBinaryOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { } +LocationSummary* MathSqrtInstr::MakeLocationSummary() const { + const intptr_t kNumInputs = 1; + const intptr_t kNumTemps = 0; + LocationSummary* summary = + new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); + summary->set_in(0, Location::RequiresXmmRegister()); + summary->set_out(Location::RequiresXmmRegister()); + return summary; +} + + +void MathSqrtInstr::EmitNativeCode(FlowGraphCompiler* compiler) { + __ sqrtsd(locs()->out().xmm_reg(), locs()->in(0).xmm_reg()); +} + + LocationSummary* UnarySmiOpInstr::MakeLocationSummary() const { const intptr_t kNumInputs = 1; const intptr_t kNumTemps = 0;