| Index: runtime/vm/flow_graph_optimizer.cc
|
| ===================================================================
|
| --- runtime/vm/flow_graph_optimizer.cc (revision 36258)
|
| +++ runtime/vm/flow_graph_optimizer.cc (working copy)
|
| @@ -56,6 +56,11 @@
|
| }
|
|
|
|
|
| +static bool CanUnboxDouble() {
|
| + return FlowGraphCompiler::SupportsUnboxedDoubles();
|
| +}
|
| +
|
| +
|
| // Optimize instance calls using ICData.
|
| void FlowGraphOptimizer::ApplyICData() {
|
| VisitBlocks();
|
| @@ -413,7 +418,7 @@
|
| // Tries to merge MathUnary operations, in this case sinus and cosinus.
|
| void FlowGraphOptimizer::TryMergeMathUnary(
|
| GrowableArray<MathUnaryInstr*>* merge_candidates) {
|
| - if (!FlowGraphCompiler::SupportsSinCos()) {
|
| + if (!FlowGraphCompiler::SupportsSinCos() || !CanUnboxDouble()) {
|
| return;
|
| }
|
| if (merge_candidates->length() < 2) {
|
| @@ -606,6 +611,7 @@
|
| converted = new BoxIntegerInstr(use->CopyWithType());
|
|
|
| } else if (from == kUnboxedMint && to == kUnboxedDouble) {
|
| + ASSERT(CanUnboxDouble());
|
| // Convert by boxing/unboxing.
|
| // TODO(fschneider): Implement direct unboxed mint-to-double conversion.
|
| BoxIntegerInstr* boxed = new BoxIntegerInstr(use->CopyWithType());
|
| @@ -617,9 +623,11 @@
|
| converted = new UnboxDoubleInstr(new Value(boxed), deopt_id);
|
|
|
| } else if ((from == kUnboxedDouble) && (to == kTagged)) {
|
| + ASSERT(CanUnboxDouble());
|
| converted = new BoxDoubleInstr(use->CopyWithType());
|
|
|
| } else if ((from == kTagged) && (to == kUnboxedDouble)) {
|
| + ASSERT(CanUnboxDouble());
|
| ASSERT((deopt_target != NULL) ||
|
| (use->Type()->ToCid() == kDoubleCid));
|
| const intptr_t deopt_id = (deopt_target != NULL) ?
|
| @@ -757,7 +765,9 @@
|
|
|
| switch (phi->Type()->ToCid()) {
|
| case kDoubleCid:
|
| - unboxed = kUnboxedDouble;
|
| + if (CanUnboxDouble()) {
|
| + unboxed = kUnboxedDouble;
|
| + }
|
| break;
|
| case kFloat32x4Cid:
|
| if (ShouldInlineSimd()) {
|
| @@ -934,6 +944,11 @@
|
|
|
|
|
| static bool ShouldSpecializeForDouble(const ICData& ic_data) {
|
| + // Don't specialize for double if we can't unbox them.
|
| + if (!CanUnboxDouble()) {
|
| + return false;
|
| + }
|
| +
|
| // Unboxed double operation can't handle case of two smis.
|
| if (ICDataHasReceiverArgumentClassIds(ic_data, kSmiCid, kSmiCid)) {
|
| return false;
|
| @@ -1318,8 +1333,6 @@
|
| case MethodRecognizer::kImmutableArrayGetIndexed:
|
| case MethodRecognizer::kObjectArrayGetIndexed:
|
| case MethodRecognizer::kGrowableArrayGetIndexed:
|
| - case MethodRecognizer::kFloat32ArrayGetIndexed:
|
| - case MethodRecognizer::kFloat64ArrayGetIndexed:
|
| case MethodRecognizer::kInt8ArrayGetIndexed:
|
| case MethodRecognizer::kUint8ArrayGetIndexed:
|
| case MethodRecognizer::kUint8ClampedArrayGetIndexed:
|
| @@ -1328,6 +1341,12 @@
|
| case MethodRecognizer::kInt16ArrayGetIndexed:
|
| case MethodRecognizer::kUint16ArrayGetIndexed:
|
| return InlineGetIndexed(kind, call, receiver, ic_data, entry, last);
|
| + case MethodRecognizer::kFloat32ArrayGetIndexed:
|
| + case MethodRecognizer::kFloat64ArrayGetIndexed:
|
| + if (!CanUnboxDouble()) {
|
| + return false;
|
| + }
|
| + return InlineGetIndexed(kind, call, receiver, ic_data, entry, last);
|
| case MethodRecognizer::kFloat32x4ArrayGetIndexed:
|
| case MethodRecognizer::kFloat64x2ArrayGetIndexed:
|
| if (!ShouldInlineSimd()) {
|
| @@ -1379,6 +1398,9 @@
|
| &ic_data, value_check, entry, last);
|
| case MethodRecognizer::kFloat32ArraySetIndexed:
|
| case MethodRecognizer::kFloat64ArraySetIndexed:
|
| + if (!CanUnboxDouble()) {
|
| + return false;
|
| + }
|
| // Check that value is always double.
|
| if (!ArgIsAlways(kDoubleCid, ic_data, 2)) {
|
| return false;
|
| @@ -1439,10 +1461,16 @@
|
| kTypedDataUint32ArrayCid,
|
| ic_data, entry, last);
|
| case MethodRecognizer::kByteArrayBaseGetFloat32:
|
| + if (!CanUnboxDouble()) {
|
| + return false;
|
| + }
|
| return InlineByteArrayViewLoad(call, receiver, receiver_cid,
|
| kTypedDataFloat32ArrayCid,
|
| ic_data, entry, last);
|
| case MethodRecognizer::kByteArrayBaseGetFloat64:
|
| + if (!CanUnboxDouble()) {
|
| + return false;
|
| + }
|
| return InlineByteArrayViewLoad(call, receiver, receiver_cid,
|
| kTypedDataFloat64ArrayCid,
|
| ic_data, entry, last);
|
| @@ -1491,10 +1519,16 @@
|
| kTypedDataUint32ArrayCid,
|
| ic_data, entry, last);
|
| case MethodRecognizer::kByteArrayBaseSetFloat32:
|
| + if (!CanUnboxDouble()) {
|
| + return false;
|
| + }
|
| return InlineByteArrayViewStore(target, call, receiver, receiver_cid,
|
| kTypedDataFloat32ArrayCid,
|
| ic_data, entry, last);
|
| case MethodRecognizer::kByteArrayBaseSetFloat64:
|
| + if (!CanUnboxDouble()) {
|
| + return false;
|
| + }
|
| return InlineByteArrayViewStore(target, call, receiver, receiver_cid,
|
| kTypedDataFloat64ArrayCid,
|
| ic_data, entry, last);
|
| @@ -1827,7 +1861,7 @@
|
| } else if (HasTwoMintOrSmi(ic_data) &&
|
| FlowGraphCompiler::SupportsUnboxedMints()) {
|
| cid = kMintCid;
|
| - } else if (HasTwoDoubleOrSmi(ic_data)) {
|
| + } else if (HasTwoDoubleOrSmi(ic_data) && CanUnboxDouble()) {
|
| // Use double comparison.
|
| if (SmiFitsInDouble()) {
|
| cid = kDoubleCid;
|
| @@ -1929,7 +1963,7 @@
|
| } else if (HasTwoMintOrSmi(ic_data) &&
|
| FlowGraphCompiler::SupportsUnboxedMints()) {
|
| cid = kMintCid;
|
| - } else if (HasTwoDoubleOrSmi(ic_data)) {
|
| + } else if (HasTwoDoubleOrSmi(ic_data) && CanUnboxDouble()) {
|
| // Use double comparison.
|
| if (SmiFitsInDouble()) {
|
| cid = kDoubleCid;
|
| @@ -2082,6 +2116,9 @@
|
| Definition* left = call->ArgumentAt(0);
|
| Definition* right = call->ArgumentAt(1);
|
| if (operands_type == kDoubleCid) {
|
| + if (!CanUnboxDouble()) {
|
| + return false;
|
| + }
|
| // Check that either left or right are not a smi. Result of a
|
| // binary operation with two smis is a smi not a double, except '/' which
|
| // returns a double for two smis.
|
| @@ -2192,7 +2229,8 @@
|
| unary_op = new UnaryMintOpInstr(
|
| op_kind, new Value(input), call->deopt_id());
|
| } else if (HasOnlyOneDouble(*call->ic_data()) &&
|
| - (op_kind == Token::kNEGATE)) {
|
| + (op_kind == Token::kNEGATE) &&
|
| + CanUnboxDouble()) {
|
| AddReceiverCheck(call);
|
| unary_op = new UnaryDoubleOpInstr(
|
| Token::kNEGATE, new Value(input), call->deopt_id());
|
| @@ -2394,6 +2432,9 @@
|
|
|
| bool FlowGraphOptimizer::InlineFloat64x2Getter(InstanceCallInstr* call,
|
| MethodRecognizer::Kind getter) {
|
| + if (!ShouldInlineSimd()) {
|
| + return false;
|
| + }
|
| AddCheckClass(call->ArgumentAt(0),
|
| ICData::ZoneHandle(
|
| call->ic_data()->AsUnaryClassChecksForArgNr(0)),
|
| @@ -2866,7 +2907,8 @@
|
| return false;
|
| }
|
|
|
| - if ((recognized_kind == MethodRecognizer::kIntegerToDouble) &&
|
| + if (CanUnboxDouble() &&
|
| + (recognized_kind == MethodRecognizer::kIntegerToDouble) &&
|
| (ic_data.NumberOfChecks() == 1) &&
|
| (class_ids[0] == kSmiCid)) {
|
| AddReceiverCheck(call);
|
| @@ -2877,6 +2919,9 @@
|
| }
|
|
|
| if (class_ids[0] == kDoubleCid) {
|
| + if (!CanUnboxDouble()) {
|
| + return false;
|
| + }
|
| switch (recognized_kind) {
|
| case MethodRecognizer::kDoubleToInteger: {
|
| AddReceiverCheck(call);
|
| @@ -2925,9 +2970,20 @@
|
| (recognized_kind == MethodRecognizer::kByteArrayBaseGetUint32) ||
|
| (recognized_kind == MethodRecognizer::kByteArrayBaseSetInt32) ||
|
| (recognized_kind == MethodRecognizer::kByteArrayBaseSetUint32)) {
|
| - if (!CanUnboxInt32()) return false;
|
| + if (!CanUnboxInt32()) {
|
| + return false;
|
| + }
|
| }
|
|
|
| + if ((recognized_kind == MethodRecognizer::kByteArrayBaseGetFloat32) ||
|
| + (recognized_kind == MethodRecognizer::kByteArrayBaseGetFloat64) ||
|
| + (recognized_kind == MethodRecognizer::kByteArrayBaseSetFloat32) ||
|
| + (recognized_kind == MethodRecognizer::kByteArrayBaseSetFloat64)) {
|
| + if (!CanUnboxDouble()) {
|
| + return false;
|
| + }
|
| + }
|
| +
|
| switch (recognized_kind) {
|
| // ByteArray getters.
|
| case MethodRecognizer::kByteArrayBaseGetInt8:
|
| @@ -3709,8 +3765,13 @@
|
|
|
| bool FlowGraphOptimizer::BuildByteArrayViewLoad(InstanceCallInstr* call,
|
| intptr_t view_cid) {
|
| - bool simd_view = (view_cid == kTypedDataFloat32x4ArrayCid) ||
|
| - (view_cid == kTypedDataInt32x4ArrayCid);
|
| + const bool simd_view = (view_cid == kTypedDataFloat32x4ArrayCid) ||
|
| + (view_cid == kTypedDataInt32x4ArrayCid);
|
| + const bool float_view = (view_cid == kTypedDataFloat32ArrayCid) ||
|
| + (view_cid == kTypedDataFloat64ArrayCid);
|
| + if (float_view && !CanUnboxDouble()) {
|
| + return false;
|
| + }
|
| if (simd_view && !ShouldInlineSimd()) {
|
| return false;
|
| }
|
| @@ -3720,8 +3781,13 @@
|
|
|
| bool FlowGraphOptimizer::BuildByteArrayViewStore(InstanceCallInstr* call,
|
| intptr_t view_cid) {
|
| - bool simd_view = (view_cid == kTypedDataFloat32x4ArrayCid) ||
|
| - (view_cid == kTypedDataInt32x4ArrayCid);
|
| + const bool simd_view = (view_cid == kTypedDataFloat32x4ArrayCid) ||
|
| + (view_cid == kTypedDataInt32x4ArrayCid);
|
| + const bool float_view = (view_cid == kTypedDataFloat32ArrayCid) ||
|
| + (view_cid == kTypedDataFloat64ArrayCid);
|
| + if (float_view && !CanUnboxDouble()) {
|
| + return false;
|
| + }
|
| if (simd_view && !ShouldInlineSimd()) {
|
| return false;
|
| }
|
| @@ -4133,6 +4199,9 @@
|
|
|
|
|
| void FlowGraphOptimizer::VisitStaticCall(StaticCallInstr* call) {
|
| + if (!CanUnboxDouble()) {
|
| + return;
|
| + }
|
| MethodRecognizer::Kind recognized_kind =
|
| MethodRecognizer::RecognizeKind(call->function());
|
| MathUnaryInstr::MathUnaryKind unary_kind;
|
| @@ -8095,13 +8164,14 @@
|
| intptr_t value_cid = instr->value()->Type()->ToCid();
|
| Representation rep = def->representation();
|
| if ((checked_type.IsFloat32x4Type() && (rep == kUnboxedFloat32x4)) ||
|
| - (checked_type.IsInt32x4Type() && (rep == kUnboxedInt32x4)) ||
|
| - (checked_type.IsDoubleType() && (rep == kUnboxedDouble)) ||
|
| + (checked_type.IsInt32x4Type() && (rep == kUnboxedInt32x4)) ||
|
| + (checked_type.IsDoubleType() && (rep == kUnboxedDouble) &&
|
| + CanUnboxDouble()) ||
|
| (checked_type.IsIntType() && (rep == kUnboxedMint))) {
|
| // Ensure that compile time type matches representation.
|
| ASSERT(((rep == kUnboxedFloat32x4) && (value_cid == kFloat32x4Cid)) ||
|
| - ((rep == kUnboxedInt32x4) && (value_cid == kInt32x4Cid)) ||
|
| - ((rep == kUnboxedDouble) && (value_cid == kDoubleCid)) ||
|
| + ((rep == kUnboxedInt32x4) && (value_cid == kInt32x4Cid)) ||
|
| + ((rep == kUnboxedDouble) && (value_cid == kDoubleCid)) ||
|
| ((rep == kUnboxedMint) && (value_cid == kMintCid)));
|
| // The representation guarantees the type check to be true.
|
| SetValue(instr, instr->negate_result() ? Bool::False() : Bool::True());
|
|
|