| Index: runtime/vm/flow_graph_optimizer.cc
|
| diff --git a/runtime/vm/flow_graph_optimizer.cc b/runtime/vm/flow_graph_optimizer.cc
|
| index 0c87164d50cdb1757452f06e8ede26be4f110d52..64763e4d99b1b5adc6e3f06f3557004017295460 100644
|
| --- a/runtime/vm/flow_graph_optimizer.cc
|
| +++ b/runtime/vm/flow_graph_optimizer.cc
|
| @@ -345,7 +345,7 @@ void FlowGraphOptimizer::InsertConversion(Representation from,
|
| converted = new UnboxDoubleInstr(new Value(boxed), deopt_id);
|
|
|
| } else if ((from == kUnboxedDouble) && (to == kTagged)) {
|
| - converted = new BoxDoubleInstr(use->CopyWithType(), NULL);
|
| + converted = new BoxDoubleInstr(use->CopyWithType());
|
|
|
| } else if ((from == kTagged) && (to == kUnboxedDouble)) {
|
| ASSERT((deopt_target != NULL) ||
|
| @@ -363,6 +363,19 @@ void FlowGraphOptimizer::InsertConversion(Representation from,
|
| } else {
|
| converted = new UnboxDoubleInstr(use->CopyWithType(), deopt_id);
|
| }
|
| + } else if ((from == kTagged) && (to == kUnboxedFloat32x4)) {
|
| + ASSERT((deopt_target != NULL) ||
|
| + (use->Type()->ToCid() == kFloat32x4Cid));
|
| + const intptr_t deopt_id = (deopt_target != NULL) ?
|
| + deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId;
|
| + CheckNonSmiInstr* non_smi = new CheckNonSmiInstr(use->CopyWithType(),
|
| + deopt_id);
|
| + // Check that value is not a Smi.
|
| + InsertBefore(insert_before, non_smi, use->instruction()->env(),
|
| + Definition::kEffect);
|
| + converted = new UnboxFloat32x4Instr(use->CopyWithType(), deopt_id);
|
| + } else if ((from == kUnboxedFloat32x4) && (to == kTagged)) {
|
| + converted = new BoxFloat32x4Instr(use->CopyWithType());
|
| }
|
| ASSERT(converted != NULL);
|
| use->BindTo(converted);
|
| @@ -763,6 +776,15 @@ bool FlowGraphOptimizer::TryReplaceWithStoreIndexed(InstanceCallInstr* call) {
|
| }
|
| break;
|
| }
|
| + case kTypedDataFloat32x4ArrayCid: {
|
| + // Check that value is always a Float32x4.
|
| + value_check = call->ic_data()->AsUnaryClassChecksForArgNr(2);
|
| + if ((value_check.NumberOfChecks() != 1) ||
|
| + (value_check.GetReceiverClassIdAt(0) != kFloat32x4Cid)) {
|
| + return false;
|
| + }
|
| + }
|
| + break;
|
| default:
|
| // TODO(fschneider): Add support for other array types.
|
| return false;
|
| @@ -824,6 +846,13 @@ void FlowGraphOptimizer::BuildStoreIndexed(InstanceCallInstr* call,
|
| ASSERT(value_type.IsInstantiated());
|
| break;
|
| }
|
| + case kTypedDataFloat32x4ArrayCid: {
|
| + type_args = instantiator = flow_graph_->constant_null();
|
| + ASSERT((class_id != kTypedDataFloat32x4ArrayCid) ||
|
| + value_type.IsFloat32x4Type());
|
| + ASSERT(value_type.IsInstantiated());
|
| + break;
|
| + }
|
| default:
|
| // TODO(fschneider): Add support for other array types.
|
| UNREACHABLE();
|
| @@ -850,8 +879,8 @@ void FlowGraphOptimizer::BuildStoreIndexed(InstanceCallInstr* call,
|
| RawObject::IsExternalTypedDataClassId(array_cid)) ? kNoStoreBarrier
|
| : kEmitStoreBarrier;
|
| if (!value_check.IsNull()) {
|
| - // No store barrier needed because checked value is a smi, an unboxed mint
|
| - // or unboxed double.
|
| + // No store barrier needed because checked value is a smi, an unboxed mint,
|
| + // an unboxed double, an unboxed Float32x4, or unboxed Uint32x4.
|
| needs_store_barrier = kNoStoreBarrier;
|
| AddCheckClass(stored_value, value_check, call->deopt_id(), call->env(),
|
| call);
|
| @@ -880,6 +909,7 @@ bool FlowGraphOptimizer::TryReplaceWithLoadIndexed(InstanceCallInstr* call) {
|
| case kGrowableObjectArrayCid:
|
| case kTypedDataFloat32ArrayCid:
|
| case kTypedDataFloat64ArrayCid:
|
| + case kTypedDataFloat32x4ArrayCid:
|
| case kTypedDataInt8ArrayCid:
|
| case kTypedDataUint8ArrayCid:
|
| case kTypedDataUint8ClampedArrayCid:
|
| @@ -1470,6 +1500,7 @@ static bool IsSupportedByteArrayViewCid(intptr_t cid) {
|
| case kTypedDataUint32ArrayCid:
|
| case kTypedDataFloat32ArrayCid:
|
| case kTypedDataFloat64ArrayCid:
|
| + case kTypedDataFloat32x4ArrayCid:
|
| return true;
|
| default:
|
| return false;
|
| @@ -1603,6 +1634,9 @@ bool FlowGraphOptimizer::TryInlineInstanceMethod(InstanceCallInstr* call) {
|
| case MethodRecognizer::kByteArrayBaseGetFloat64:
|
| return BuildByteArrayViewLoad(
|
| call, class_ids[0], kTypedDataFloat64ArrayCid);
|
| + case MethodRecognizer::kByteArrayBaseGetFloat32x4:
|
| + return BuildByteArrayViewLoad(
|
| + call, class_ids[0], kTypedDataFloat32x4ArrayCid);
|
|
|
| // ByteArray setters.
|
| case MethodRecognizer::kByteArrayBaseSetInt8:
|
| @@ -1629,6 +1663,9 @@ bool FlowGraphOptimizer::TryInlineInstanceMethod(InstanceCallInstr* call) {
|
| case MethodRecognizer::kByteArrayBaseSetFloat64:
|
| return BuildByteArrayViewStore(
|
| call, class_ids[0], kTypedDataFloat64ArrayCid);
|
| + case MethodRecognizer::kByteArrayBaseSetFloat32x4:
|
| + return BuildByteArrayViewStore(
|
| + call, class_ids[0], kTypedDataFloat32x4ArrayCid);
|
| default:
|
| // Unsupported method.
|
| return false;
|
| @@ -1711,6 +1748,15 @@ bool FlowGraphOptimizer::BuildByteArrayViewStore(
|
| value_check.AddReceiverCheck(kDoubleCid, Function::Handle());
|
| break;
|
| }
|
| + case kTypedDataFloat32x4ArrayCid: {
|
| + // Check that value is always Float32x4.
|
| + value_check = ICData::New(Function::Handle(),
|
| + String::Handle(),
|
| + Isolate::kNoDeoptId,
|
| + 1);
|
| + value_check.AddReceiverCheck(kFloat32x4Cid, Function::Handle());
|
| + break;
|
| + }
|
| default:
|
| // Array cids are already checked in the caller.
|
| UNREACHABLE();
|
| @@ -3825,6 +3871,8 @@ void ConstantPropagator::VisitGuardField(GuardFieldInstr* instr) { }
|
|
|
| void ConstantPropagator::VisitCheckSmi(CheckSmiInstr* instr) { }
|
|
|
| +void ConstantPropagator::VisitCheckNonSmi(CheckNonSmiInstr* instr) { }
|
| +
|
|
|
| void ConstantPropagator::VisitCheckEitherNonSmi(
|
| CheckEitherNonSmiInstr* instr) { }
|
| @@ -4354,6 +4402,28 @@ void ConstantPropagator::VisitBoxDouble(BoxDoubleInstr* instr) {
|
| }
|
|
|
|
|
| +void ConstantPropagator::VisitUnboxFloat32x4(UnboxFloat32x4Instr* instr) {
|
| + const Object& value = instr->value()->definition()->constant_value();
|
| + if (IsNonConstant(value)) {
|
| + SetValue(instr, non_constant_);
|
| + } else if (IsConstant(value)) {
|
| + // TODO(kmillikin): Handle conversion.
|
| + SetValue(instr, non_constant_);
|
| + }
|
| +}
|
| +
|
| +
|
| +void ConstantPropagator::VisitBoxFloat32x4(BoxFloat32x4Instr* instr) {
|
| + const Object& value = instr->value()->definition()->constant_value();
|
| + if (IsNonConstant(value)) {
|
| + SetValue(instr, non_constant_);
|
| + } else if (IsConstant(value)) {
|
| + // TODO(kmillikin): Handle conversion.
|
| + SetValue(instr, non_constant_);
|
| + }
|
| +}
|
| +
|
| +
|
| void ConstantPropagator::Analyze() {
|
| GraphEntryInstr* entry = graph_->graph_entry();
|
| reachable_->Add(entry->preorder_number());
|
|
|