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 380 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
391 Type* static_type = op_typer_.NumericSubtract(lhs, rhs); | 391 Type* static_type = op_typer_.NumericSubtract(lhs, rhs); |
392 if (info->type_check() == TypeCheckKind::kNone) { | 392 if (info->type_check() == TypeCheckKind::kNone) { |
393 new_type = static_type; | 393 new_type = static_type; |
394 } else { | 394 } else { |
395 Type* feedback_type = TypeOfSpeculativeOp(info->type_check()); | 395 Type* feedback_type = TypeOfSpeculativeOp(info->type_check()); |
396 new_type = Type::Intersect(static_type, feedback_type, graph_zone()); | 396 new_type = Type::Intersect(static_type, feedback_type, graph_zone()); |
397 } | 397 } |
398 break; | 398 break; |
399 } | 399 } |
400 | 400 |
| 401 case IrOpcode::kSpeculativeNumberMultiply: { |
| 402 Type* lhs = FeedbackTypeOf(node->InputAt(0)); |
| 403 Type* rhs = FeedbackTypeOf(node->InputAt(1)); |
| 404 if (lhs->Is(Type::None()) || rhs->Is(Type::None())) return false; |
| 405 // TODO(jarin) The ToNumber conversion is too conservative here, |
| 406 // e.g. it will treat true as 1 even though the number check will |
| 407 // fail on a boolean. OperationTyper should have a function that |
| 408 // computes a more precise type. |
| 409 lhs = op_typer_.ToNumber(lhs); |
| 410 rhs = op_typer_.ToNumber(rhs); |
| 411 Type* static_type = op_typer_.NumericMultiply(lhs, rhs); |
| 412 if (info->type_check() == TypeCheckKind::kNone) { |
| 413 new_type = static_type; |
| 414 } else { |
| 415 Type* feedback_type = TypeOfSpeculativeOp(info->type_check()); |
| 416 new_type = Type::Intersect(static_type, feedback_type, graph_zone()); |
| 417 } |
| 418 break; |
| 419 } |
| 420 |
| 421 case IrOpcode::kSpeculativeNumberDivide: { |
| 422 Type* lhs = FeedbackTypeOf(node->InputAt(0)); |
| 423 Type* rhs = FeedbackTypeOf(node->InputAt(1)); |
| 424 if (lhs->Is(Type::None()) || rhs->Is(Type::None())) return false; |
| 425 // TODO(jarin) The ToNumber conversion is too conservative here, |
| 426 // e.g. it will treat true as 1 even though the number check will |
| 427 // fail on a boolean. OperationTyper should have a function that |
| 428 // computes a more precise type. |
| 429 lhs = op_typer_.ToNumber(lhs); |
| 430 rhs = op_typer_.ToNumber(rhs); |
| 431 Type* static_type = op_typer_.NumericDivide(lhs, rhs); |
| 432 if (info->type_check() == TypeCheckKind::kNone) { |
| 433 new_type = static_type; |
| 434 } else { |
| 435 Type* feedback_type = TypeOfSpeculativeOp(info->type_check()); |
| 436 new_type = Type::Intersect(static_type, feedback_type, graph_zone()); |
| 437 } |
| 438 break; |
| 439 } |
| 440 |
| 441 case IrOpcode::kSpeculativeNumberModulus: { |
| 442 Type* lhs = FeedbackTypeOf(node->InputAt(0)); |
| 443 Type* rhs = FeedbackTypeOf(node->InputAt(1)); |
| 444 if (lhs->Is(Type::None()) || rhs->Is(Type::None())) return false; |
| 445 // TODO(jarin) The ToNumber conversion is too conservative here, |
| 446 // e.g. it will treat true as 1 even though the number check will |
| 447 // fail on a boolean. OperationTyper should have a function that |
| 448 // computes a more precise type. |
| 449 lhs = op_typer_.ToNumber(lhs); |
| 450 rhs = op_typer_.ToNumber(rhs); |
| 451 Type* static_type = op_typer_.NumericModulus(lhs, rhs); |
| 452 if (info->type_check() == TypeCheckKind::kNone) { |
| 453 new_type = static_type; |
| 454 } else { |
| 455 Type* feedback_type = TypeOfSpeculativeOp(info->type_check()); |
| 456 new_type = Type::Intersect(static_type, feedback_type, graph_zone()); |
| 457 } |
| 458 break; |
| 459 } |
| 460 |
401 case IrOpcode::kPhi: { | 461 case IrOpcode::kPhi: { |
402 new_type = TypePhi(node); | 462 new_type = TypePhi(node); |
403 if (type != nullptr) { | 463 if (type != nullptr) { |
404 new_type = Weaken(node, type, new_type); | 464 new_type = Weaken(node, type, new_type); |
405 } | 465 } |
406 // Recompute the phi representation based on the new type. | 466 // Recompute the phi representation based on the new type. |
407 MachineRepresentation output = | 467 MachineRepresentation output = |
408 GetOutputInfoForPhi(node, GetInfo(node)->truncation(), new_type); | 468 GetOutputInfoForPhi(node, GetInfo(node)->truncation(), new_type); |
409 ResetOutput(node, output); | 469 ResetOutput(node, output); |
410 break; | 470 break; |
(...skipping 585 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
996 return WriteBarrierKindFor(base_taggedness, field_representation, | 1056 return WriteBarrierKindFor(base_taggedness, field_representation, |
997 field_type, value); | 1057 field_type, value); |
998 } | 1058 } |
999 | 1059 |
1000 Graph* graph() const { return jsgraph_->graph(); } | 1060 Graph* graph() const { return jsgraph_->graph(); } |
1001 CommonOperatorBuilder* common() const { return jsgraph_->common(); } | 1061 CommonOperatorBuilder* common() const { return jsgraph_->common(); } |
1002 SimplifiedOperatorBuilder* simplified() const { | 1062 SimplifiedOperatorBuilder* simplified() const { |
1003 return jsgraph_->simplified(); | 1063 return jsgraph_->simplified(); |
1004 } | 1064 } |
1005 | 1065 |
1006 void ChangeToPureOp(Node* node, const Operator* new_op) { | 1066 void ReplaceEffectControlUses(Node* node, Node* effect, Node* control) { |
1007 // Disconnect the node from effect and control chains. | |
1008 Node* control = NodeProperties::GetControlInput(node); | |
1009 Node* effect = NodeProperties::GetEffectInput(node); | |
1010 for (Edge edge : node->use_edges()) { | 1067 for (Edge edge : node->use_edges()) { |
1011 if (NodeProperties::IsControlEdge(edge)) { | 1068 if (NodeProperties::IsControlEdge(edge)) { |
1012 edge.UpdateTo(control); | 1069 edge.UpdateTo(control); |
1013 } else if (NodeProperties::IsEffectEdge(edge)) { | 1070 } else if (NodeProperties::IsEffectEdge(edge)) { |
1014 edge.UpdateTo(effect); | 1071 edge.UpdateTo(effect); |
1015 } else { | 1072 } else { |
1016 DCHECK(NodeProperties::IsValueEdge(edge)); | 1073 DCHECK(NodeProperties::IsValueEdge(edge)); |
1017 } | 1074 } |
1018 } | 1075 } |
1019 | |
1020 node->TrimInputCount(new_op->ValueInputCount()); | |
1021 NodeProperties::ChangeOp(node, new_op); | |
1022 } | |
1023 | |
1024 void ReplaceEffectControlUses(Node* node, Node* effect, Node* control) { | |
1025 for (Edge edge : node->use_edges()) { | |
1026 if (NodeProperties::IsControlEdge(edge)) { | |
1027 edge.UpdateTo(control); | |
1028 } else if (NodeProperties::IsEffectEdge(edge)) { | |
1029 edge.UpdateTo(effect); | |
1030 } else { | |
1031 DCHECK(NodeProperties::IsValueEdge(edge)); | |
1032 } | |
1033 } | |
1034 } | 1076 } |
1035 | 1077 |
| 1078 void ChangeToPureOp(Node* node, const Operator* new_op) { |
| 1079 if (node->op()->EffectInputCount() > 0) { |
| 1080 DCHECK_LT(0, node->op()->ControlInputCount()); |
| 1081 // Disconnect the node from effect and control chains. |
| 1082 Node* control = NodeProperties::GetControlInput(node); |
| 1083 Node* effect = NodeProperties::GetEffectInput(node); |
| 1084 ReplaceEffectControlUses(node, effect, control); |
| 1085 node->TrimInputCount(new_op->ValueInputCount()); |
| 1086 } else { |
| 1087 DCHECK_EQ(0, node->op()->ControlInputCount()); |
| 1088 } |
| 1089 |
| 1090 NodeProperties::ChangeOp(node, new_op); |
| 1091 } |
| 1092 |
1036 void ChangeToInt32OverflowOp(Node* node, const Operator* op) { | 1093 void ChangeToInt32OverflowOp(Node* node, const Operator* op) { |
1037 Node* effect = NodeProperties::GetEffectInput(node); | 1094 Node* effect = NodeProperties::GetEffectInput(node); |
1038 Node* control = NodeProperties::GetControlInput(node); | 1095 Node* control = NodeProperties::GetControlInput(node); |
1039 Node* arith = graph()->NewNode(op, node->InputAt(0), node->InputAt(1)); | 1096 Node* arith = graph()->NewNode(op, node->InputAt(0), node->InputAt(1)); |
1040 Node* overflow = graph()->NewNode(common()->Projection(1), arith); | 1097 Node* overflow = graph()->NewNode(common()->Projection(1), arith); |
1041 effect = | 1098 effect = |
1042 graph()->NewNode(simplified()->CheckIf(), overflow, effect, control); | 1099 graph()->NewNode(simplified()->CheckIf(), overflow, effect, control); |
1043 Node* value = graph()->NewNode(common()->Projection(0), arith); | 1100 Node* value = graph()->NewNode(common()->Projection(0), arith); |
1044 ReplaceEffectControlUses(node, effect, control); | 1101 ReplaceEffectControlUses(node, effect, control); |
1045 DeferReplacement(node, value); | 1102 DeferReplacement(node, value); |
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1288 // => signed Int32Add/Sub (truncated) | 1345 // => signed Int32Add/Sub (truncated) |
1289 VisitWord32TruncatingBinop(node); | 1346 VisitWord32TruncatingBinop(node); |
1290 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node)); | 1347 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node)); |
1291 } else { | 1348 } else { |
1292 // => Float64Add/Sub | 1349 // => Float64Add/Sub |
1293 VisitFloat64Binop(node); | 1350 VisitFloat64Binop(node); |
1294 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); | 1351 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); |
1295 } | 1352 } |
1296 return; | 1353 return; |
1297 } | 1354 } |
| 1355 case IrOpcode::kSpeculativeNumberMultiply: |
1298 case IrOpcode::kNumberMultiply: { | 1356 case IrOpcode::kNumberMultiply: { |
1299 if (BothInputsAreSigned32(node)) { | 1357 if (BothInputsAreSigned32(node)) { |
1300 if (NodeProperties::GetType(node)->Is(Type::Signed32())) { | 1358 if (NodeProperties::GetType(node)->Is(Type::Signed32())) { |
1301 // Multiply reduces to Int32Mul if the inputs and the output | 1359 // Multiply reduces to Int32Mul if the inputs and the output |
1302 // are integers. | 1360 // are integers. |
1303 VisitInt32Binop(node); | 1361 VisitInt32Binop(node); |
1304 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node)); | 1362 if (lower()) ChangeToPureOp(node, Int32Op(node)); |
1305 return; | 1363 return; |
1306 } | 1364 } |
1307 if (truncation.TruncatesToWord32() && | 1365 if (truncation.TruncatesToWord32() && |
1308 NodeProperties::GetType(node)->Is(type_cache_.kSafeInteger)) { | 1366 NodeProperties::GetType(node)->Is(type_cache_.kSafeInteger)) { |
1309 // Multiply reduces to Int32Mul if the inputs are integers, | 1367 // Multiply reduces to Int32Mul if the inputs are integers, |
1310 // the uses are truncating and the result is in the safe | 1368 // the uses are truncating and the result is in the safe |
1311 // integer range. | 1369 // integer range. |
1312 VisitWord32TruncatingBinop(node); | 1370 VisitWord32TruncatingBinop(node); |
1313 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node)); | 1371 if (lower()) ChangeToPureOp(node, Int32Op(node)); |
1314 return; | 1372 return; |
1315 } | 1373 } |
1316 } | 1374 } |
1317 // => Float64Mul | 1375 // Number x Number => Float64Mul |
1318 VisitFloat64Binop(node); | 1376 if (BothInputsAre(node, Type::NumberOrUndefined())) { |
1319 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); | 1377 VisitFloat64Binop(node); |
| 1378 if (lower()) ChangeToPureOp(node, Float64Op(node)); |
| 1379 return; |
| 1380 } |
| 1381 // Checked float64 x float64 => float64 |
| 1382 DCHECK_EQ(IrOpcode::kSpeculativeNumberMultiply, node->opcode()); |
| 1383 VisitBinop(node, UseInfo::CheckedNumberOrUndefinedAsFloat64(), |
| 1384 MachineRepresentation::kFloat64, TypeCheckKind::kNumber); |
| 1385 if (lower()) ChangeToPureOp(node, Float64Op(node)); |
1320 return; | 1386 return; |
1321 } | 1387 } |
| 1388 case IrOpcode::kSpeculativeNumberDivide: |
1322 case IrOpcode::kNumberDivide: { | 1389 case IrOpcode::kNumberDivide: { |
1323 if (BothInputsAreSigned32(node)) { | 1390 if (BothInputsAreSigned32(node)) { |
1324 if (NodeProperties::GetType(node)->Is(Type::Signed32())) { | 1391 if (NodeProperties::GetType(node)->Is(Type::Signed32())) { |
1325 // => signed Int32Div | 1392 // => signed Int32Div |
1326 VisitInt32Binop(node); | 1393 VisitInt32Binop(node); |
1327 if (lower()) DeferReplacement(node, lowering->Int32Div(node)); | 1394 if (lower()) DeferReplacement(node, lowering->Int32Div(node)); |
1328 return; | 1395 return; |
1329 } | 1396 } |
1330 if (truncation.TruncatesToWord32()) { | 1397 if (truncation.TruncatesToWord32()) { |
1331 // => signed Int32Div | 1398 // => signed Int32Div |
1332 VisitWord32TruncatingBinop(node); | 1399 VisitWord32TruncatingBinop(node); |
1333 if (lower()) DeferReplacement(node, lowering->Int32Div(node)); | 1400 if (lower()) DeferReplacement(node, lowering->Int32Div(node)); |
1334 return; | 1401 return; |
1335 } | 1402 } |
1336 } | 1403 } |
1337 if (BothInputsAreUnsigned32(node) && truncation.TruncatesToWord32()) { | 1404 if (BothInputsAreUnsigned32(node) && truncation.TruncatesToWord32()) { |
1338 // => unsigned Uint32Div | 1405 // => unsigned Uint32Div |
1339 VisitWord32TruncatingBinop(node); | 1406 VisitWord32TruncatingBinop(node); |
1340 if (lower()) DeferReplacement(node, lowering->Uint32Div(node)); | 1407 if (lower()) DeferReplacement(node, lowering->Uint32Div(node)); |
1341 return; | 1408 return; |
1342 } | 1409 } |
1343 // => Float64Div | 1410 // Number x Number => Float64Div |
1344 VisitFloat64Binop(node); | 1411 if (BothInputsAre(node, Type::NumberOrUndefined())) { |
1345 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); | 1412 VisitFloat64Binop(node); |
| 1413 if (lower()) ChangeToPureOp(node, Float64Op(node)); |
| 1414 return; |
| 1415 } |
| 1416 // Checked float64 x float64 => float64 |
| 1417 DCHECK_EQ(IrOpcode::kSpeculativeNumberDivide, node->opcode()); |
| 1418 VisitBinop(node, UseInfo::CheckedNumberOrUndefinedAsFloat64(), |
| 1419 MachineRepresentation::kFloat64, TypeCheckKind::kNumber); |
| 1420 if (lower()) ChangeToPureOp(node, Float64Op(node)); |
1346 return; | 1421 return; |
1347 } | 1422 } |
| 1423 case IrOpcode::kSpeculativeNumberModulus: |
1348 case IrOpcode::kNumberModulus: { | 1424 case IrOpcode::kNumberModulus: { |
1349 if (BothInputsAreSigned32(node)) { | 1425 if (BothInputsAreSigned32(node)) { |
1350 if (NodeProperties::GetType(node)->Is(Type::Signed32())) { | 1426 if (NodeProperties::GetType(node)->Is(Type::Signed32())) { |
1351 // => signed Int32Mod | 1427 // => signed Int32Mod |
1352 VisitInt32Binop(node); | 1428 VisitInt32Binop(node); |
1353 if (lower()) DeferReplacement(node, lowering->Int32Mod(node)); | 1429 if (lower()) DeferReplacement(node, lowering->Int32Mod(node)); |
1354 return; | 1430 return; |
1355 } | 1431 } |
1356 if (truncation.TruncatesToWord32()) { | 1432 if (truncation.TruncatesToWord32()) { |
1357 // => signed Int32Mod | 1433 // => signed Int32Mod |
1358 VisitWord32TruncatingBinop(node); | 1434 VisitWord32TruncatingBinop(node); |
1359 if (lower()) DeferReplacement(node, lowering->Int32Mod(node)); | 1435 if (lower()) DeferReplacement(node, lowering->Int32Mod(node)); |
1360 return; | 1436 return; |
1361 } | 1437 } |
1362 } | 1438 } |
1363 if (BothInputsAreUnsigned32(node) && truncation.TruncatesToWord32()) { | 1439 if (BothInputsAreUnsigned32(node) && truncation.TruncatesToWord32()) { |
1364 // => unsigned Uint32Mod | 1440 // => unsigned Uint32Mod |
1365 VisitWord32TruncatingBinop(node); | 1441 VisitWord32TruncatingBinop(node); |
1366 if (lower()) DeferReplacement(node, lowering->Uint32Mod(node)); | 1442 if (lower()) DeferReplacement(node, lowering->Uint32Mod(node)); |
1367 return; | 1443 return; |
1368 } | 1444 } |
1369 // => Float64Mod | 1445 // Number x Number => Float64Mod |
1370 VisitFloat64Binop(node); | 1446 if (BothInputsAre(node, Type::NumberOrUndefined())) { |
1371 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); | 1447 // => Float64Mod |
| 1448 VisitFloat64Binop(node); |
| 1449 if (lower()) ChangeToPureOp(node, Float64Op(node)); |
| 1450 return; |
| 1451 } |
| 1452 // Checked float64 x float64 => float64 |
| 1453 DCHECK_EQ(IrOpcode::kSpeculativeNumberModulus, node->opcode()); |
| 1454 VisitBinop(node, UseInfo::CheckedNumberOrUndefinedAsFloat64(), |
| 1455 MachineRepresentation::kFloat64, TypeCheckKind::kNumber); |
| 1456 if (lower()) ChangeToPureOp(node, Float64Op(node)); |
1372 return; | 1457 return; |
1373 } | 1458 } |
1374 case IrOpcode::kNumberBitwiseOr: | 1459 case IrOpcode::kNumberBitwiseOr: |
1375 case IrOpcode::kNumberBitwiseXor: | 1460 case IrOpcode::kNumberBitwiseXor: |
1376 case IrOpcode::kNumberBitwiseAnd: { | 1461 case IrOpcode::kNumberBitwiseAnd: { |
1377 VisitInt32Binop(node); | 1462 VisitInt32Binop(node); |
1378 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node)); | 1463 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node)); |
1379 return; | 1464 return; |
1380 } | 1465 } |
1381 case IrOpcode::kNumberShiftLeft: { | 1466 case IrOpcode::kNumberShiftLeft: { |
(...skipping 544 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1926 return SetOutput(node, MachineRepresentation::kTagged); | 2011 return SetOutput(node, MachineRepresentation::kTagged); |
1927 } | 2012 } |
1928 UNREACHABLE(); | 2013 UNREACHABLE(); |
1929 } | 2014 } |
1930 | 2015 |
1931 void DeferReplacement(Node* node, Node* replacement) { | 2016 void DeferReplacement(Node* node, Node* replacement) { |
1932 TRACE("defer replacement #%d:%s with #%d:%s\n", node->id(), | 2017 TRACE("defer replacement #%d:%s with #%d:%s\n", node->id(), |
1933 node->op()->mnemonic(), replacement->id(), | 2018 node->op()->mnemonic(), replacement->id(), |
1934 replacement->op()->mnemonic()); | 2019 replacement->op()->mnemonic()); |
1935 | 2020 |
| 2021 // Disconnect the node from effect and control chains, if necessary. |
| 2022 if (node->op()->EffectInputCount() > 0) { |
| 2023 DCHECK_LT(0, node->op()->ControlInputCount()); |
| 2024 // Disconnect the node from effect and control chains. |
| 2025 Node* control = NodeProperties::GetControlInput(node); |
| 2026 Node* effect = NodeProperties::GetEffectInput(node); |
| 2027 ReplaceEffectControlUses(node, effect, control); |
| 2028 } else { |
| 2029 DCHECK_EQ(0, node->op()->ControlInputCount()); |
| 2030 } |
| 2031 |
1936 if (replacement->id() < count_ && | 2032 if (replacement->id() < count_ && |
1937 GetUpperBound(node)->Is(GetUpperBound(replacement)) && | 2033 GetUpperBound(node)->Is(GetUpperBound(replacement)) && |
1938 TypeOf(node)->Is(TypeOf(replacement))) { | 2034 TypeOf(node)->Is(TypeOf(replacement))) { |
1939 // Replace with a previously existing node eagerly only if the type is the | 2035 // Replace with a previously existing node eagerly only if the type is the |
1940 // same. | 2036 // same. |
1941 node->ReplaceUses(replacement); | 2037 node->ReplaceUses(replacement); |
1942 } else { | 2038 } else { |
1943 // Otherwise, we are replacing a node with a representation change. | 2039 // Otherwise, we are replacing a node with a representation change. |
1944 // Such a substitution must be done after all lowering is done, because | 2040 // Such a substitution must be done after all lowering is done, because |
1945 // changing the type could confuse the representation change | 2041 // changing the type could confuse the representation change |
(...skipping 982 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2928 isolate(), graph()->zone(), callable.descriptor(), 0, flags, | 3024 isolate(), graph()->zone(), callable.descriptor(), 0, flags, |
2929 Operator::kNoProperties); | 3025 Operator::kNoProperties); |
2930 to_number_operator_.set(common()->Call(desc)); | 3026 to_number_operator_.set(common()->Call(desc)); |
2931 } | 3027 } |
2932 return to_number_operator_.get(); | 3028 return to_number_operator_.get(); |
2933 } | 3029 } |
2934 | 3030 |
2935 } // namespace compiler | 3031 } // namespace compiler |
2936 } // namespace internal | 3032 } // namespace internal |
2937 } // namespace v8 | 3033 } // namespace v8 |
OLD | NEW |