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/base/adapters.h" | 5 #include "src/base/adapters.h" |
6 #include "src/compiler/instruction-selector-impl.h" | 6 #include "src/compiler/instruction-selector-impl.h" |
7 #include "src/compiler/node-matchers.h" | 7 #include "src/compiler/node-matchers.h" |
8 #include "src/compiler/node-properties.h" | 8 #include "src/compiler/node-properties.h" |
9 | 9 |
10 namespace v8 { | 10 namespace v8 { |
(...skipping 975 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
986 } | 986 } |
987 } | 987 } |
988 } | 988 } |
989 | 989 |
990 | 990 |
991 bool InstructionSelector::IsTailCallAddressImmediate() { return true; } | 991 bool InstructionSelector::IsTailCallAddressImmediate() { return true; } |
992 | 992 |
993 | 993 |
994 namespace { | 994 namespace { |
995 | 995 |
| 996 void VisitCompareWithMemoryOperand(InstructionSelector* selector, |
| 997 InstructionCode opcode, Node* left, |
| 998 InstructionOperand right, |
| 999 FlagsContinuation* cont) { |
| 1000 DCHECK(left->opcode() == IrOpcode::kLoad); |
| 1001 X87OperandGenerator g(selector); |
| 1002 size_t input_count = 0; |
| 1003 InstructionOperand inputs[6]; |
| 1004 AddressingMode addressing_mode = |
| 1005 g.GetEffectiveAddressMemoryOperand(left, inputs, &input_count); |
| 1006 opcode |= AddressingModeField::encode(addressing_mode); |
| 1007 opcode = cont->Encode(opcode); |
| 1008 inputs[input_count++] = right; |
| 1009 |
| 1010 if (cont->IsBranch()) { |
| 1011 inputs[input_count++] = g.Label(cont->true_block()); |
| 1012 inputs[input_count++] = g.Label(cont->false_block()); |
| 1013 selector->Emit(opcode, 0, nullptr, input_count, inputs); |
| 1014 } else { |
| 1015 DCHECK(cont->IsSet()); |
| 1016 InstructionOperand output = g.DefineAsRegister(cont->result()); |
| 1017 selector->Emit(opcode, 1, &output, input_count, inputs); |
| 1018 } |
| 1019 } |
| 1020 |
| 1021 // Determines if {input} of {node} can be replaced by a memory operand. |
| 1022 bool CanUseMemoryOperand(InstructionSelector* selector, InstructionCode opcode, |
| 1023 Node* node, Node* input) { |
| 1024 if (input->opcode() != IrOpcode::kLoad || !selector->CanCover(node, input)) { |
| 1025 return false; |
| 1026 } |
| 1027 MachineRepresentation load_representation = |
| 1028 LoadRepresentationOf(input->op()).representation(); |
| 1029 if (load_representation == MachineRepresentation::kWord32 || |
| 1030 load_representation == MachineRepresentation::kTagged) { |
| 1031 return opcode == kX87Cmp || opcode == kX87Test; |
| 1032 } |
| 1033 return false; |
| 1034 } |
| 1035 |
996 // Shared routine for multiple compare operations. | 1036 // Shared routine for multiple compare operations. |
997 void VisitCompare(InstructionSelector* selector, InstructionCode opcode, | 1037 void VisitCompare(InstructionSelector* selector, InstructionCode opcode, |
998 InstructionOperand left, InstructionOperand right, | 1038 InstructionOperand left, InstructionOperand right, |
999 FlagsContinuation* cont) { | 1039 FlagsContinuation* cont) { |
1000 X87OperandGenerator g(selector); | 1040 X87OperandGenerator g(selector); |
1001 if (cont->IsBranch()) { | 1041 if (cont->IsBranch()) { |
1002 selector->Emit(cont->Encode(opcode), g.NoOutput(), left, right, | 1042 selector->Emit(cont->Encode(opcode), g.NoOutput(), left, right, |
1003 g.Label(cont->true_block()), g.Label(cont->false_block())); | 1043 g.Label(cont->true_block()), g.Label(cont->false_block())); |
1004 } else { | 1044 } else { |
1005 DCHECK(cont->IsSet()); | 1045 DCHECK(cont->IsSet()); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1047 if (cont->IsBranch()) { | 1087 if (cont->IsBranch()) { |
1048 selector->Emit(cont->Encode(kX87Float64Cmp), g.NoOutput(), | 1088 selector->Emit(cont->Encode(kX87Float64Cmp), g.NoOutput(), |
1049 g.Label(cont->true_block()), g.Label(cont->false_block())); | 1089 g.Label(cont->true_block()), g.Label(cont->false_block())); |
1050 } else { | 1090 } else { |
1051 DCHECK(cont->IsSet()); | 1091 DCHECK(cont->IsSet()); |
1052 selector->Emit(cont->Encode(kX87Float64Cmp), | 1092 selector->Emit(cont->Encode(kX87Float64Cmp), |
1053 g.DefineAsByteRegister(cont->result())); | 1093 g.DefineAsByteRegister(cont->result())); |
1054 } | 1094 } |
1055 } | 1095 } |
1056 | 1096 |
1057 | |
1058 // Shared routine for multiple word compare operations. | 1097 // Shared routine for multiple word compare operations. |
1059 void VisitWordCompare(InstructionSelector* selector, Node* node, | 1098 void VisitWordCompare(InstructionSelector* selector, Node* node, |
1060 InstructionCode opcode, FlagsContinuation* cont) { | 1099 InstructionCode opcode, FlagsContinuation* cont) { |
1061 X87OperandGenerator g(selector); | 1100 X87OperandGenerator g(selector); |
1062 Node* const left = node->InputAt(0); | 1101 Node* left = node->InputAt(0); |
1063 Node* const right = node->InputAt(1); | 1102 Node* right = node->InputAt(1); |
1064 | 1103 |
1065 // Match immediates on left or right side of comparison. | 1104 // If one of the two inputs is an immediate, make sure it's on the right. |
| 1105 if (!g.CanBeImmediate(right) && g.CanBeImmediate(left)) { |
| 1106 if (!node->op()->HasProperty(Operator::kCommutative)) cont->Commute(); |
| 1107 std::swap(left, right); |
| 1108 } |
| 1109 |
| 1110 // Match immediates on right side of comparison. |
1066 if (g.CanBeImmediate(right)) { | 1111 if (g.CanBeImmediate(right)) { |
1067 VisitCompare(selector, opcode, g.Use(left), g.UseImmediate(right), cont); | 1112 if (CanUseMemoryOperand(selector, opcode, node, left)) { |
1068 } else if (g.CanBeImmediate(left)) { | 1113 return VisitCompareWithMemoryOperand(selector, opcode, left, |
| 1114 g.UseImmediate(right), cont); |
| 1115 } |
| 1116 return VisitCompare(selector, opcode, g.Use(left), g.UseImmediate(right), |
| 1117 cont); |
| 1118 } |
| 1119 |
| 1120 if (g.CanBeBetterLeftOperand(right)) { |
1069 if (!node->op()->HasProperty(Operator::kCommutative)) cont->Commute(); | 1121 if (!node->op()->HasProperty(Operator::kCommutative)) cont->Commute(); |
1070 VisitCompare(selector, opcode, g.Use(right), g.UseImmediate(left), cont); | 1122 std::swap(left, right); |
1071 } else { | |
1072 VisitCompare(selector, opcode, left, right, cont, | |
1073 node->op()->HasProperty(Operator::kCommutative)); | |
1074 } | 1123 } |
| 1124 |
| 1125 if (CanUseMemoryOperand(selector, opcode, node, left)) { |
| 1126 return VisitCompareWithMemoryOperand(selector, opcode, left, |
| 1127 g.UseRegister(right), cont); |
| 1128 } |
| 1129 return VisitCompare(selector, opcode, left, right, cont, |
| 1130 node->op()->HasProperty(Operator::kCommutative)); |
1075 } | 1131 } |
1076 | 1132 |
1077 | |
1078 void VisitWordCompare(InstructionSelector* selector, Node* node, | 1133 void VisitWordCompare(InstructionSelector* selector, Node* node, |
1079 FlagsContinuation* cont) { | 1134 FlagsContinuation* cont) { |
1080 X87OperandGenerator g(selector); | 1135 X87OperandGenerator g(selector); |
1081 Int32BinopMatcher m(node); | 1136 Int32BinopMatcher m(node); |
1082 if (m.left().IsLoad() && m.right().IsLoadStackPointer()) { | 1137 if (m.left().IsLoad() && m.right().IsLoadStackPointer()) { |
1083 LoadMatcher<ExternalReferenceMatcher> mleft(m.left().node()); | 1138 LoadMatcher<ExternalReferenceMatcher> mleft(m.left().node()); |
1084 ExternalReference js_stack_limit = | 1139 ExternalReference js_stack_limit = |
1085 ExternalReference::address_of_stack_limit(selector->isolate()); | 1140 ExternalReference::address_of_stack_limit(selector->isolate()); |
1086 if (mleft.object().Is(js_stack_limit) && mleft.index().Is(0)) { | 1141 if (mleft.object().Is(js_stack_limit) && mleft.index().Is(0)) { |
1087 // Compare(Load(js_stack_limit), LoadStackPointer) | 1142 // Compare(Load(js_stack_limit), LoadStackPointer) |
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1370 MachineOperatorBuilder::kFloat32RoundTruncate | | 1425 MachineOperatorBuilder::kFloat32RoundTruncate | |
1371 MachineOperatorBuilder::kFloat64RoundTruncate | | 1426 MachineOperatorBuilder::kFloat64RoundTruncate | |
1372 MachineOperatorBuilder::kFloat32RoundTiesEven | | 1427 MachineOperatorBuilder::kFloat32RoundTiesEven | |
1373 MachineOperatorBuilder::kFloat64RoundTiesEven; | 1428 MachineOperatorBuilder::kFloat64RoundTiesEven; |
1374 return flags; | 1429 return flags; |
1375 } | 1430 } |
1376 | 1431 |
1377 } // namespace compiler | 1432 } // namespace compiler |
1378 } // namespace internal | 1433 } // namespace internal |
1379 } // namespace v8 | 1434 } // namespace v8 |
OLD | NEW |