OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 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 #include "src/s390/frames-s390.h" | 9 #include "src/s390/frames-s390.h" |
10 | 10 |
(...skipping 17 matching lines...) Expand all Loading... |
28 explicit S390OperandGenerator(InstructionSelector* selector) | 28 explicit S390OperandGenerator(InstructionSelector* selector) |
29 : OperandGenerator(selector) {} | 29 : OperandGenerator(selector) {} |
30 | 30 |
31 InstructionOperand UseOperand(Node* node, ImmediateMode mode) { | 31 InstructionOperand UseOperand(Node* node, ImmediateMode mode) { |
32 if (CanBeImmediate(node, mode)) { | 32 if (CanBeImmediate(node, mode)) { |
33 return UseImmediate(node); | 33 return UseImmediate(node); |
34 } | 34 } |
35 return UseRegister(node); | 35 return UseRegister(node); |
36 } | 36 } |
37 | 37 |
| 38 int64_t GetImmediate(Node* node) { |
| 39 if (node->opcode() == IrOpcode::kInt32Constant) |
| 40 return OpParameter<int32_t>(node); |
| 41 else if (node->opcode() == IrOpcode::kInt64Constant) |
| 42 return OpParameter<int64_t>(node); |
| 43 else |
| 44 UNIMPLEMENTED(); |
| 45 return 0L; |
| 46 } |
| 47 |
38 bool CanBeImmediate(Node* node, ImmediateMode mode) { | 48 bool CanBeImmediate(Node* node, ImmediateMode mode) { |
39 int64_t value; | 49 int64_t value; |
40 if (node->opcode() == IrOpcode::kInt32Constant) | 50 if (node->opcode() == IrOpcode::kInt32Constant) |
41 value = OpParameter<int32_t>(node); | 51 value = OpParameter<int32_t>(node); |
42 else if (node->opcode() == IrOpcode::kInt64Constant) | 52 else if (node->opcode() == IrOpcode::kInt64Constant) |
43 value = OpParameter<int64_t>(node); | 53 value = OpParameter<int64_t>(node); |
44 else | 54 else |
45 return false; | 55 return false; |
46 return CanBeImmediate(value, mode); | 56 return CanBeImmediate(value, mode); |
47 } | 57 } |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
125 DCHECK(m.scale() == 0); | 135 DCHECK(m.scale() == 0); |
126 return GenerateMemoryOperandInputs(m.index(), m.base(), m.displacement(), | 136 return GenerateMemoryOperandInputs(m.index(), m.base(), m.displacement(), |
127 m.displacement_mode(), inputs, | 137 m.displacement_mode(), inputs, |
128 input_count); | 138 input_count); |
129 } else { | 139 } else { |
130 inputs[(*input_count)++] = UseRegister(operand->InputAt(0)); | 140 inputs[(*input_count)++] = UseRegister(operand->InputAt(0)); |
131 inputs[(*input_count)++] = UseRegister(operand->InputAt(1)); | 141 inputs[(*input_count)++] = UseRegister(operand->InputAt(1)); |
132 return kMode_MRR; | 142 return kMode_MRR; |
133 } | 143 } |
134 } | 144 } |
| 145 |
| 146 bool CanBeBetterLeftOperand(Node* node) const { |
| 147 return !selector()->IsLive(node); |
| 148 } |
| 149 |
| 150 MachineRepresentation GetRepresentation(Node* node) { |
| 151 return sequence()->GetRepresentation(selector()->GetVirtualRegister(node)); |
| 152 } |
| 153 |
| 154 bool Is64BitOperand(Node* node) { |
| 155 return MachineRepresentation::kWord64 == GetRepresentation(node); |
| 156 } |
135 }; | 157 }; |
136 | 158 |
137 namespace { | 159 namespace { |
138 | 160 |
139 void VisitRR(InstructionSelector* selector, ArchOpcode opcode, Node* node) { | 161 void VisitRR(InstructionSelector* selector, ArchOpcode opcode, Node* node) { |
140 S390OperandGenerator g(selector); | 162 S390OperandGenerator g(selector); |
141 selector->Emit(opcode, g.DefineAsRegister(node), | 163 selector->Emit(opcode, g.DefineAsRegister(node), |
142 g.UseRegister(node->InputAt(0))); | 164 g.UseRegister(node->InputAt(0))); |
143 } | 165 } |
144 | 166 |
(...skipping 30 matching lines...) Expand all Loading... |
175 } | 197 } |
176 #endif | 198 #endif |
177 | 199 |
178 // Shared routine for multiple binary operations. | 200 // Shared routine for multiple binary operations. |
179 template <typename Matcher> | 201 template <typename Matcher> |
180 void VisitBinop(InstructionSelector* selector, Node* node, | 202 void VisitBinop(InstructionSelector* selector, Node* node, |
181 InstructionCode opcode, ImmediateMode operand_mode, | 203 InstructionCode opcode, ImmediateMode operand_mode, |
182 FlagsContinuation* cont) { | 204 FlagsContinuation* cont) { |
183 S390OperandGenerator g(selector); | 205 S390OperandGenerator g(selector); |
184 Matcher m(node); | 206 Matcher m(node); |
| 207 Node* left = m.left().node(); |
| 208 Node* right = m.right().node(); |
185 InstructionOperand inputs[4]; | 209 InstructionOperand inputs[4]; |
186 size_t input_count = 0; | 210 size_t input_count = 0; |
187 InstructionOperand outputs[2]; | 211 InstructionOperand outputs[2]; |
188 size_t output_count = 0; | 212 size_t output_count = 0; |
189 | 213 |
190 inputs[input_count++] = g.UseRegister(m.left().node()); | 214 // TODO(turbofan): match complex addressing modes. |
191 inputs[input_count++] = g.UseOperand(m.right().node(), operand_mode); | 215 if (left == right) { |
| 216 // If both inputs refer to the same operand, enforce allocating a register |
| 217 // for both of them to ensure that we don't end up generating code like |
| 218 // this: |
| 219 // |
| 220 // mov rax, [rbp-0x10] |
| 221 // add rax, [rbp-0x10] |
| 222 // jo label |
| 223 InstructionOperand const input = g.UseRegister(left); |
| 224 inputs[input_count++] = input; |
| 225 inputs[input_count++] = input; |
| 226 } else if (g.CanBeImmediate(right, operand_mode)) { |
| 227 inputs[input_count++] = g.UseRegister(left); |
| 228 inputs[input_count++] = g.UseImmediate(right); |
| 229 } else { |
| 230 if (node->op()->HasProperty(Operator::kCommutative) && |
| 231 g.CanBeBetterLeftOperand(right)) { |
| 232 std::swap(left, right); |
| 233 } |
| 234 inputs[input_count++] = g.UseRegister(left); |
| 235 inputs[input_count++] = g.UseRegister(right); |
| 236 } |
192 | 237 |
193 if (cont->IsBranch()) { | 238 if (cont->IsBranch()) { |
194 inputs[input_count++] = g.Label(cont->true_block()); | 239 inputs[input_count++] = g.Label(cont->true_block()); |
195 inputs[input_count++] = g.Label(cont->false_block()); | 240 inputs[input_count++] = g.Label(cont->false_block()); |
196 } | 241 } |
197 | 242 |
198 if (cont->IsDeoptimize()) { | 243 if (cont->IsDeoptimize()) { |
199 // If we can deoptimize as a result of the binop, we need to make sure that | 244 // If we can deoptimize as a result of the binop, we need to make sure that |
200 // the deopt inputs are not overwritten by the binop result. One way | 245 // the deopt inputs are not overwritten by the binop result. One way |
201 // to achieve that is to declare the output register as same-as-first. | 246 // to achieve that is to declare the output register as same-as-first. |
(...skipping 793 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
995 { | 1040 { |
996 InstructionOperand shift_31 = g.UseImmediate(31); | 1041 InstructionOperand shift_31 = g.UseImmediate(31); |
997 InstructionOperand outputs[] = {temp_operand}; | 1042 InstructionOperand outputs[] = {temp_operand}; |
998 InstructionOperand inputs[] = {result_operand, shift_31}; | 1043 InstructionOperand inputs[] = {result_operand, shift_31}; |
999 selector->Emit(kS390_ShiftRightArith32, 1, outputs, 2, inputs); | 1044 selector->Emit(kS390_ShiftRightArith32, 1, outputs, 2, inputs); |
1000 } | 1045 } |
1001 | 1046 |
1002 VisitCompare(selector, kS390_Cmp32, high32_operand, temp_operand, cont); | 1047 VisitCompare(selector, kS390_Cmp32, high32_operand, temp_operand, cont); |
1003 } | 1048 } |
1004 | 1049 |
| 1050 void VisitMul(InstructionSelector* selector, Node* node, ArchOpcode opcode) { |
| 1051 S390OperandGenerator g(selector); |
| 1052 Int32BinopMatcher m(node); |
| 1053 Node* left = m.left().node(); |
| 1054 Node* right = m.right().node(); |
| 1055 if (g.CanBeImmediate(right, kInt32Imm)) { |
| 1056 selector->Emit(opcode, g.DefineSameAsFirst(node), g.UseRegister(left), |
| 1057 g.UseImmediate(right)); |
| 1058 } else { |
| 1059 if (g.CanBeBetterLeftOperand(right)) { |
| 1060 std::swap(left, right); |
| 1061 } |
| 1062 selector->Emit(opcode, g.DefineSameAsFirst(node), g.UseRegister(left), |
| 1063 g.Use(right)); |
| 1064 } |
| 1065 } |
| 1066 |
1005 } // namespace | 1067 } // namespace |
1006 | 1068 |
| 1069 void InstructionSelector::VisitInt32MulWithOverflow(Node* node) { |
| 1070 if (Node* ovf = NodeProperties::FindProjection(node, 1)) { |
| 1071 FlagsContinuation cont = FlagsContinuation::ForSet(kNotEqual, ovf); |
| 1072 return EmitInt32MulWithOverflow(this, node, &cont); |
| 1073 } |
| 1074 VisitMul(this, node, kS390_Mul32); |
| 1075 // FlagsContinuation cont; |
| 1076 // EmitInt32MulWithOverflow(this, node, &cont); |
| 1077 } |
| 1078 |
1007 void InstructionSelector::VisitInt32Mul(Node* node) { | 1079 void InstructionSelector::VisitInt32Mul(Node* node) { |
1008 VisitRRR(this, kS390_Mul32, node); | 1080 S390OperandGenerator g(this); |
| 1081 Int32BinopMatcher m(node); |
| 1082 Node* left = m.left().node(); |
| 1083 Node* right = m.right().node(); |
| 1084 if (g.CanBeImmediate(right, kInt32Imm) && |
| 1085 base::bits::IsPowerOfTwo32(g.GetImmediate(right))) { |
| 1086 int power = 31 - base::bits::CountLeadingZeros32(g.GetImmediate(right)); |
| 1087 Emit(kS390_ShiftLeft32, g.DefineSameAsFirst(node), g.UseRegister(left), |
| 1088 g.UseImmediate(power)); |
| 1089 return; |
| 1090 } |
| 1091 VisitMul(this, node, kS390_Mul32); |
1009 } | 1092 } |
1010 | 1093 |
1011 #if V8_TARGET_ARCH_S390X | 1094 #if V8_TARGET_ARCH_S390X |
1012 void InstructionSelector::VisitInt64Mul(Node* node) { | 1095 void InstructionSelector::VisitInt64Mul(Node* node) { |
1013 VisitRRR(this, kS390_Mul64, node); | 1096 S390OperandGenerator g(this); |
| 1097 Int64BinopMatcher m(node); |
| 1098 Node* left = m.left().node(); |
| 1099 Node* right = m.right().node(); |
| 1100 if (g.CanBeImmediate(right, kInt32Imm) && |
| 1101 base::bits::IsPowerOfTwo64(g.GetImmediate(right))) { |
| 1102 int power = 31 - base::bits::CountLeadingZeros64(g.GetImmediate(right)); |
| 1103 Emit(kS390_ShiftLeft64, g.DefineSameAsFirst(node), g.UseRegister(left), |
| 1104 g.UseImmediate(power)); |
| 1105 return; |
| 1106 } |
| 1107 VisitMul(this, node, kS390_Mul64); |
1014 } | 1108 } |
1015 #endif | 1109 #endif |
1016 | 1110 |
1017 void InstructionSelector::VisitInt32MulHigh(Node* node) { | 1111 void InstructionSelector::VisitInt32MulHigh(Node* node) { |
1018 S390OperandGenerator g(this); | 1112 S390OperandGenerator g(this); |
1019 Emit(kS390_MulHigh32, g.DefineAsRegister(node), | 1113 Int32BinopMatcher m(node); |
1020 g.UseRegister(node->InputAt(0)), g.UseRegister(node->InputAt(1))); | 1114 Node* left = m.left().node(); |
| 1115 Node* right = m.right().node(); |
| 1116 if (g.CanBeBetterLeftOperand(right)) { |
| 1117 std::swap(left, right); |
| 1118 } |
| 1119 Emit(kS390_MulHigh32, g.DefineAsRegister(node), g.UseRegister(left), |
| 1120 g.Use(right)); |
1021 } | 1121 } |
1022 | 1122 |
1023 void InstructionSelector::VisitUint32MulHigh(Node* node) { | 1123 void InstructionSelector::VisitUint32MulHigh(Node* node) { |
1024 S390OperandGenerator g(this); | 1124 S390OperandGenerator g(this); |
1025 Emit(kS390_MulHighU32, g.DefineAsRegister(node), | 1125 Int32BinopMatcher m(node); |
1026 g.UseRegister(node->InputAt(0)), g.UseRegister(node->InputAt(1))); | 1126 Node* left = m.left().node(); |
| 1127 Node* right = m.right().node(); |
| 1128 if (g.CanBeBetterLeftOperand(right)) { |
| 1129 std::swap(left, right); |
| 1130 } |
| 1131 Emit(kS390_MulHighU32, g.DefineAsRegister(node), g.UseRegister(left), |
| 1132 g.Use(right)); |
1027 } | 1133 } |
1028 | 1134 |
1029 void InstructionSelector::VisitInt32Div(Node* node) { | 1135 void InstructionSelector::VisitInt32Div(Node* node) { |
1030 VisitRRR(this, kS390_Div32, node); | 1136 VisitRRR(this, kS390_Div32, node); |
1031 } | 1137 } |
1032 | 1138 |
1033 #if V8_TARGET_ARCH_S390X | 1139 #if V8_TARGET_ARCH_S390X |
1034 void InstructionSelector::VisitInt64Div(Node* node) { | 1140 void InstructionSelector::VisitInt64Div(Node* node) { |
1035 VisitRRR(this, kS390_Div64, node); | 1141 VisitRRR(this, kS390_Div64, node); |
1036 } | 1142 } |
(...skipping 677 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1714 VisitWord64Compare(this, node, &cont); | 1820 VisitWord64Compare(this, node, &cont); |
1715 } | 1821 } |
1716 | 1822 |
1717 void InstructionSelector::VisitUint64LessThanOrEqual(Node* node) { | 1823 void InstructionSelector::VisitUint64LessThanOrEqual(Node* node) { |
1718 FlagsContinuation cont = | 1824 FlagsContinuation cont = |
1719 FlagsContinuation::ForSet(kUnsignedLessThanOrEqual, node); | 1825 FlagsContinuation::ForSet(kUnsignedLessThanOrEqual, node); |
1720 VisitWord64Compare(this, node, &cont); | 1826 VisitWord64Compare(this, node, &cont); |
1721 } | 1827 } |
1722 #endif | 1828 #endif |
1723 | 1829 |
1724 void InstructionSelector::VisitInt32MulWithOverflow(Node* node) { | |
1725 if (Node* ovf = NodeProperties::FindProjection(node, 1)) { | |
1726 FlagsContinuation cont = FlagsContinuation::ForSet(kNotEqual, ovf); | |
1727 return EmitInt32MulWithOverflow(this, node, &cont); | |
1728 } | |
1729 FlagsContinuation cont; | |
1730 EmitInt32MulWithOverflow(this, node, &cont); | |
1731 } | |
1732 | |
1733 void InstructionSelector::VisitFloat32Equal(Node* node) { | 1830 void InstructionSelector::VisitFloat32Equal(Node* node) { |
1734 FlagsContinuation cont = FlagsContinuation::ForSet(kEqual, node); | 1831 FlagsContinuation cont = FlagsContinuation::ForSet(kEqual, node); |
1735 VisitFloat32Compare(this, node, &cont); | 1832 VisitFloat32Compare(this, node, &cont); |
1736 } | 1833 } |
1737 | 1834 |
1738 void InstructionSelector::VisitFloat32LessThan(Node* node) { | 1835 void InstructionSelector::VisitFloat32LessThan(Node* node) { |
1739 FlagsContinuation cont = FlagsContinuation::ForSet(kUnsignedLessThan, node); | 1836 FlagsContinuation cont = FlagsContinuation::ForSet(kUnsignedLessThan, node); |
1740 VisitFloat32Compare(this, node, &cont); | 1837 VisitFloat32Compare(this, node, &cont); |
1741 } | 1838 } |
1742 | 1839 |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1921 // static | 2018 // static |
1922 MachineOperatorBuilder::AlignmentRequirements | 2019 MachineOperatorBuilder::AlignmentRequirements |
1923 InstructionSelector::AlignmentRequirements() { | 2020 InstructionSelector::AlignmentRequirements() { |
1924 return MachineOperatorBuilder::AlignmentRequirements:: | 2021 return MachineOperatorBuilder::AlignmentRequirements:: |
1925 FullUnalignedAccessSupport(); | 2022 FullUnalignedAccessSupport(); |
1926 } | 2023 } |
1927 | 2024 |
1928 } // namespace compiler | 2025 } // namespace compiler |
1929 } // namespace internal | 2026 } // namespace internal |
1930 } // namespace v8 | 2027 } // namespace v8 |
OLD | NEW |