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 |