| Index: runtime/vm/flow_graph_optimizer.cc
|
| diff --git a/runtime/vm/flow_graph_optimizer.cc b/runtime/vm/flow_graph_optimizer.cc
|
| index afa0bb9ed78f91935be28453274e476c92fa2a8a..45305081a13f3d3594f583207873747fe91acc52 100644
|
| --- a/runtime/vm/flow_graph_optimizer.cc
|
| +++ b/runtime/vm/flow_graph_optimizer.cc
|
| @@ -1943,6 +1943,8 @@ bool FlowGraphOptimizer::TryReplaceWithBinaryOp(InstanceCallInstr* call,
|
| operands_type = kFloat32x4Cid;
|
| } else if (HasOnlyTwoOf(ic_data, kInt32x4Cid)) {
|
| operands_type = kInt32x4Cid;
|
| + } else if (HasOnlyTwoOf(ic_data, kFloat64x2Cid)) {
|
| + operands_type = kFloat64x2Cid;
|
| } else {
|
| return false;
|
| }
|
| @@ -2063,6 +2065,8 @@ bool FlowGraphOptimizer::TryReplaceWithBinaryOp(InstanceCallInstr* call,
|
| return InlineFloat32x4BinaryOp(call, op_kind);
|
| } else if (operands_type == kInt32x4Cid) {
|
| return InlineInt32x4BinaryOp(call, op_kind);
|
| + } else if (operands_type == kFloat64x2Cid) {
|
| + return InlineFloat64x2BinaryOp(call, op_kind);
|
| } else if (op_kind == Token::kMOD) {
|
| ASSERT(operands_type == kSmiCid);
|
| if (right->IsConstant()) {
|
| @@ -2333,6 +2337,29 @@ bool FlowGraphOptimizer::InlineFloat32x4Getter(InstanceCallInstr* call,
|
| }
|
|
|
|
|
| +bool FlowGraphOptimizer::InlineFloat64x2Getter(InstanceCallInstr* call,
|
| + MethodRecognizer::Kind getter) {
|
| + AddCheckClass(call->ArgumentAt(0),
|
| + ICData::ZoneHandle(
|
| + call->ic_data()->AsUnaryClassChecksForArgNr(0)),
|
| + call->deopt_id(),
|
| + call->env(),
|
| + call);
|
| + if ((getter == MethodRecognizer::kFloat64x2GetX) ||
|
| + (getter == MethodRecognizer::kFloat64x2GetY)) {
|
| + Simd64x2ShuffleInstr* instr = new Simd64x2ShuffleInstr(
|
| + getter,
|
| + new Value(call->ArgumentAt(0)),
|
| + 0,
|
| + call->deopt_id());
|
| + ReplaceCall(call, instr);
|
| + return true;
|
| + }
|
| + UNREACHABLE();
|
| + return false;
|
| +}
|
| +
|
| +
|
| bool FlowGraphOptimizer::InlineInt32x4Getter(InstanceCallInstr* call,
|
| MethodRecognizer::Kind getter) {
|
| if (!ShouldInlineSimd()) {
|
| @@ -2471,6 +2498,37 @@ bool FlowGraphOptimizer::InlineInt32x4BinaryOp(InstanceCallInstr* call,
|
| }
|
|
|
|
|
| +bool FlowGraphOptimizer::InlineFloat64x2BinaryOp(InstanceCallInstr* call,
|
| + Token::Kind op_kind) {
|
| + if (!ShouldInlineSimd()) {
|
| + return false;
|
| + }
|
| + ASSERT(call->ArgumentCount() == 2);
|
| + Definition* left = call->ArgumentAt(0);
|
| + Definition* right = call->ArgumentAt(1);
|
| + // Type check left.
|
| + AddCheckClass(left,
|
| + ICData::ZoneHandle(
|
| + call->ic_data()->AsUnaryClassChecksForArgNr(0)),
|
| + call->deopt_id(),
|
| + call->env(),
|
| + call);
|
| + // Type check right.
|
| + AddCheckClass(right,
|
| + ICData::ZoneHandle(
|
| + call->ic_data()->AsUnaryClassChecksForArgNr(1)),
|
| + call->deopt_id(),
|
| + call->env(),
|
| + call);
|
| + // Replace call.
|
| + BinaryFloat64x2OpInstr* float64x2_bin_op =
|
| + new BinaryFloat64x2OpInstr(op_kind, new Value(left), new Value(right),
|
| + call->deopt_id());
|
| + ReplaceCall(call, float64x2_bin_op);
|
| + return true;
|
| +}
|
| +
|
| +
|
| // Only unique implicit instance getters can be currently handled.
|
| bool FlowGraphOptimizer::TryInlineInstanceGetter(InstanceCallInstr* call) {
|
| ASSERT(call->HasICData());
|
| @@ -2863,6 +2921,10 @@ bool FlowGraphOptimizer::TryInlineInstanceMethod(InstanceCallInstr* call) {
|
| return TryInlineInt32x4Method(call, recognized_kind);
|
| }
|
|
|
| + if ((class_ids[0] == kFloat64x2Cid) && (ic_data.NumberOfChecks() == 1)) {
|
| + return TryInlineFloat64x2Method(call, recognized_kind);
|
| + }
|
| +
|
| if (recognized_kind == MethodRecognizer::kIntegerLeftShiftWithMask32) {
|
| ASSERT(call->ArgumentCount() == 3);
|
| ASSERT(ic_data.num_args_tested() == 2);
|
| @@ -2958,6 +3020,46 @@ bool FlowGraphOptimizer::TryInlineFloat32x4Constructor(
|
| call->deopt_id());
|
| ReplaceCall(call, cast);
|
| return true;
|
| + } else if (recognized_kind == MethodRecognizer::kFloat32x4FromFloat64x2) {
|
| + Float64x2ToFloat32x4Instr* cast =
|
| + new Float64x2ToFloat32x4Instr(new Value(call->ArgumentAt(1)),
|
| + call->deopt_id());
|
| + ReplaceCall(call, cast);
|
| + return true;
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +
|
| +bool FlowGraphOptimizer::TryInlineFloat64x2Constructor(
|
| + StaticCallInstr* call,
|
| + MethodRecognizer::Kind recognized_kind) {
|
| + if (!ShouldInlineSimd()) {
|
| + return false;
|
| + }
|
| + if (recognized_kind == MethodRecognizer::kFloat64x2Zero) {
|
| + Float64x2ZeroInstr* zero = new Float64x2ZeroInstr(call->deopt_id());
|
| + ReplaceCall(call, zero);
|
| + return true;
|
| + } else if (recognized_kind == MethodRecognizer::kFloat64x2Splat) {
|
| + Float64x2SplatInstr* splat =
|
| + new Float64x2SplatInstr(new Value(call->ArgumentAt(1)),
|
| + call->deopt_id());
|
| + ReplaceCall(call, splat);
|
| + return true;
|
| + } else if (recognized_kind == MethodRecognizer::kFloat64x2Constructor) {
|
| + Float64x2ConstructorInstr* con =
|
| + new Float64x2ConstructorInstr(new Value(call->ArgumentAt(1)),
|
| + new Value(call->ArgumentAt(2)),
|
| + call->deopt_id());
|
| + ReplaceCall(call, con);
|
| + return true;
|
| + } else if (recognized_kind == MethodRecognizer::kFloat64x2FromFloat32x4) {
|
| + Float32x4ToFloat64x2Instr* cast =
|
| + new Float32x4ToFloat64x2Instr(new Value(call->ArgumentAt(1)),
|
| + call->deopt_id());
|
| + ReplaceCall(call, cast);
|
| + return true;
|
| }
|
| return false;
|
| }
|
| @@ -3144,6 +3246,25 @@ bool FlowGraphOptimizer::TryInlineFloat32x4Method(
|
| }
|
|
|
|
|
| +bool FlowGraphOptimizer::TryInlineFloat64x2Method(
|
| + InstanceCallInstr* call,
|
| + MethodRecognizer::Kind recognized_kind) {
|
| + if (!ShouldInlineSimd()) {
|
| + return false;
|
| + }
|
| + ASSERT(call->HasICData());
|
| + switch (recognized_kind) {
|
| + case MethodRecognizer::kFloat64x2GetX:
|
| + case MethodRecognizer::kFloat64x2GetY:
|
| + ASSERT(call->ic_data()->HasReceiverClassId(kFloat64x2Cid));
|
| + ASSERT(call->ic_data()->HasOneTarget());
|
| + return InlineFloat64x2Getter(call, recognized_kind);
|
| + default:
|
| + return false;
|
| + }
|
| +}
|
| +
|
| +
|
| bool FlowGraphOptimizer::TryInlineInt32x4Method(
|
| InstanceCallInstr* call,
|
| MethodRecognizer::Kind recognized_kind) {
|
| @@ -3818,8 +3939,14 @@ void FlowGraphOptimizer::VisitStaticCall(StaticCallInstr* call) {
|
| ReplaceCall(call, math_unary);
|
| } else if ((recognized_kind == MethodRecognizer::kFloat32x4Zero) ||
|
| (recognized_kind == MethodRecognizer::kFloat32x4Splat) ||
|
| - (recognized_kind == MethodRecognizer::kFloat32x4Constructor)) {
|
| + (recognized_kind == MethodRecognizer::kFloat32x4Constructor) ||
|
| + (recognized_kind == MethodRecognizer::kFloat32x4FromFloat64x2)) {
|
| TryInlineFloat32x4Constructor(call, recognized_kind);
|
| + } else if ((recognized_kind == MethodRecognizer::kFloat64x2Constructor) ||
|
| + (recognized_kind == MethodRecognizer::kFloat64x2Zero) ||
|
| + (recognized_kind == MethodRecognizer::kFloat64x2Splat) ||
|
| + (recognized_kind == MethodRecognizer::kFloat64x2FromFloat32x4)) {
|
| + TryInlineFloat64x2Constructor(call, recognized_kind);
|
| } else if (recognized_kind == MethodRecognizer::kInt32x4BoolConstructor) {
|
| TryInlineInt32x4Constructor(call, recognized_kind);
|
| } else if (recognized_kind == MethodRecognizer::kObjectConstructor) {
|
| @@ -7735,6 +7862,46 @@ void ConstantPropagator::VisitBinaryInt32x4Op(BinaryInt32x4OpInstr* instr) {
|
| }
|
|
|
|
|
| +void ConstantPropagator::VisitSimd64x2Shuffle(Simd64x2ShuffleInstr* instr) {
|
| + SetValue(instr, non_constant_);
|
| +}
|
| +
|
| +
|
| +void ConstantPropagator::VisitBinaryFloat64x2Op(BinaryFloat64x2OpInstr* instr) {
|
| + SetValue(instr, non_constant_);
|
| +}
|
| +
|
| +
|
| +void ConstantPropagator::VisitFloat32x4ToFloat64x2(
|
| + Float32x4ToFloat64x2Instr* instr) {
|
| + SetValue(instr, non_constant_);
|
| +}
|
| +
|
| +
|
| +void ConstantPropagator::VisitFloat64x2ToFloat32x4(
|
| + Float64x2ToFloat32x4Instr* instr) {
|
| + SetValue(instr, non_constant_);
|
| +}
|
| +
|
| +
|
| +void ConstantPropagator::VisitFloat64x2Zero(
|
| + Float64x2ZeroInstr* instr) {
|
| + SetValue(instr, non_constant_);
|
| +}
|
| +
|
| +
|
| +void ConstantPropagator::VisitFloat64x2Splat(
|
| + Float64x2SplatInstr* instr) {
|
| + SetValue(instr, non_constant_);
|
| +}
|
| +
|
| +
|
| +void ConstantPropagator::VisitFloat64x2Constructor(
|
| + Float64x2ConstructorInstr* instr) {
|
| + SetValue(instr, non_constant_);
|
| +}
|
| +
|
| +
|
| void ConstantPropagator::VisitMathUnary(MathUnaryInstr* instr) {
|
| const Object& value = instr->value()->definition()->constant_value();
|
| if (IsNonConstant(value)) {
|
|
|