| 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 971 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 982 } | 982 } |
| 983 } | 983 } |
| 984 } | 984 } |
| 985 | 985 |
| 986 | 986 |
| 987 bool InstructionSelector::IsTailCallAddressImmediate() { return true; } | 987 bool InstructionSelector::IsTailCallAddressImmediate() { return true; } |
| 988 | 988 |
| 989 | 989 |
| 990 namespace { | 990 namespace { |
| 991 | 991 |
| 992 void VisitCompareWithMemoryOperand(InstructionSelector* selector, |
| 993 InstructionCode opcode, Node* left, |
| 994 InstructionOperand right, |
| 995 FlagsContinuation* cont) { |
| 996 DCHECK(left->opcode() == IrOpcode::kLoad); |
| 997 IA32OperandGenerator g(selector); |
| 998 size_t input_count = 0; |
| 999 InstructionOperand inputs[6]; |
| 1000 AddressingMode addressing_mode = |
| 1001 g.GetEffectiveAddressMemoryOperand(left, inputs, &input_count); |
| 1002 opcode |= AddressingModeField::encode(addressing_mode); |
| 1003 opcode = cont->Encode(opcode); |
| 1004 inputs[input_count++] = right; |
| 1005 |
| 1006 if (cont->IsBranch()) { |
| 1007 inputs[input_count++] = g.Label(cont->true_block()); |
| 1008 inputs[input_count++] = g.Label(cont->false_block()); |
| 1009 selector->Emit(opcode, 0, nullptr, input_count, inputs); |
| 1010 } else { |
| 1011 DCHECK(cont->IsSet()); |
| 1012 InstructionOperand output = g.DefineAsRegister(cont->result()); |
| 1013 selector->Emit(opcode, 1, &output, input_count, inputs); |
| 1014 } |
| 1015 } |
| 1016 |
| 1017 // Determines if {input} of {node} can be replaced by a memory operand. |
| 1018 bool CanUseMemoryOperand(InstructionSelector* selector, InstructionCode opcode, |
| 1019 Node* node, Node* input) { |
| 1020 if (input->opcode() != IrOpcode::kLoad || !selector->CanCover(node, input)) { |
| 1021 return false; |
| 1022 } |
| 1023 if (LoadRepresentationOf(input->op()).representation() == |
| 1024 MachineRepresentation::kWord32) { |
| 1025 return opcode == kIA32Cmp || opcode == kIA32Test; |
| 1026 } |
| 1027 return false; |
| 1028 } |
| 1029 |
| 992 // Shared routine for multiple compare operations. | 1030 // Shared routine for multiple compare operations. |
| 993 void VisitCompare(InstructionSelector* selector, InstructionCode opcode, | 1031 void VisitCompare(InstructionSelector* selector, InstructionCode opcode, |
| 994 InstructionOperand left, InstructionOperand right, | 1032 InstructionOperand left, InstructionOperand right, |
| 995 FlagsContinuation* cont) { | 1033 FlagsContinuation* cont) { |
| 996 IA32OperandGenerator g(selector); | 1034 IA32OperandGenerator g(selector); |
| 997 if (cont->IsBranch()) { | 1035 if (cont->IsBranch()) { |
| 998 selector->Emit(cont->Encode(opcode), g.NoOutput(), left, right, | 1036 selector->Emit(cont->Encode(opcode), g.NoOutput(), left, right, |
| 999 g.Label(cont->true_block()), g.Label(cont->false_block())); | 1037 g.Label(cont->true_block()), g.Label(cont->false_block())); |
| 1000 } else { | 1038 } else { |
| 1001 DCHECK(cont->IsSet()); | 1039 DCHECK(cont->IsSet()); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1037 | 1075 |
| 1038 // Shared routine for multiple word compare operations. | 1076 // Shared routine for multiple word compare operations. |
| 1039 void VisitWordCompare(InstructionSelector* selector, Node* node, | 1077 void VisitWordCompare(InstructionSelector* selector, Node* node, |
| 1040 InstructionCode opcode, FlagsContinuation* cont) { | 1078 InstructionCode opcode, FlagsContinuation* cont) { |
| 1041 IA32OperandGenerator g(selector); | 1079 IA32OperandGenerator g(selector); |
| 1042 Node* const left = node->InputAt(0); | 1080 Node* const left = node->InputAt(0); |
| 1043 Node* const right = node->InputAt(1); | 1081 Node* const right = node->InputAt(1); |
| 1044 | 1082 |
| 1045 // Match immediates on left or right side of comparison. | 1083 // Match immediates on left or right side of comparison. |
| 1046 if (g.CanBeImmediate(right)) { | 1084 if (g.CanBeImmediate(right)) { |
| 1047 VisitCompare(selector, opcode, g.Use(left), g.UseImmediate(right), cont); | 1085 return VisitCompare(selector, opcode, g.Use(left), g.UseImmediate(right), |
| 1086 cont); |
| 1048 } else if (g.CanBeImmediate(left)) { | 1087 } else if (g.CanBeImmediate(left)) { |
| 1049 if (!node->op()->HasProperty(Operator::kCommutative)) cont->Commute(); | 1088 if (!node->op()->HasProperty(Operator::kCommutative)) cont->Commute(); |
| 1050 VisitCompare(selector, opcode, g.Use(right), g.UseImmediate(left), cont); | 1089 return VisitCompare(selector, opcode, g.Use(right), g.UseImmediate(left), |
| 1051 } else { | 1090 cont); |
| 1052 VisitCompare(selector, opcode, left, right, cont, | |
| 1053 node->op()->HasProperty(Operator::kCommutative)); | |
| 1054 } | 1091 } |
| 1092 // TODO(epertoso): emit memory operands for comparisons againt immediates as |
| 1093 // well. |
| 1094 if (CanUseMemoryOperand(selector, opcode, node, left)) { |
| 1095 return VisitCompareWithMemoryOperand(selector, opcode, left, |
| 1096 g.UseRegister(right), cont); |
| 1097 } |
| 1098 return VisitCompare(selector, opcode, left, right, cont, |
| 1099 node->op()->HasProperty(Operator::kCommutative)); |
| 1055 } | 1100 } |
| 1056 | 1101 |
| 1057 | |
| 1058 void VisitWordCompare(InstructionSelector* selector, Node* node, | 1102 void VisitWordCompare(InstructionSelector* selector, Node* node, |
| 1059 FlagsContinuation* cont) { | 1103 FlagsContinuation* cont) { |
| 1060 IA32OperandGenerator g(selector); | 1104 IA32OperandGenerator g(selector); |
| 1061 Int32BinopMatcher m(node); | 1105 Int32BinopMatcher m(node); |
| 1062 if (m.left().IsLoad() && m.right().IsLoadStackPointer()) { | 1106 if (m.left().IsLoad() && m.right().IsLoadStackPointer()) { |
| 1063 LoadMatcher<ExternalReferenceMatcher> mleft(m.left().node()); | 1107 LoadMatcher<ExternalReferenceMatcher> mleft(m.left().node()); |
| 1064 ExternalReference js_stack_limit = | 1108 ExternalReference js_stack_limit = |
| 1065 ExternalReference::address_of_stack_limit(selector->isolate()); | 1109 ExternalReference::address_of_stack_limit(selector->isolate()); |
| 1066 if (mleft.object().Is(js_stack_limit) && mleft.index().Is(0)) { | 1110 if (mleft.object().Is(js_stack_limit) && mleft.index().Is(0)) { |
| 1067 // Compare(Load(js_stack_limit), LoadStackPointer) | 1111 // Compare(Load(js_stack_limit), LoadStackPointer) |
| (...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1357 MachineOperatorBuilder::kFloat64RoundTruncate | | 1401 MachineOperatorBuilder::kFloat64RoundTruncate | |
| 1358 MachineOperatorBuilder::kFloat32RoundTiesEven | | 1402 MachineOperatorBuilder::kFloat32RoundTiesEven | |
| 1359 MachineOperatorBuilder::kFloat64RoundTiesEven; | 1403 MachineOperatorBuilder::kFloat64RoundTiesEven; |
| 1360 } | 1404 } |
| 1361 return flags; | 1405 return flags; |
| 1362 } | 1406 } |
| 1363 | 1407 |
| 1364 } // namespace compiler | 1408 } // namespace compiler |
| 1365 } // namespace internal | 1409 } // namespace internal |
| 1366 } // namespace v8 | 1410 } // namespace v8 |
| OLD | NEW |