Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(43)

Side by Side Diff: src/compiler/simplified-lowering.cc

Issue 2074903002: [turbofan] Numeric type feedback for mul, div and mod. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Rebase Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/compiler/representation-change.cc ('k') | src/compiler/simplified-operator.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/compiler/representation-change.cc ('k') | src/compiler/simplified-operator.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698