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 966 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
977 } | 977 } |
978 | 978 |
979 | 979 |
980 bool InstructionSelector::IsTailCallAddressImmediate() { return true; } | 980 bool InstructionSelector::IsTailCallAddressImmediate() { return true; } |
981 | 981 |
982 | 982 |
983 namespace { | 983 namespace { |
984 | 984 |
985 // Shared routine for multiple compare operations. | 985 // Shared routine for multiple compare operations. |
986 void VisitCompare(InstructionSelector* selector, InstructionCode opcode, | 986 void VisitCompare(InstructionSelector* selector, InstructionCode opcode, |
987 size_t left_operands_count, InstructionOperand* left_operands, | |
988 InstructionOperand right, FlagsContinuation* cont) { | |
989 DCHECK(left_operands_count > 0 && left_operands_count <= 4); | |
990 IA32OperandGenerator g(selector); | |
991 opcode = cont->Encode(opcode); | |
992 int input_count = 0; | |
993 InstructionOperand inputs[6]; | |
994 do { | |
995 inputs[input_count] = left_operands[input_count]; | |
996 } while (++input_count < left_operands_count); | |
997 inputs[input_count++] = right; | |
998 | |
999 if (cont->IsBranch()) { | |
1000 inputs[input_count++] = g.Label(cont->true_block()); | |
1001 inputs[input_count++] = g.Label(cont->false_block()); | |
1002 selector->Emit(opcode, 0, nullptr, input_count, inputs); | |
1003 } else { | |
1004 DCHECK(cont->IsSet()); | |
1005 InstructionOperand output = g.DefineAsRegister(cont->result()); | |
1006 selector->Emit(opcode, 1, &output, input_count, inputs); | |
1007 } | |
1008 } | |
1009 | |
1010 // Determines if `input' of `node' can be replaced by a memory operand. | |
1011 bool CanUseMemOp(InstructionCode opcode, Node* node, Node* input) { | |
Benedikt Meurer
2016/02/18 05:02:53
Nit: Please use complete workds as in the rest of
epertoso
2016/02/18 10:58:29
Done.
| |
1012 if (input->opcode() == IrOpcode::kLoad && input->OwnedBy(node)) { | |
Benedikt Meurer
2016/02/18 05:02:53
OwnedBy is not enough here. You need to use CanCov
epertoso
2016/02/18 10:58:29
Done. Also added the effect level check.
| |
1013 if (LoadRepresentationOf(input->op()).representation() == | |
1014 MachineRepresentation::kWord32) { | |
1015 return (opcode == kIA32Cmp || opcode == kIA32Test); | |
1016 } | |
1017 } | |
1018 return false; | |
1019 } | |
1020 | |
1021 // Shared routine for multiple compare operations. | |
1022 void VisitCompare(InstructionSelector* selector, InstructionCode opcode, | |
987 InstructionOperand left, InstructionOperand right, | 1023 InstructionOperand left, InstructionOperand right, |
988 FlagsContinuation* cont) { | 1024 FlagsContinuation* cont) { |
989 IA32OperandGenerator g(selector); | 1025 VisitCompare(selector, opcode, 1, &left, right, cont); |
990 if (cont->IsBranch()) { | |
991 selector->Emit(cont->Encode(opcode), g.NoOutput(), left, right, | |
992 g.Label(cont->true_block()), g.Label(cont->false_block())); | |
993 } else { | |
994 DCHECK(cont->IsSet()); | |
995 selector->Emit(cont->Encode(opcode), g.DefineAsByteRegister(cont->result()), | |
996 left, right); | |
997 } | |
998 } | 1026 } |
999 | 1027 |
1000 | 1028 |
1001 // Shared routine for multiple compare operations. | 1029 // Shared routine for multiple compare operations. |
1002 void VisitCompare(InstructionSelector* selector, InstructionCode opcode, | 1030 void VisitCompare(InstructionSelector* selector, InstructionCode opcode, |
1003 Node* left, Node* right, FlagsContinuation* cont, | 1031 Node* left, Node* right, FlagsContinuation* cont, |
1004 bool commutative) { | 1032 bool commutative, Node* node = nullptr) { |
1005 IA32OperandGenerator g(selector); | 1033 IA32OperandGenerator g(selector); |
1006 if (commutative && g.CanBeBetterLeftOperand(right)) { | 1034 if (commutative && g.CanBeBetterLeftOperand(right)) { |
1007 std::swap(left, right); | 1035 std::swap(left, right); |
1008 } | 1036 } |
1009 VisitCompare(selector, opcode, g.UseRegister(left), g.Use(right), cont); | 1037 if (node && CanUseMemOp(opcode, node, left)) { |
Benedikt Meurer
2016/02/18 05:02:53
This is not safe unless you also know that there's
epertoso
2016/02/18 10:58:29
Done in CanUseMemoryOperand.
| |
1038 size_t input_count = 0; | |
1039 InstructionOperand inputs[4]; | |
1040 AddressingMode addressing_mode = | |
1041 g.GetEffectiveAddressMemoryOperand(left, inputs, &input_count); | |
1042 opcode |= AddressingModeField::encode(addressing_mode); | |
1043 VisitCompare(selector, opcode, input_count, inputs, g.Use(right), cont); | |
1044 } else { | |
1045 VisitCompare(selector, opcode, g.UseRegister(left), g.Use(right), cont); | |
1046 } | |
1010 } | 1047 } |
1011 | 1048 |
1012 | 1049 |
1013 // Shared routine for multiple float32 compare operations (inputs commuted). | 1050 // Shared routine for multiple float32 compare operations (inputs commuted). |
1014 void VisitFloat32Compare(InstructionSelector* selector, Node* node, | 1051 void VisitFloat32Compare(InstructionSelector* selector, Node* node, |
1015 FlagsContinuation* cont) { | 1052 FlagsContinuation* cont) { |
1016 Node* const left = node->InputAt(0); | 1053 Node* const left = node->InputAt(0); |
1017 Node* const right = node->InputAt(1); | 1054 Node* const right = node->InputAt(1); |
1018 VisitCompare(selector, kSSEFloat32Cmp, right, left, cont, false); | 1055 VisitCompare(selector, kSSEFloat32Cmp, right, left, cont, false); |
1019 } | 1056 } |
1020 | 1057 |
1021 | 1058 |
1022 // Shared routine for multiple float64 compare operations (inputs commuted). | 1059 // Shared routine for multiple float64 compare operations (inputs commuted). |
1023 void VisitFloat64Compare(InstructionSelector* selector, Node* node, | 1060 void VisitFloat64Compare(InstructionSelector* selector, Node* node, |
1024 FlagsContinuation* cont) { | 1061 FlagsContinuation* cont) { |
1025 Node* const left = node->InputAt(0); | 1062 Node* const left = node->InputAt(0); |
1026 Node* const right = node->InputAt(1); | 1063 Node* const right = node->InputAt(1); |
1027 VisitCompare(selector, kSSEFloat64Cmp, right, left, cont, false); | 1064 VisitCompare(selector, kSSEFloat64Cmp, right, left, cont, false); |
1028 } | 1065 } |
1029 | 1066 |
1030 | 1067 |
1031 // Shared routine for multiple word compare operations. | 1068 // Shared routine for multiple word compare operations. |
1032 void VisitWordCompare(InstructionSelector* selector, Node* node, | 1069 void VisitWordCompare(InstructionSelector* selector, Node* node, |
1033 InstructionCode opcode, FlagsContinuation* cont) { | 1070 InstructionCode opcode, FlagsContinuation* cont) { |
1034 IA32OperandGenerator g(selector); | 1071 IA32OperandGenerator g(selector); |
1035 Node* const left = node->InputAt(0); | 1072 Node* left = node->InputAt(0); |
1036 Node* const right = node->InputAt(1); | 1073 Node* right = node->InputAt(1); |
1037 | 1074 |
1038 // Match immediates on left or right side of comparison. | 1075 if (!g.CanBeImmediate(right) && g.CanBeImmediate(left)) { |
1076 if (!node->op()->HasProperty(Operator::kCommutative)) cont->Commute(); | |
1077 std::swap(left, right); | |
1078 } | |
1079 | |
1080 // Match immediates on right side of comparison. | |
1039 if (g.CanBeImmediate(right)) { | 1081 if (g.CanBeImmediate(right)) { |
1040 VisitCompare(selector, opcode, g.Use(left), g.UseImmediate(right), cont); | 1082 if (CanUseMemOp(opcode, node, left)) { |
1041 } else if (g.CanBeImmediate(left)) { | 1083 size_t left_operands_count = 0; |
1042 if (!node->op()->HasProperty(Operator::kCommutative)) cont->Commute(); | 1084 InstructionOperand left_operands[4]; |
1043 VisitCompare(selector, opcode, g.Use(right), g.UseImmediate(left), cont); | 1085 AddressingMode addressing_mode = g.GetEffectiveAddressMemoryOperand( |
1086 left, left_operands, &left_operands_count); | |
1087 opcode |= AddressingModeField::encode(addressing_mode); | |
1088 VisitCompare(selector, opcode, left_operands_count, left_operands, | |
1089 g.UseImmediate(right), cont); | |
1090 } else { | |
1091 VisitCompare(selector, opcode, g.Use(left), g.UseImmediate(right), cont); | |
1092 } | |
1044 } else { | 1093 } else { |
1045 VisitCompare(selector, opcode, left, right, cont, | 1094 VisitCompare(selector, opcode, left, right, cont, |
1046 node->op()->HasProperty(Operator::kCommutative)); | 1095 node->op()->HasProperty(Operator::kCommutative), node); |
1047 } | 1096 } |
1048 } | 1097 } |
1049 | 1098 |
1050 | 1099 |
1051 void VisitWordCompare(InstructionSelector* selector, Node* node, | 1100 void VisitWordCompare(InstructionSelector* selector, Node* node, |
1052 FlagsContinuation* cont) { | 1101 FlagsContinuation* cont) { |
1053 IA32OperandGenerator g(selector); | 1102 IA32OperandGenerator g(selector); |
1054 Int32BinopMatcher m(node); | 1103 Int32BinopMatcher m(node); |
1055 if (m.left().IsLoad() && m.right().IsLoadStackPointer()) { | 1104 if (m.left().IsLoad() && m.right().IsLoadStackPointer()) { |
1056 LoadMatcher<ExternalReferenceMatcher> mleft(m.left().node()); | 1105 LoadMatcher<ExternalReferenceMatcher> mleft(m.left().node()); |
(...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1350 MachineOperatorBuilder::kFloat64RoundTruncate | | 1399 MachineOperatorBuilder::kFloat64RoundTruncate | |
1351 MachineOperatorBuilder::kFloat32RoundTiesEven | | 1400 MachineOperatorBuilder::kFloat32RoundTiesEven | |
1352 MachineOperatorBuilder::kFloat64RoundTiesEven; | 1401 MachineOperatorBuilder::kFloat64RoundTiesEven; |
1353 } | 1402 } |
1354 return flags; | 1403 return flags; |
1355 } | 1404 } |
1356 | 1405 |
1357 } // namespace compiler | 1406 } // namespace compiler |
1358 } // namespace internal | 1407 } // namespace internal |
1359 } // namespace v8 | 1408 } // namespace v8 |
OLD | NEW |