| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/flow_graph_optimizer.h" | 5 #include "vm/flow_graph_optimizer.h" |
| 6 | 6 |
| 7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
| 8 #include "vm/cha.h" | 8 #include "vm/cha.h" |
| 9 #include "vm/flow_graph_builder.h" | 9 #include "vm/flow_graph_builder.h" |
| 10 #include "vm/flow_graph_compiler.h" | 10 #include "vm/flow_graph_compiler.h" |
| (...skipping 513 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 524 && ic_data.HasReceiverClassId(kSmiCid) | 524 && ic_data.HasReceiverClassId(kSmiCid) |
| 525 && ic_data.HasReceiverClassId(kMintCid); | 525 && ic_data.HasReceiverClassId(kMintCid); |
| 526 } | 526 } |
| 527 | 527 |
| 528 | 528 |
| 529 static bool HasOnlyTwoSmis(const ICData& ic_data) { | 529 static bool HasOnlyTwoSmis(const ICData& ic_data) { |
| 530 return (ic_data.NumberOfChecks() == 1) && | 530 return (ic_data.NumberOfChecks() == 1) && |
| 531 ICDataHasReceiverArgumentClassIds(ic_data, kSmiCid, kSmiCid); | 531 ICDataHasReceiverArgumentClassIds(ic_data, kSmiCid, kSmiCid); |
| 532 } | 532 } |
| 533 | 533 |
| 534 static bool HasOnlyTwoFloat32x4s(const ICData& ic_data) { |
| 535 return (ic_data.NumberOfChecks() == 1) && |
| 536 ICDataHasReceiverArgumentClassIds(ic_data, kFloat32x4Cid, kFloat32x4Cid); |
| 537 } |
| 538 |
| 534 | 539 |
| 535 // Returns false if the ICData contains anything other than the 4 combinations | 540 // Returns false if the ICData contains anything other than the 4 combinations |
| 536 // of Mint and Smi for the receiver and argument classes. | 541 // of Mint and Smi for the receiver and argument classes. |
| 537 static bool HasTwoMintOrSmi(const ICData& ic_data) { | 542 static bool HasTwoMintOrSmi(const ICData& ic_data) { |
| 538 GrowableArray<intptr_t> class_ids(2); | 543 GrowableArray<intptr_t> class_ids(2); |
| 539 class_ids.Add(kSmiCid); | 544 class_ids.Add(kSmiCid); |
| 540 class_ids.Add(kMintCid); | 545 class_ids.Add(kMintCid); |
| 541 return ICDataHasOnlyReceiverArgumentClassIds(ic_data, class_ids, class_ids); | 546 return ICDataHasOnlyReceiverArgumentClassIds(ic_data, class_ids, class_ids); |
| 542 } | 547 } |
| 543 | 548 |
| (...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 958 ? kMintCid | 963 ? kMintCid |
| 959 : kSmiCid; | 964 : kSmiCid; |
| 960 } else if (HasTwoMintOrSmi(ic_data) && | 965 } else if (HasTwoMintOrSmi(ic_data) && |
| 961 FlowGraphCompiler::SupportsUnboxedMints()) { | 966 FlowGraphCompiler::SupportsUnboxedMints()) { |
| 962 // Don't generate mint code if the IC data is marked because of an | 967 // Don't generate mint code if the IC data is marked because of an |
| 963 // overflow. | 968 // overflow. |
| 964 if (ic_data.deopt_reason() == kDeoptBinaryMintOp) return false; | 969 if (ic_data.deopt_reason() == kDeoptBinaryMintOp) return false; |
| 965 operands_type = kMintCid; | 970 operands_type = kMintCid; |
| 966 } else if (ShouldSpecializeForDouble(ic_data)) { | 971 } else if (ShouldSpecializeForDouble(ic_data)) { |
| 967 operands_type = kDoubleCid; | 972 operands_type = kDoubleCid; |
| 973 } else if (HasOnlyTwoFloat32x4s(ic_data)) { |
| 974 operands_type = kFloat32x4Cid; |
| 968 } else { | 975 } else { |
| 969 return false; | 976 return false; |
| 970 } | 977 } |
| 971 break; | 978 break; |
| 972 case Token::kMUL: | 979 case Token::kMUL: |
| 973 if (HasOnlyTwoSmis(ic_data)) { | 980 if (HasOnlyTwoSmis(ic_data)) { |
| 974 // Don't generate smi code if the IC data is marked because of an | 981 // Don't generate smi code if the IC data is marked because of an |
| 975 // overflow. | 982 // overflow. |
| 976 // TODO(fschneider): Add unboxed mint multiplication. | 983 // TODO(fschneider): Add unboxed mint multiplication. |
| 977 if (ic_data.deopt_reason() == kDeoptBinarySmiOp) return false; | 984 if (ic_data.deopt_reason() == kDeoptBinarySmiOp) return false; |
| 978 operands_type = kSmiCid; | 985 operands_type = kSmiCid; |
| 979 } else if (ShouldSpecializeForDouble(ic_data)) { | 986 } else if (ShouldSpecializeForDouble(ic_data)) { |
| 980 operands_type = kDoubleCid; | 987 operands_type = kDoubleCid; |
| 988 } else if (HasOnlyTwoFloat32x4s(ic_data)) { |
| 989 operands_type = kFloat32x4Cid; |
| 981 } else { | 990 } else { |
| 982 return false; | 991 return false; |
| 983 } | 992 } |
| 984 break; | 993 break; |
| 985 case Token::kDIV: | 994 case Token::kDIV: |
| 986 if (ShouldSpecializeForDouble(ic_data)) { | 995 if (ShouldSpecializeForDouble(ic_data)) { |
| 987 operands_type = kDoubleCid; | 996 operands_type = kDoubleCid; |
| 997 } else if (HasOnlyTwoFloat32x4s(ic_data)) { |
| 998 operands_type = kFloat32x4Cid; |
| 988 } else { | 999 } else { |
| 989 return false; | 1000 return false; |
| 990 } | 1001 } |
| 991 break; | 1002 break; |
| 992 case Token::kMOD: | 1003 case Token::kMOD: |
| 993 if (HasOnlyTwoSmis(ic_data)) { | 1004 if (HasOnlyTwoSmis(ic_data)) { |
| 994 operands_type = kSmiCid; | 1005 operands_type = kSmiCid; |
| 995 } else { | 1006 } else { |
| 996 return false; | 1007 return false; |
| 997 } | 1008 } |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1064 ShiftMintOpInstr* shift_op = | 1075 ShiftMintOpInstr* shift_op = |
| 1065 new ShiftMintOpInstr(op_kind, new Value(left), new Value(right), | 1076 new ShiftMintOpInstr(op_kind, new Value(left), new Value(right), |
| 1066 call); | 1077 call); |
| 1067 ReplaceCall(call, shift_op); | 1078 ReplaceCall(call, shift_op); |
| 1068 } else { | 1079 } else { |
| 1069 BinaryMintOpInstr* bin_op = | 1080 BinaryMintOpInstr* bin_op = |
| 1070 new BinaryMintOpInstr(op_kind, new Value(left), new Value(right), | 1081 new BinaryMintOpInstr(op_kind, new Value(left), new Value(right), |
| 1071 call); | 1082 call); |
| 1072 ReplaceCall(call, bin_op); | 1083 ReplaceCall(call, bin_op); |
| 1073 } | 1084 } |
| 1085 } else if (operands_type == kFloat32x4Cid) { |
| 1086 // Type check left. |
| 1087 AddCheckClass(left, |
| 1088 ICData::ZoneHandle( |
| 1089 call->ic_data()->AsUnaryClassChecksForArgNr(0)), |
| 1090 call->deopt_id(), |
| 1091 call->env(), |
| 1092 call); |
| 1093 // Type check right. |
| 1094 AddCheckClass(right, |
| 1095 ICData::ZoneHandle( |
| 1096 call->ic_data()->AsUnaryClassChecksForArgNr(1)), |
| 1097 call->deopt_id(), |
| 1098 call->env(), |
| 1099 call); |
| 1100 // Replace call. |
| 1101 BinaryFloat32x4OpInstr* float32x4_bin_op = |
| 1102 new BinaryFloat32x4OpInstr(op_kind, new Value(left), new Value(right), |
| 1103 call); |
| 1104 ReplaceCall(call, float32x4_bin_op); |
| 1074 } else if (op_kind == Token::kMOD) { | 1105 } else if (op_kind == Token::kMOD) { |
| 1075 // TODO(vegorov): implement fast path code for modulo. | 1106 // TODO(vegorov): implement fast path code for modulo. |
| 1076 ASSERT(operands_type == kSmiCid); | 1107 ASSERT(operands_type == kSmiCid); |
| 1077 if (!right->IsConstant()) return false; | 1108 if (!right->IsConstant()) return false; |
| 1078 const Object& obj = right->AsConstant()->value(); | 1109 const Object& obj = right->AsConstant()->value(); |
| 1079 if (!obj.IsSmi()) return false; | 1110 if (!obj.IsSmi()) return false; |
| 1080 const intptr_t value = Smi::Cast(obj).Value(); | 1111 const intptr_t value = Smi::Cast(obj).Value(); |
| 1081 if ((value <= 0) || !Utils::IsPowerOfTwo(value)) return false; | 1112 if ((value <= 0) || !Utils::IsPowerOfTwo(value)) return false; |
| 1082 | 1113 |
| 1083 // Insert smi check and attach a copy of the original environment | 1114 // Insert smi check and attach a copy of the original environment |
| (...skipping 3308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4392 const Object& right = instr->right()->definition()->constant_value(); | 4423 const Object& right = instr->right()->definition()->constant_value(); |
| 4393 if (IsNonConstant(left) || IsNonConstant(right)) { | 4424 if (IsNonConstant(left) || IsNonConstant(right)) { |
| 4394 SetValue(instr, non_constant_); | 4425 SetValue(instr, non_constant_); |
| 4395 } else if (IsConstant(left) && IsConstant(right)) { | 4426 } else if (IsConstant(left) && IsConstant(right)) { |
| 4396 // TODO(kmillikin): Handle binary operation. | 4427 // TODO(kmillikin): Handle binary operation. |
| 4397 SetValue(instr, non_constant_); | 4428 SetValue(instr, non_constant_); |
| 4398 } | 4429 } |
| 4399 } | 4430 } |
| 4400 | 4431 |
| 4401 | 4432 |
| 4433 void ConstantPropagator::VisitBinaryFloat32x4Op( |
| 4434 BinaryFloat32x4OpInstr* instr) { |
| 4435 const Object& left = instr->left()->definition()->constant_value(); |
| 4436 const Object& right = instr->right()->definition()->constant_value(); |
| 4437 if (IsNonConstant(left) || IsNonConstant(right)) { |
| 4438 SetValue(instr, non_constant_); |
| 4439 } else if (IsConstant(left) && IsConstant(right)) { |
| 4440 // TODO(kmillikin): Handle binary operation. |
| 4441 SetValue(instr, non_constant_); |
| 4442 } |
| 4443 } |
| 4444 |
| 4445 |
| 4402 void ConstantPropagator::VisitMathSqrt(MathSqrtInstr* instr) { | 4446 void ConstantPropagator::VisitMathSqrt(MathSqrtInstr* instr) { |
| 4403 const Object& value = instr->value()->definition()->constant_value(); | 4447 const Object& value = instr->value()->definition()->constant_value(); |
| 4404 if (IsNonConstant(value)) { | 4448 if (IsNonConstant(value)) { |
| 4405 SetValue(instr, non_constant_); | 4449 SetValue(instr, non_constant_); |
| 4406 } else if (IsConstant(value)) { | 4450 } else if (IsConstant(value)) { |
| 4407 // TODO(kmillikin): Handle sqrt. | 4451 // TODO(kmillikin): Handle sqrt. |
| 4408 SetValue(instr, non_constant_); | 4452 SetValue(instr, non_constant_); |
| 4409 } | 4453 } |
| 4410 } | 4454 } |
| 4411 | 4455 |
| (...skipping 604 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5016 if (changed) { | 5060 if (changed) { |
| 5017 // We may have changed the block order and the dominator tree. | 5061 // We may have changed the block order and the dominator tree. |
| 5018 flow_graph->DiscoverBlocks(); | 5062 flow_graph->DiscoverBlocks(); |
| 5019 GrowableArray<BitVector*> dominance_frontier; | 5063 GrowableArray<BitVector*> dominance_frontier; |
| 5020 flow_graph->ComputeDominators(&dominance_frontier); | 5064 flow_graph->ComputeDominators(&dominance_frontier); |
| 5021 } | 5065 } |
| 5022 } | 5066 } |
| 5023 | 5067 |
| 5024 | 5068 |
| 5025 } // namespace dart | 5069 } // namespace dart |
| OLD | NEW |