| 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 <algorithm> | 5 #include <algorithm> |
| 6 | 6 |
| 7 #include "src/base/adapters.h" | 7 #include "src/base/adapters.h" |
| 8 #include "src/compiler/instruction-selector-impl.h" | 8 #include "src/compiler/instruction-selector-impl.h" |
| 9 #include "src/compiler/node-matchers.h" | 9 #include "src/compiler/node-matchers.h" |
| 10 #include "src/compiler/node-properties.h" | 10 #include "src/compiler/node-properties.h" |
| (...skipping 18 matching lines...) Expand all Loading... |
| 29 } | 29 } |
| 30 case IrOpcode::kNumberConstant: { | 30 case IrOpcode::kNumberConstant: { |
| 31 const double value = OpParameter<double>(node); | 31 const double value = OpParameter<double>(node); |
| 32 return bit_cast<int64_t>(value) == 0; | 32 return bit_cast<int64_t>(value) == 0; |
| 33 } | 33 } |
| 34 default: | 34 default: |
| 35 return false; | 35 return false; |
| 36 } | 36 } |
| 37 } | 37 } |
| 38 | 38 |
| 39 bool CanBeMemoryOperand(InstructionCode opcode, Node* node, Node* input) { |
| 40 if (input->opcode() != IrOpcode::kLoad || |
| 41 !selector()->CanCover(node, input)) { |
| 42 return false; |
| 43 } |
| 44 MachineRepresentation rep = |
| 45 LoadRepresentationOf(input->op()).representation(); |
| 46 if (rep == MachineRepresentation::kWord64 || |
| 47 rep == MachineRepresentation::kTagged) { |
| 48 return opcode == kX64Cmp || opcode == kX64Test; |
| 49 } else if (rep == MachineRepresentation::kWord32) { |
| 50 return opcode == kX64Cmp32 || opcode == kX64Test32; |
| 51 } |
| 52 return false; |
| 53 } |
| 54 |
| 39 AddressingMode GenerateMemoryOperandInputs(Node* index, int scale_exponent, | 55 AddressingMode GenerateMemoryOperandInputs(Node* index, int scale_exponent, |
| 40 Node* base, Node* displacement, | 56 Node* base, Node* displacement, |
| 41 InstructionOperand inputs[], | 57 InstructionOperand inputs[], |
| 42 size_t* input_count) { | 58 size_t* input_count) { |
| 43 AddressingMode mode = kMode_MRI; | 59 AddressingMode mode = kMode_MRI; |
| 44 if (base != nullptr) { | 60 if (base != nullptr) { |
| 45 inputs[(*input_count)++] = UseRegister(base); | 61 inputs[(*input_count)++] = UseRegister(base); |
| 46 if (index != nullptr) { | 62 if (index != nullptr) { |
| 47 DCHECK(scale_exponent >= 0 && scale_exponent <= 3); | 63 DCHECK(scale_exponent >= 0 && scale_exponent <= 3); |
| 48 inputs[(*input_count)++] = UseRegister(index); | 64 inputs[(*input_count)++] = UseRegister(index); |
| (...skipping 1307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1356 inputs[input_count++] = g.Label(cont->true_block()); | 1372 inputs[input_count++] = g.Label(cont->true_block()); |
| 1357 inputs[input_count++] = g.Label(cont->false_block()); | 1373 inputs[input_count++] = g.Label(cont->false_block()); |
| 1358 selector->Emit(opcode, 0, nullptr, input_count, inputs); | 1374 selector->Emit(opcode, 0, nullptr, input_count, inputs); |
| 1359 } else { | 1375 } else { |
| 1360 DCHECK(cont->IsSet()); | 1376 DCHECK(cont->IsSet()); |
| 1361 InstructionOperand output = g.DefineAsRegister(cont->result()); | 1377 InstructionOperand output = g.DefineAsRegister(cont->result()); |
| 1362 selector->Emit(opcode, 1, &output, input_count, inputs); | 1378 selector->Emit(opcode, 1, &output, input_count, inputs); |
| 1363 } | 1379 } |
| 1364 } | 1380 } |
| 1365 | 1381 |
| 1366 // Determines if {input} of {node} can be replaced by a memory operand. | |
| 1367 bool CanUseMemoryOperand(InstructionSelector* selector, InstructionCode opcode, | |
| 1368 Node* node, Node* input) { | |
| 1369 if (input->opcode() != IrOpcode::kLoad || !selector->CanCover(node, input)) { | |
| 1370 return false; | |
| 1371 } | |
| 1372 MachineRepresentation rep = | |
| 1373 LoadRepresentationOf(input->op()).representation(); | |
| 1374 if (rep == MachineRepresentation::kWord64 || | |
| 1375 rep == MachineRepresentation::kTagged) { | |
| 1376 return opcode == kX64Cmp || opcode == kX64Test; | |
| 1377 } else if (rep == MachineRepresentation::kWord32) { | |
| 1378 return opcode == kX64Cmp32 || opcode == kX64Test32; | |
| 1379 } | |
| 1380 return false; | |
| 1381 } | |
| 1382 | |
| 1383 // Shared routine for multiple compare operations. | 1382 // Shared routine for multiple compare operations. |
| 1384 void VisitCompare(InstructionSelector* selector, InstructionCode opcode, | 1383 void VisitCompare(InstructionSelector* selector, InstructionCode opcode, |
| 1385 InstructionOperand left, InstructionOperand right, | 1384 InstructionOperand left, InstructionOperand right, |
| 1386 FlagsContinuation* cont) { | 1385 FlagsContinuation* cont) { |
| 1387 X64OperandGenerator g(selector); | 1386 X64OperandGenerator g(selector); |
| 1388 opcode = cont->Encode(opcode); | 1387 opcode = cont->Encode(opcode); |
| 1389 if (cont->IsBranch()) { | 1388 if (cont->IsBranch()) { |
| 1390 selector->Emit(opcode, g.NoOutput(), left, right, | 1389 selector->Emit(opcode, g.NoOutput(), left, right, |
| 1391 g.Label(cont->true_block()), g.Label(cont->false_block())); | 1390 g.Label(cont->true_block()), g.Label(cont->false_block())); |
| 1392 } else { | 1391 } else { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1407 VisitCompare(selector, opcode, g.UseRegister(left), g.Use(right), cont); | 1406 VisitCompare(selector, opcode, g.UseRegister(left), g.Use(right), cont); |
| 1408 } | 1407 } |
| 1409 | 1408 |
| 1410 // Shared routine for multiple word compare operations. | 1409 // Shared routine for multiple word compare operations. |
| 1411 void VisitWordCompare(InstructionSelector* selector, Node* node, | 1410 void VisitWordCompare(InstructionSelector* selector, Node* node, |
| 1412 InstructionCode opcode, FlagsContinuation* cont) { | 1411 InstructionCode opcode, FlagsContinuation* cont) { |
| 1413 X64OperandGenerator g(selector); | 1412 X64OperandGenerator g(selector); |
| 1414 Node* left = node->InputAt(0); | 1413 Node* left = node->InputAt(0); |
| 1415 Node* right = node->InputAt(1); | 1414 Node* right = node->InputAt(1); |
| 1416 | 1415 |
| 1417 // If one of the two inputs is an immediate, make sure it's on the right. | 1416 // If one of the two inputs is an immediate, make sure it's on the right, or |
| 1418 if (!g.CanBeImmediate(right) && g.CanBeImmediate(left)) { | 1417 // if one of the two inputs is a memory operand, make sure it's on the left. |
| 1418 if ((!g.CanBeImmediate(right) && g.CanBeImmediate(left)) || |
| 1419 (g.CanBeMemoryOperand(opcode, node, right) && |
| 1420 !g.CanBeMemoryOperand(opcode, node, left))) { |
| 1419 if (!node->op()->HasProperty(Operator::kCommutative)) cont->Commute(); | 1421 if (!node->op()->HasProperty(Operator::kCommutative)) cont->Commute(); |
| 1420 std::swap(left, right); | 1422 std::swap(left, right); |
| 1421 } | 1423 } |
| 1422 | 1424 |
| 1423 // Match immediates on right side of comparison. | 1425 // Match immediates on right side of comparison. |
| 1424 if (g.CanBeImmediate(right)) { | 1426 if (g.CanBeImmediate(right)) { |
| 1425 if (CanUseMemoryOperand(selector, opcode, node, left)) { | 1427 if (g.CanBeMemoryOperand(opcode, node, left)) { |
| 1426 return VisitCompareWithMemoryOperand(selector, opcode, left, | 1428 return VisitCompareWithMemoryOperand(selector, opcode, left, |
| 1427 g.UseImmediate(right), cont); | 1429 g.UseImmediate(right), cont); |
| 1428 } | 1430 } |
| 1429 return VisitCompare(selector, opcode, g.Use(left), g.UseImmediate(right), | 1431 return VisitCompare(selector, opcode, g.Use(left), g.UseImmediate(right), |
| 1430 cont); | 1432 cont); |
| 1431 } | 1433 } |
| 1432 | 1434 |
| 1435 // Match memory operands on left side of comparison. |
| 1436 if (g.CanBeMemoryOperand(opcode, node, left)) { |
| 1437 return VisitCompareWithMemoryOperand(selector, opcode, left, |
| 1438 g.UseRegister(right), cont); |
| 1439 } |
| 1440 |
| 1433 if (g.CanBeBetterLeftOperand(right)) { | 1441 if (g.CanBeBetterLeftOperand(right)) { |
| 1434 if (!node->op()->HasProperty(Operator::kCommutative)) cont->Commute(); | 1442 if (!node->op()->HasProperty(Operator::kCommutative)) cont->Commute(); |
| 1435 std::swap(left, right); | 1443 std::swap(left, right); |
| 1436 } | 1444 } |
| 1437 | 1445 |
| 1438 if (CanUseMemoryOperand(selector, opcode, node, left)) { | |
| 1439 return VisitCompareWithMemoryOperand(selector, opcode, left, | |
| 1440 g.UseRegister(right), cont); | |
| 1441 } | |
| 1442 return VisitCompare(selector, opcode, left, right, cont, | 1446 return VisitCompare(selector, opcode, left, right, cont, |
| 1443 node->op()->HasProperty(Operator::kCommutative)); | 1447 node->op()->HasProperty(Operator::kCommutative)); |
| 1444 } | 1448 } |
| 1445 | 1449 |
| 1446 // Shared routine for 64-bit word comparison operations. | 1450 // Shared routine for 64-bit word comparison operations. |
| 1447 void VisitWord64Compare(InstructionSelector* selector, Node* node, | 1451 void VisitWord64Compare(InstructionSelector* selector, Node* node, |
| 1448 FlagsContinuation* cont) { | 1452 FlagsContinuation* cont) { |
| 1449 X64OperandGenerator g(selector); | 1453 X64OperandGenerator g(selector); |
| 1450 Int64BinopMatcher m(node); | 1454 Int64BinopMatcher m(node); |
| 1451 if (m.left().IsLoad() && m.right().IsLoadStackPointer()) { | 1455 if (m.left().IsLoad() && m.right().IsLoadStackPointer()) { |
| (...skipping 441 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1893 MachineOperatorBuilder::kFloat64RoundTruncate | | 1897 MachineOperatorBuilder::kFloat64RoundTruncate | |
| 1894 MachineOperatorBuilder::kFloat32RoundTiesEven | | 1898 MachineOperatorBuilder::kFloat32RoundTiesEven | |
| 1895 MachineOperatorBuilder::kFloat64RoundTiesEven; | 1899 MachineOperatorBuilder::kFloat64RoundTiesEven; |
| 1896 } | 1900 } |
| 1897 return flags; | 1901 return flags; |
| 1898 } | 1902 } |
| 1899 | 1903 |
| 1900 } // namespace compiler | 1904 } // namespace compiler |
| 1901 } // namespace internal | 1905 } // namespace internal |
| 1902 } // namespace v8 | 1906 } // namespace v8 |
| OLD | NEW |