| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/compiler/simplified-lowering.h" | 5 #include "src/compiler/simplified-lowering.h" |
| 6 | 6 |
| 7 #include <limits> | 7 #include <limits> |
| 8 | 8 |
| 9 #include "src/address-map.h" | 9 #include "src/address-map.h" |
| 10 #include "src/base/bits.h" | 10 #include "src/base/bits.h" |
| (...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 234 | 234 |
| 235 MachineRepresentation representation() const { return representation_; } | 235 MachineRepresentation representation() const { return representation_; } |
| 236 | 236 |
| 237 // Helpers for feedback typing. | 237 // Helpers for feedback typing. |
| 238 void set_feedback_type(Type* type) { feedback_type_ = type; } | 238 void set_feedback_type(Type* type) { feedback_type_ = type; } |
| 239 Type* feedback_type() const { return feedback_type_; } | 239 Type* feedback_type() const { return feedback_type_; } |
| 240 void set_weakened() { weakened_ = true; } | 240 void set_weakened() { weakened_ = true; } |
| 241 bool weakened() const { return weakened_; } | 241 bool weakened() const { return weakened_; } |
| 242 void set_restriction_type(Type* type) { restriction_type_ = type; } | 242 void set_restriction_type(Type* type) { restriction_type_ = type; } |
| 243 Type* restriction_type() const { return restriction_type_; } | 243 Type* restriction_type() const { return restriction_type_; } |
| 244 void set_unrestricted_feedback_type(Type* type) { | |
| 245 unrestricted_feedback_type_ = type; | |
| 246 } | |
| 247 Type* unrestricted_feedback_type() const { | |
| 248 return unrestricted_feedback_type_; | |
| 249 } | |
| 250 | 244 |
| 251 private: | 245 private: |
| 252 enum State : uint8_t { kUnvisited, kPushed, kVisited, kQueued }; | 246 enum State : uint8_t { kUnvisited, kPushed, kVisited, kQueued }; |
| 253 State state_ = kUnvisited; | 247 State state_ = kUnvisited; |
| 254 MachineRepresentation representation_ = | 248 MachineRepresentation representation_ = |
| 255 MachineRepresentation::kNone; // Output representation. | 249 MachineRepresentation::kNone; // Output representation. |
| 256 Truncation truncation_ = Truncation::None(); // Information about uses. | 250 Truncation truncation_ = Truncation::None(); // Information about uses. |
| 257 | 251 |
| 258 Type* restriction_type_ = Type::Any(); | 252 Type* restriction_type_ = Type::Any(); |
| 259 Type* feedback_type_ = nullptr; | 253 Type* feedback_type_ = nullptr; |
| 260 Type* unrestricted_feedback_type_ = nullptr; | |
| 261 bool weakened_ = false; | 254 bool weakened_ = false; |
| 262 }; | 255 }; |
| 263 | 256 |
| 264 RepresentationSelector(JSGraph* jsgraph, Zone* zone, | 257 RepresentationSelector(JSGraph* jsgraph, Zone* zone, |
| 265 RepresentationChanger* changer, | 258 RepresentationChanger* changer, |
| 266 SourcePositionTable* source_positions) | 259 SourcePositionTable* source_positions) |
| 267 : jsgraph_(jsgraph), | 260 : jsgraph_(jsgraph), |
| 268 zone_(zone), | 261 zone_(zone), |
| 269 count_(jsgraph->graph()->NodeCount()), | 262 count_(jsgraph->graph()->NodeCount()), |
| 270 info_(count_, zone), | 263 info_(count_, zone), |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 364 Type* TypeOf(Node* node) { | 357 Type* TypeOf(Node* node) { |
| 365 Type* type = GetInfo(node)->feedback_type(); | 358 Type* type = GetInfo(node)->feedback_type(); |
| 366 return type == nullptr ? NodeProperties::GetType(node) : type; | 359 return type == nullptr ? NodeProperties::GetType(node) : type; |
| 367 } | 360 } |
| 368 | 361 |
| 369 Type* FeedbackTypeOf(Node* node) { | 362 Type* FeedbackTypeOf(Node* node) { |
| 370 Type* type = GetInfo(node)->feedback_type(); | 363 Type* type = GetInfo(node)->feedback_type(); |
| 371 return type == nullptr ? Type::None() : type; | 364 return type == nullptr ? Type::None() : type; |
| 372 } | 365 } |
| 373 | 366 |
| 374 Type* UnrestrictedFeedbackTypeOf(Node* node) { | |
| 375 Type* type = GetInfo(node)->unrestricted_feedback_type(); | |
| 376 return type == nullptr ? NodeProperties::GetType(node) : type; | |
| 377 } | |
| 378 | |
| 379 Type* TypePhi(Node* node) { | 367 Type* TypePhi(Node* node) { |
| 380 int arity = node->op()->ValueInputCount(); | 368 int arity = node->op()->ValueInputCount(); |
| 381 Type* type = FeedbackTypeOf(node->InputAt(0)); | 369 Type* type = FeedbackTypeOf(node->InputAt(0)); |
| 382 for (int i = 1; i < arity; ++i) { | 370 for (int i = 1; i < arity; ++i) { |
| 383 type = op_typer_.Merge(type, FeedbackTypeOf(node->InputAt(i))); | 371 type = op_typer_.Merge(type, FeedbackTypeOf(node->InputAt(i))); |
| 384 } | 372 } |
| 385 return type; | 373 return type; |
| 386 } | 374 } |
| 387 | 375 |
| 388 Type* TypeSelect(Node* node) { | 376 Type* TypeSelect(Node* node) { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 411 switch (node->opcode()) { | 399 switch (node->opcode()) { |
| 412 #define DECLARE_CASE(Name) \ | 400 #define DECLARE_CASE(Name) \ |
| 413 case IrOpcode::k##Name: { \ | 401 case IrOpcode::k##Name: { \ |
| 414 new_type = op_typer_.Name(FeedbackTypeOf(node->InputAt(0)), \ | 402 new_type = op_typer_.Name(FeedbackTypeOf(node->InputAt(0)), \ |
| 415 FeedbackTypeOf(node->InputAt(1))); \ | 403 FeedbackTypeOf(node->InputAt(1))); \ |
| 416 break; \ | 404 break; \ |
| 417 } | 405 } |
| 418 SIMPLIFIED_NUMBER_BINOP_LIST(DECLARE_CASE) | 406 SIMPLIFIED_NUMBER_BINOP_LIST(DECLARE_CASE) |
| 419 #undef DECLARE_CASE | 407 #undef DECLARE_CASE |
| 420 | 408 |
| 421 #define DECLARE_CASE(Name) \ | 409 #define DECLARE_CASE(Name) \ |
| 422 case IrOpcode::k##Name: { \ | 410 case IrOpcode::k##Name: { \ |
| 423 new_type = op_typer_.Name(FeedbackTypeOf(node->InputAt(0)), \ | 411 new_type = \ |
| 424 FeedbackTypeOf(node->InputAt(1))); \ | 412 Type::Intersect(op_typer_.Name(FeedbackTypeOf(node->InputAt(0)), \ |
| 425 break; \ | 413 FeedbackTypeOf(node->InputAt(1))), \ |
| 414 info->restriction_type(), graph_zone()); \ |
| 415 break; \ |
| 426 } | 416 } |
| 427 SIMPLIFIED_SPECULATIVE_NUMBER_BINOP_LIST(DECLARE_CASE) | 417 SIMPLIFIED_SPECULATIVE_NUMBER_BINOP_LIST(DECLARE_CASE) |
| 428 #undef DECLARE_CASE | 418 #undef DECLARE_CASE |
| 429 | 419 |
| 430 #define DECLARE_CASE(Name) \ | 420 #define DECLARE_CASE(Name) \ |
| 431 case IrOpcode::k##Name: { \ | 421 case IrOpcode::k##Name: { \ |
| 432 new_type = op_typer_.Name(FeedbackTypeOf(node->InputAt(0))); \ | 422 new_type = op_typer_.Name(FeedbackTypeOf(node->InputAt(0))); \ |
| 433 break; \ | 423 break; \ |
| 434 } | 424 } |
| 435 SIMPLIFIED_NUMBER_UNOP_LIST(DECLARE_CASE) | 425 SIMPLIFIED_NUMBER_UNOP_LIST(DECLARE_CASE) |
| (...skipping 18 matching lines...) Expand all Loading... |
| 454 } | 444 } |
| 455 | 445 |
| 456 case IrOpcode::kSelect: { | 446 case IrOpcode::kSelect: { |
| 457 new_type = TypeSelect(node); | 447 new_type = TypeSelect(node); |
| 458 break; | 448 break; |
| 459 } | 449 } |
| 460 | 450 |
| 461 default: | 451 default: |
| 462 // Shortcut for operations that we do not handle. | 452 // Shortcut for operations that we do not handle. |
| 463 if (type == nullptr) { | 453 if (type == nullptr) { |
| 464 type = GetUpperBound(node); | 454 GetInfo(node)->set_feedback_type(NodeProperties::GetType(node)); |
| 465 info->set_unrestricted_feedback_type(type); | |
| 466 info->set_feedback_type( | |
| 467 Type::Intersect(type, info->restriction_type(), graph_zone())); | |
| 468 return true; | 455 return true; |
| 469 } | 456 } |
| 470 return false; | 457 return false; |
| 471 } | 458 } |
| 472 Type* unrestricted_feedback_type = new_type; | |
| 473 new_type = | |
| 474 Type::Intersect(new_type, info->restriction_type(), graph_zone()); | |
| 475 // We need to guarantee that the feedback type is a subtype of the upper | 459 // We need to guarantee that the feedback type is a subtype of the upper |
| 476 // bound. Naively that should hold, but weakening can actually produce | 460 // bound. Naively that should hold, but weakening can actually produce |
| 477 // a bigger type if we are unlucky with ordering of phi typing. To be | 461 // a bigger type if we are unlucky with ordering of phi typing. To be |
| 478 // really sure, just intersect the upper bound with the feedback type. | 462 // really sure, just intersect the upper bound with the feedback type. |
| 479 new_type = Type::Intersect(GetUpperBound(node), new_type, graph_zone()); | 463 new_type = Type::Intersect(GetUpperBound(node), new_type, graph_zone()); |
| 480 | 464 |
| 481 if (type != nullptr && new_type->Is(type)) return false; | 465 if (type != nullptr && new_type->Is(type)) return false; |
| 482 info->set_unrestricted_feedback_type(unrestricted_feedback_type); | 466 GetInfo(node)->set_feedback_type(new_type); |
| 483 info->set_feedback_type(new_type); | |
| 484 if (FLAG_trace_representation) { | 467 if (FLAG_trace_representation) { |
| 485 PrintNodeFeedbackType(node); | 468 PrintNodeFeedbackType(node); |
| 486 } | 469 } |
| 487 return true; | 470 return true; |
| 488 } | 471 } |
| 489 | 472 |
| 490 void PrintNodeFeedbackType(Node* n) { | 473 void PrintNodeFeedbackType(Node* n) { |
| 491 OFStream os(stdout); | 474 OFStream os(stdout); |
| 492 os << "#" << n->id() << ":" << *n->op() << "("; | 475 os << "#" << n->id() << ":" << *n->op() << "("; |
| 493 int j = 0; | 476 int j = 0; |
| (...skipping 616 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1110 return WriteBarrierKindFor(base_taggedness, field_representation, | 1093 return WriteBarrierKindFor(base_taggedness, field_representation, |
| 1111 field_type, value_representation, value); | 1094 field_type, value_representation, value); |
| 1112 } | 1095 } |
| 1113 | 1096 |
| 1114 Graph* graph() const { return jsgraph_->graph(); } | 1097 Graph* graph() const { return jsgraph_->graph(); } |
| 1115 CommonOperatorBuilder* common() const { return jsgraph_->common(); } | 1098 CommonOperatorBuilder* common() const { return jsgraph_->common(); } |
| 1116 SimplifiedOperatorBuilder* simplified() const { | 1099 SimplifiedOperatorBuilder* simplified() const { |
| 1117 return jsgraph_->simplified(); | 1100 return jsgraph_->simplified(); |
| 1118 } | 1101 } |
| 1119 | 1102 |
| 1103 void LowerToCheckedInt32Mul(Node* node, Truncation truncation, |
| 1104 Type* input0_type, Type* input1_type) { |
| 1105 // If one of the inputs is positive and/or truncation is being applied, |
| 1106 // there is no need to return -0. |
| 1107 CheckForMinusZeroMode mz_mode = |
| 1108 truncation.IsUsedAsWord32() || |
| 1109 (input0_type->Is(Type::OrderedNumber()) && |
| 1110 input0_type->Min() > 0) || |
| 1111 (input1_type->Is(Type::OrderedNumber()) && |
| 1112 input1_type->Min() > 0) |
| 1113 ? CheckForMinusZeroMode::kDontCheckForMinusZero |
| 1114 : CheckForMinusZeroMode::kCheckForMinusZero; |
| 1115 |
| 1116 NodeProperties::ChangeOp(node, simplified()->CheckedInt32Mul(mz_mode)); |
| 1117 } |
| 1118 |
| 1120 void ChangeToInt32OverflowOp(Node* node) { | 1119 void ChangeToInt32OverflowOp(Node* node) { |
| 1121 NodeProperties::ChangeOp(node, Int32OverflowOp(node)); | 1120 NodeProperties::ChangeOp(node, Int32OverflowOp(node)); |
| 1122 } | 1121 } |
| 1123 | 1122 |
| 1124 void ChangeToUint32OverflowOp(Node* node) { | 1123 void ChangeToUint32OverflowOp(Node* node) { |
| 1125 NodeProperties::ChangeOp(node, Uint32OverflowOp(node)); | 1124 NodeProperties::ChangeOp(node, Uint32OverflowOp(node)); |
| 1126 } | 1125 } |
| 1127 | 1126 |
| 1128 void VisitSpeculativeAdditiveOp(Node* node, Truncation truncation, | 1127 void VisitSpeculativeAdditiveOp(Node* node, Truncation truncation, |
| 1129 SimplifiedLowering* lowering) { | 1128 SimplifiedLowering* lowering) { |
| 1130 // ToNumber(x) can throw if x is either a Receiver or a Symbol, so we can | 1129 // ToNumber(x) can throw if x is either a Receiver or a Symbol, so we can |
| 1131 // only eliminate an unused speculative number operation if we know that | 1130 // only eliminate an unused speculative number operation if we know that |
| 1132 // the inputs are PlainPrimitive, which excludes everything that's might | 1131 // the inputs are PlainPrimitive, which excludes everything that's might |
| 1133 // have side effects or throws during a ToNumber conversion. | 1132 // have side effects or throws during a ToNumber conversion. |
| 1134 if (BothInputsAre(node, Type::PlainPrimitive())) { | 1133 if (BothInputsAre(node, Type::PlainPrimitive())) { |
| 1135 if (truncation.IsUnused()) return VisitUnused(node); | 1134 if (truncation.IsUnused()) return VisitUnused(node); |
| 1136 } | 1135 } |
| 1137 if (BothInputsAre(node, type_cache_.kAdditiveSafeIntegerOrMinusZero) && | 1136 if (BothInputsAre(node, type_cache_.kAdditiveSafeIntegerOrMinusZero) && |
| 1138 (GetUpperBound(node)->Is(Type::Signed32()) || | 1137 (GetUpperBound(node)->Is(Type::Signed32()) || |
| 1139 GetUpperBound(node)->Is(Type::Unsigned32()) || | 1138 GetUpperBound(node)->Is(Type::Unsigned32()) || |
| 1140 truncation.IsUsedAsWord32())) { | 1139 truncation.IsUsedAsWord32())) { |
| 1141 // => Int32Add/Sub | 1140 // => Int32Add/Sub |
| 1142 VisitWord32TruncatingBinop(node); | 1141 VisitWord32TruncatingBinop(node); |
| 1143 if (lower()) ChangeToPureOp(node, Int32Op(node)); | 1142 if (lower()) ChangeToPureOp(node, Int32Op(node)); |
| 1144 return; | 1143 return; |
| 1145 } | 1144 } |
| 1146 | 1145 |
| 1147 // We always take SignedSmall/Signed32 feedback otherwise. | 1146 // Try to use type feedback. |
| 1148 NumberOperationHint const hint = NumberOperationHintOf(node->op()); | 1147 NumberOperationHint hint = NumberOperationHintOf(node->op()); |
| 1148 |
| 1149 // Handle the case when no int32 checks on inputs are necessary |
| 1150 // (but an overflow check is needed on the output). |
| 1151 if (BothInputsAre(node, Type::Signed32()) || |
| 1152 (BothInputsAre(node, Type::Signed32OrMinusZero()) && |
| 1153 NodeProperties::GetType(node)->Is(type_cache_.kSafeInteger))) { |
| 1154 // If both the inputs the feedback are int32, use the overflow op. |
| 1155 if (hint == NumberOperationHint::kSignedSmall || |
| 1156 hint == NumberOperationHint::kSigned32) { |
| 1157 VisitBinop(node, UseInfo::TruncatingWord32(), |
| 1158 MachineRepresentation::kWord32, Type::Signed32()); |
| 1159 if (lower()) ChangeToInt32OverflowOp(node); |
| 1160 return; |
| 1161 } |
| 1162 } |
| 1163 |
| 1149 if (hint == NumberOperationHint::kSignedSmall || | 1164 if (hint == NumberOperationHint::kSignedSmall || |
| 1150 hint == NumberOperationHint::kSigned32) { | 1165 hint == NumberOperationHint::kSigned32) { |
| 1151 // Check if we can guarantee truncations for the inputs. | 1166 VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint), |
| 1152 if (BothInputsAre(node, Type::Signed32()) || | 1167 MachineRepresentation::kWord32, Type::Signed32()); |
| 1153 (BothInputsAre(node, Type::Signed32OrMinusZero()) && | 1168 if (lower()) ChangeToInt32OverflowOp(node); |
| 1154 NodeProperties::GetType(node)->Is(type_cache_.kSafeInteger))) { | |
| 1155 VisitBinop(node, UseInfo::TruncatingWord32(), | |
| 1156 MachineRepresentation::kWord32, Type::Signed32()); | |
| 1157 } else { | |
| 1158 VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint), | |
| 1159 MachineRepresentation::kWord32, Type::Signed32()); | |
| 1160 } | |
| 1161 if (lower()) { | |
| 1162 // Avoid overflow checks if the unrestricted feedback type of {node} | |
| 1163 // suggests that the result will fit into Signed32/Unsigned32 range. | |
| 1164 Type* const type = UnrestrictedFeedbackTypeOf(node); | |
| 1165 if (type->Is(Type::Unsigned32())) { | |
| 1166 ChangeToPureOp(node, Uint32Op(node)); | |
| 1167 } else if (type->Is(Type::Signed32())) { | |
| 1168 ChangeToPureOp(node, Int32Op(node)); | |
| 1169 } else { | |
| 1170 ChangeToInt32OverflowOp(node); | |
| 1171 } | |
| 1172 } | |
| 1173 return; | 1169 return; |
| 1174 } | 1170 } |
| 1175 | 1171 |
| 1176 // default case => Float64Add/Sub | 1172 // default case => Float64Add/Sub |
| 1177 VisitBinop(node, UseInfo::CheckedNumberOrOddballAsFloat64(), | 1173 VisitBinop(node, UseInfo::CheckedNumberOrOddballAsFloat64(), |
| 1178 MachineRepresentation::kFloat64, Type::Number()); | 1174 MachineRepresentation::kFloat64, Type::Number()); |
| 1179 if (lower()) { | 1175 if (lower()) { |
| 1180 ChangeToPureOp(node, Float64Op(node)); | 1176 ChangeToPureOp(node, Float64Op(node)); |
| 1181 } | 1177 } |
| 1178 return; |
| 1182 } | 1179 } |
| 1183 | 1180 |
| 1184 void VisitSpeculativeNumberModulus(Node* node, Truncation truncation, | 1181 void VisitSpeculativeNumberModulus(Node* node, Truncation truncation, |
| 1185 SimplifiedLowering* lowering) { | 1182 SimplifiedLowering* lowering) { |
| 1186 // ToNumber(x) can throw if x is either a Receiver or a Symbol, so we | 1183 // ToNumber(x) can throw if x is either a Receiver or a Symbol, so we |
| 1187 // can only eliminate an unused speculative number operation if we know | 1184 // can only eliminate an unused speculative number operation if we know |
| 1188 // that the inputs are PlainPrimitive, which excludes everything that's | 1185 // that the inputs are PlainPrimitive, which excludes everything that's |
| 1189 // might have side effects or throws during a ToNumber conversion. | 1186 // might have side effects or throws during a ToNumber conversion. |
| 1190 if (BothInputsAre(node, Type::PlainPrimitive())) { | 1187 if (BothInputsAre(node, Type::PlainPrimitive())) { |
| 1191 if (truncation.IsUnused()) return VisitUnused(node); | 1188 if (truncation.IsUnused()) return VisitUnused(node); |
| (...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1513 type_cache_.kSafeIntegerOrMinusZero)))) { | 1510 type_cache_.kSafeIntegerOrMinusZero)))) { |
| 1514 // Multiply reduces to Int32Mul if the inputs are integers, and | 1511 // Multiply reduces to Int32Mul if the inputs are integers, and |
| 1515 // (a) the output is either known to be Signed32, or | 1512 // (a) the output is either known to be Signed32, or |
| 1516 // (b) the output is known to be Unsigned32, or | 1513 // (b) the output is known to be Unsigned32, or |
| 1517 // (c) the uses are truncating and the result is in the safe | 1514 // (c) the uses are truncating and the result is in the safe |
| 1518 // integer range. | 1515 // integer range. |
| 1519 VisitWord32TruncatingBinop(node); | 1516 VisitWord32TruncatingBinop(node); |
| 1520 if (lower()) ChangeToPureOp(node, Int32Op(node)); | 1517 if (lower()) ChangeToPureOp(node, Int32Op(node)); |
| 1521 return; | 1518 return; |
| 1522 } | 1519 } |
| 1520 // Try to use type feedback. |
| 1521 NumberOperationHint hint = NumberOperationHintOf(node->op()); |
| 1522 Type* input0_type = TypeOf(node->InputAt(0)); |
| 1523 Type* input1_type = TypeOf(node->InputAt(1)); |
| 1523 | 1524 |
| 1524 // We always take SignedSmall/Signed32 feedback otherwise. | 1525 // Handle the case when no int32 checks on inputs are necessary |
| 1525 NumberOperationHint const hint = NumberOperationHintOf(node->op()); | 1526 // (but an overflow check is needed on the output). |
| 1527 if (BothInputsAre(node, Type::Signed32())) { |
| 1528 // If both the inputs the feedback are int32, use the overflow op. |
| 1529 if (hint == NumberOperationHint::kSignedSmall || |
| 1530 hint == NumberOperationHint::kSigned32) { |
| 1531 VisitBinop(node, UseInfo::TruncatingWord32(), |
| 1532 MachineRepresentation::kWord32, Type::Signed32()); |
| 1533 if (lower()) { |
| 1534 LowerToCheckedInt32Mul(node, truncation, input0_type, |
| 1535 input1_type); |
| 1536 } |
| 1537 return; |
| 1538 } |
| 1539 } |
| 1540 |
| 1526 if (hint == NumberOperationHint::kSignedSmall || | 1541 if (hint == NumberOperationHint::kSignedSmall || |
| 1527 hint == NumberOperationHint::kSigned32) { | 1542 hint == NumberOperationHint::kSigned32) { |
| 1528 // Handle the case when no int32 checks on inputs are necessary | 1543 VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint), |
| 1529 // (but an overflow check is needed on the output). | 1544 MachineRepresentation::kWord32, Type::Signed32()); |
| 1530 if (BothInputsAre(node, Type::Signed32())) { | |
| 1531 // If both the inputs the feedback are int32, use the overflow op. | |
| 1532 VisitBinop(node, UseInfo::TruncatingWord32(), | |
| 1533 MachineRepresentation::kWord32, Type::Signed32()); | |
| 1534 } else { | |
| 1535 VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint), | |
| 1536 MachineRepresentation::kWord32, Type::Signed32()); | |
| 1537 } | |
| 1538 if (lower()) { | 1545 if (lower()) { |
| 1539 // Avoid overflow checks if the unrestricted feedback type of {node} | 1546 LowerToCheckedInt32Mul(node, truncation, input0_type, input1_type); |
| 1540 // suggests that the result will fit into Signed32/Unsigned32 range, | |
| 1541 // or at least try to avoid the expensive minus zero checks. | |
| 1542 Type* const type = UnrestrictedFeedbackTypeOf(node); | |
| 1543 if (type->Is(Type::Unsigned32())) { | |
| 1544 ChangeToPureOp(node, Uint32Op(node)); | |
| 1545 } else if (type->Is(Type::Signed32())) { | |
| 1546 ChangeToPureOp(node, Int32Op(node)); | |
| 1547 } else { | |
| 1548 CheckForMinusZeroMode const mode = | |
| 1549 (truncation.IdentifiesMinusZeroAndZero() || | |
| 1550 !type->Maybe(Type::MinusZero())) | |
| 1551 ? CheckForMinusZeroMode::kDontCheckForMinusZero | |
| 1552 : CheckForMinusZeroMode::kCheckForMinusZero; | |
| 1553 NodeProperties::ChangeOp(node, | |
| 1554 simplified()->CheckedInt32Mul(mode)); | |
| 1555 } | |
| 1556 } | 1547 } |
| 1557 return; | 1548 return; |
| 1558 } | 1549 } |
| 1559 | 1550 |
| 1560 // Checked float64 x float64 => float64 | 1551 // Checked float64 x float64 => float64 |
| 1561 VisitBinop(node, UseInfo::CheckedNumberOrOddballAsFloat64(), | 1552 VisitBinop(node, UseInfo::CheckedNumberOrOddballAsFloat64(), |
| 1562 MachineRepresentation::kFloat64, Type::Number()); | 1553 MachineRepresentation::kFloat64, Type::Number()); |
| 1563 if (lower()) ChangeToPureOp(node, Float64Op(node)); | 1554 if (lower()) ChangeToPureOp(node, Float64Op(node)); |
| 1564 return; | 1555 return; |
| 1565 } | 1556 } |
| (...skipping 1681 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3247 isolate(), graph()->zone(), callable.descriptor(), 0, flags, | 3238 isolate(), graph()->zone(), callable.descriptor(), 0, flags, |
| 3248 Operator::kNoProperties); | 3239 Operator::kNoProperties); |
| 3249 to_number_operator_.set(common()->Call(desc)); | 3240 to_number_operator_.set(common()->Call(desc)); |
| 3250 } | 3241 } |
| 3251 return to_number_operator_.get(); | 3242 return to_number_operator_.get(); |
| 3252 } | 3243 } |
| 3253 | 3244 |
| 3254 } // namespace compiler | 3245 } // namespace compiler |
| 3255 } // namespace internal | 3246 } // namespace internal |
| 3256 } // namespace v8 | 3247 } // namespace v8 |
| OLD | NEW |