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 |
11 namespace v8 { | 11 namespace v8 { |
12 namespace internal { | 12 namespace internal { |
13 namespace compiler { | 13 namespace compiler { |
14 | 14 |
15 enum ImmediateMode { | 15 enum class OperandMode : uint32_t { |
16 kShift32Imm, | 16 kNone = 0u, |
17 kShift64Imm, | 17 // Immediate mode |
18 kInt32Imm, | 18 kShift32Imm = 1u << 0, |
19 kInt32Imm_Negate, | 19 kShift64Imm = 1u << 1, |
20 kUint32Imm, | 20 kInt32Imm = 1u << 2, |
21 kInt20Imm, | 21 kInt32Imm_Negate = 1u << 3, |
22 kNoImmediate | 22 kUint32Imm = 1u << 4, |
| 23 kInt20Imm = 1u << 5, |
| 24 // Instr format |
| 25 kAllowRRR = 1u << 7, |
| 26 kAllowRM = 1u << 8, |
| 27 kAllowRI = 1u << 9, |
| 28 kAllowRRI = 1u << 10, |
| 29 kAllowRRM = 1u << 11, |
| 30 // Useful combination |
| 31 kAllowImmediate = kAllowRI | kAllowRRI, |
| 32 kAllowMemoryOperand = kAllowRM | kAllowRRM, |
| 33 kAllowDistinctOps = kAllowRRR | kAllowRRI | kAllowRRM, |
| 34 kBitWiseCommonMode = kAllowRI | kUint32Imm, |
| 35 kArithmeticCommonMode = kAllowRM | kAllowRI |
23 }; | 36 }; |
24 | 37 |
| 38 typedef base::Flags<OperandMode, uint32_t> OperandModes; |
| 39 DEFINE_OPERATORS_FOR_FLAGS(OperandModes); |
| 40 OperandModes immediateModeMask = |
| 41 OperandMode::kShift32Imm | OperandMode::kShift64Imm | |
| 42 OperandMode::kInt32Imm | OperandMode::kInt32Imm_Negate | |
| 43 OperandMode::kUint32Imm | OperandMode::kInt20Imm; |
| 44 |
| 45 #define BitWiseOperandMode \ |
| 46 ((OperandMode::kBitWiseCommonMode | \ |
| 47 (CpuFeatures::IsSupported(DISTINCT_OPS) \ |
| 48 ? OperandMode::kAllowRRR \ |
| 49 : OperandMode::kBitWiseCommonMode))) |
| 50 #define AddOperandMode \ |
| 51 ((OperandMode::kArithmeticCommonMode | OperandMode::kInt32Imm | \ |
| 52 (CpuFeatures::IsSupported(DISTINCT_OPS) \ |
| 53 ? (OperandMode::kAllowRRR | OperandMode::kAllowRRI) \ |
| 54 : OperandMode::kArithmeticCommonMode))) |
| 55 #define SubOperandMode \ |
| 56 ((OperandMode::kArithmeticCommonMode | OperandMode::kInt32Imm_Negate | \ |
| 57 (CpuFeatures::IsSupported(DISTINCT_OPS) \ |
| 58 ? (OperandMode::kAllowRRR | OperandMode::kAllowRRI) \ |
| 59 : OperandMode::kArithmeticCommonMode))) |
| 60 #define MulOperandMode \ |
| 61 (OperandMode::kArithmeticCommonMode | OperandMode::kInt32Imm) |
| 62 |
25 // Adds S390-specific methods for generating operands. | 63 // Adds S390-specific methods for generating operands. |
26 class S390OperandGenerator final : public OperandGenerator { | 64 class S390OperandGenerator final : public OperandGenerator { |
27 public: | 65 public: |
28 explicit S390OperandGenerator(InstructionSelector* selector) | 66 explicit S390OperandGenerator(InstructionSelector* selector) |
29 : OperandGenerator(selector) {} | 67 : OperandGenerator(selector) {} |
30 | 68 |
31 InstructionOperand UseOperand(Node* node, ImmediateMode mode) { | 69 InstructionOperand UseOperand(Node* node, OperandModes mode) { |
32 if (CanBeImmediate(node, mode)) { | 70 if (CanBeImmediate(node, mode)) { |
33 return UseImmediate(node); | 71 return UseImmediate(node); |
34 } | 72 } |
35 return UseRegister(node); | 73 return UseRegister(node); |
36 } | 74 } |
37 | 75 |
38 int64_t GetImmediate(Node* node) { | 76 int64_t GetImmediate(Node* node) { |
39 if (node->opcode() == IrOpcode::kInt32Constant) | 77 if (node->opcode() == IrOpcode::kInt32Constant) |
40 return OpParameter<int32_t>(node); | 78 return OpParameter<int32_t>(node); |
41 else if (node->opcode() == IrOpcode::kInt64Constant) | 79 else if (node->opcode() == IrOpcode::kInt64Constant) |
42 return OpParameter<int64_t>(node); | 80 return OpParameter<int64_t>(node); |
43 else | 81 else |
44 UNIMPLEMENTED(); | 82 UNIMPLEMENTED(); |
45 return 0L; | 83 return 0L; |
46 } | 84 } |
47 | 85 |
48 bool CanBeImmediate(Node* node, ImmediateMode mode) { | 86 bool CanBeImmediate(Node* node, OperandModes mode) { |
49 int64_t value; | 87 int64_t value; |
50 if (node->opcode() == IrOpcode::kInt32Constant) | 88 if (node->opcode() == IrOpcode::kInt32Constant) |
51 value = OpParameter<int32_t>(node); | 89 value = OpParameter<int32_t>(node); |
52 else if (node->opcode() == IrOpcode::kInt64Constant) | 90 else if (node->opcode() == IrOpcode::kInt64Constant) |
53 value = OpParameter<int64_t>(node); | 91 value = OpParameter<int64_t>(node); |
54 else | 92 else |
55 return false; | 93 return false; |
56 return CanBeImmediate(value, mode); | 94 return CanBeImmediate(value, mode); |
57 } | 95 } |
58 | 96 |
59 bool CanBeImmediate(int64_t value, ImmediateMode mode) { | 97 bool CanBeImmediate(int64_t value, OperandModes mode) { |
60 switch (mode) { | 98 if (mode & OperandMode::kShift32Imm) |
61 case kShift32Imm: | 99 return 0 <= value && value < 32; |
62 return 0 <= value && value < 32; | 100 else if (mode & OperandMode::kShift64Imm) |
63 case kShift64Imm: | 101 return 0 <= value && value < 64; |
64 return 0 <= value && value < 64; | 102 else if (mode & OperandMode::kInt32Imm) |
65 case kInt32Imm: | 103 return is_int32(value); |
66 return is_int32(value); | 104 else if (mode & OperandMode::kInt32Imm_Negate) |
67 case kInt32Imm_Negate: | 105 return is_int32(-value); |
68 return is_int32(-value); | 106 else if (mode & OperandMode::kUint32Imm) |
69 case kUint32Imm: | 107 return is_uint32(value); |
70 return is_uint32(value); | 108 else if (mode & OperandMode::kInt20Imm) |
71 case kInt20Imm: | 109 return is_int20(value); |
72 return is_int20(value); | 110 else |
73 case kNoImmediate: | 111 return false; |
74 return false; | |
75 } | |
76 return false; | |
77 } | 112 } |
78 | 113 |
79 AddressingMode GenerateMemoryOperandInputs(Node* index, Node* base, | 114 AddressingMode GenerateMemoryOperandInputs(Node* index, Node* base, |
80 Node* displacement, | 115 Node* displacement, |
81 DisplacementMode displacement_mode, | 116 DisplacementMode displacement_mode, |
82 InstructionOperand inputs[], | 117 InstructionOperand inputs[], |
83 size_t* input_count) { | 118 size_t* input_count) { |
84 AddressingMode mode = kMode_MRI; | 119 AddressingMode mode = kMode_MRI; |
85 if (base != nullptr) { | 120 if (base != nullptr) { |
86 inputs[(*input_count)++] = UseRegister(base); | 121 inputs[(*input_count)++] = UseRegister(base); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
124 size_t* input_count) { | 159 size_t* input_count) { |
125 #if V8_TARGET_ARCH_S390X | 160 #if V8_TARGET_ARCH_S390X |
126 BaseWithIndexAndDisplacement64Matcher m(operand, | 161 BaseWithIndexAndDisplacement64Matcher m(operand, |
127 AddressOption::kAllowInputSwap); | 162 AddressOption::kAllowInputSwap); |
128 #else | 163 #else |
129 BaseWithIndexAndDisplacement32Matcher m(operand, | 164 BaseWithIndexAndDisplacement32Matcher m(operand, |
130 AddressOption::kAllowInputSwap); | 165 AddressOption::kAllowInputSwap); |
131 #endif | 166 #endif |
132 DCHECK(m.matches()); | 167 DCHECK(m.matches()); |
133 if ((m.displacement() == nullptr || | 168 if ((m.displacement() == nullptr || |
134 CanBeImmediate(m.displacement(), kInt20Imm))) { | 169 CanBeImmediate(m.displacement(), OperandMode::kInt20Imm))) { |
135 DCHECK(m.scale() == 0); | 170 DCHECK(m.scale() == 0); |
136 return GenerateMemoryOperandInputs(m.index(), m.base(), m.displacement(), | 171 return GenerateMemoryOperandInputs(m.index(), m.base(), m.displacement(), |
137 m.displacement_mode(), inputs, | 172 m.displacement_mode(), inputs, |
138 input_count); | 173 input_count); |
139 } else { | 174 } else { |
140 inputs[(*input_count)++] = UseRegister(operand->InputAt(0)); | 175 inputs[(*input_count)++] = UseRegister(operand->InputAt(0)); |
141 inputs[(*input_count)++] = UseRegister(operand->InputAt(1)); | 176 inputs[(*input_count)++] = UseRegister(operand->InputAt(1)); |
142 return kMode_MRR; | 177 return kMode_MRR; |
143 } | 178 } |
144 } | 179 } |
145 | 180 |
146 bool CanBeBetterLeftOperand(Node* node) const { | 181 bool CanBeBetterLeftOperand(Node* node) const { |
147 return !selector()->IsLive(node); | 182 return !selector()->IsLive(node); |
148 } | 183 } |
149 | 184 |
150 MachineRepresentation GetRepresentation(Node* node) { | 185 MachineRepresentation GetRepresentation(Node* node) { |
151 return sequence()->GetRepresentation(selector()->GetVirtualRegister(node)); | 186 return sequence()->GetRepresentation(selector()->GetVirtualRegister(node)); |
152 } | 187 } |
153 | 188 |
154 bool Is64BitOperand(Node* node) { | 189 bool Is64BitOperand(Node* node) { |
155 return MachineRepresentation::kWord64 == GetRepresentation(node); | 190 return MachineRepresentation::kWord64 == GetRepresentation(node); |
156 } | 191 } |
157 }; | 192 }; |
158 | 193 |
159 namespace { | 194 namespace { |
160 | 195 |
| 196 ArchOpcode SelectLoadOpcode(Node* node) { |
| 197 NodeMatcher m(node); |
| 198 DCHECK(m.IsLoad()); |
| 199 LoadRepresentation load_rep = LoadRepresentationOf(node->op()); |
| 200 ArchOpcode opcode = kArchNop; |
| 201 switch (load_rep.representation()) { |
| 202 case MachineRepresentation::kFloat32: |
| 203 opcode = kS390_LoadFloat32; |
| 204 break; |
| 205 case MachineRepresentation::kFloat64: |
| 206 opcode = kS390_LoadDouble; |
| 207 break; |
| 208 case MachineRepresentation::kBit: // Fall through. |
| 209 case MachineRepresentation::kWord8: |
| 210 opcode = load_rep.IsSigned() ? kS390_LoadWordS8 : kS390_LoadWordU8; |
| 211 break; |
| 212 case MachineRepresentation::kWord16: |
| 213 opcode = load_rep.IsSigned() ? kS390_LoadWordS16 : kS390_LoadWordU16; |
| 214 break; |
| 215 #if !V8_TARGET_ARCH_S390X |
| 216 case MachineRepresentation::kTaggedSigned: // Fall through. |
| 217 case MachineRepresentation::kTaggedPointer: // Fall through. |
| 218 case MachineRepresentation::kTagged: // Fall through. |
| 219 #endif |
| 220 case MachineRepresentation::kWord32: |
| 221 opcode = kS390_LoadWordU32; |
| 222 break; |
| 223 #if V8_TARGET_ARCH_S390X |
| 224 case MachineRepresentation::kTaggedSigned: // Fall through. |
| 225 case MachineRepresentation::kTaggedPointer: // Fall through. |
| 226 case MachineRepresentation::kTagged: // Fall through. |
| 227 case MachineRepresentation::kWord64: |
| 228 opcode = kS390_LoadWord64; |
| 229 break; |
| 230 #else |
| 231 case MachineRepresentation::kWord64: // Fall through. |
| 232 #endif |
| 233 case MachineRepresentation::kSimd128: // Fall through. |
| 234 case MachineRepresentation::kNone: |
| 235 default: |
| 236 UNREACHABLE(); |
| 237 } |
| 238 return opcode; |
| 239 } |
| 240 |
| 241 bool AutoZeroExtendsWord32ToWord64(Node* node) { |
| 242 #if !V8_TARGET_ARCH_S390X |
| 243 return true; |
| 244 #else |
| 245 switch (node->opcode()) { |
| 246 case IrOpcode::kInt32Div: |
| 247 case IrOpcode::kUint32Div: |
| 248 case IrOpcode::kInt32MulHigh: |
| 249 case IrOpcode::kInt32Mod: |
| 250 case IrOpcode::kUint32Mod: |
| 251 return true; |
| 252 default: |
| 253 return false; |
| 254 } |
| 255 return false; |
| 256 #endif |
| 257 } |
| 258 |
| 259 bool ZeroExtendsWord32ToWord64(Node* node) { |
| 260 #if !V8_TARGET_ARCH_S390X |
| 261 return true; |
| 262 #else |
| 263 switch (node->opcode()) { |
| 264 case IrOpcode::kInt32Add: |
| 265 case IrOpcode::kInt32Sub: |
| 266 case IrOpcode::kWord32And: |
| 267 case IrOpcode::kWord32Or: |
| 268 case IrOpcode::kWord32Xor: |
| 269 case IrOpcode::kWord32Shl: |
| 270 case IrOpcode::kWord32Shr: |
| 271 case IrOpcode::kWord32Sar: |
| 272 case IrOpcode::kInt32Mul: |
| 273 case IrOpcode::kWord32Ror: |
| 274 case IrOpcode::kInt32Div: |
| 275 case IrOpcode::kUint32Div: |
| 276 case IrOpcode::kInt32MulHigh: |
| 277 case IrOpcode::kInt32Mod: |
| 278 case IrOpcode::kUint32Mod: |
| 279 return true; |
| 280 // TODO(john.yan): consider the following case to be valid |
| 281 // case IrOpcode::kWord32Equal: |
| 282 // case IrOpcode::kInt32LessThan: |
| 283 // case IrOpcode::kInt32LessThanOrEqual: |
| 284 // case IrOpcode::kUint32LessThan: |
| 285 // case IrOpcode::kUint32LessThanOrEqual: |
| 286 // case IrOpcode::kUint32MulHigh: |
| 287 // // These 32-bit operations implicitly zero-extend to 64-bit on x64, so |
| 288 // the |
| 289 // // zero-extension is a no-op. |
| 290 // return true; |
| 291 // case IrOpcode::kProjection: { |
| 292 // Node* const value = node->InputAt(0); |
| 293 // switch (value->opcode()) { |
| 294 // case IrOpcode::kInt32AddWithOverflow: |
| 295 // case IrOpcode::kInt32SubWithOverflow: |
| 296 // case IrOpcode::kInt32MulWithOverflow: |
| 297 // return true; |
| 298 // default: |
| 299 // return false; |
| 300 // } |
| 301 // } |
| 302 case IrOpcode::kLoad: { |
| 303 LoadRepresentation load_rep = LoadRepresentationOf(node->op()); |
| 304 switch (load_rep.representation()) { |
| 305 case MachineRepresentation::kWord32: |
| 306 return true; |
| 307 default: |
| 308 return false; |
| 309 } |
| 310 } |
| 311 default: |
| 312 return false; |
| 313 } |
| 314 #endif |
| 315 } |
| 316 |
161 void VisitRR(InstructionSelector* selector, ArchOpcode opcode, Node* node) { | 317 void VisitRR(InstructionSelector* selector, ArchOpcode opcode, Node* node) { |
162 S390OperandGenerator g(selector); | 318 S390OperandGenerator g(selector); |
163 selector->Emit(opcode, g.DefineAsRegister(node), | 319 selector->Emit(opcode, g.DefineAsRegister(node), |
164 g.UseRegister(node->InputAt(0))); | 320 g.UseRegister(node->InputAt(0))); |
165 } | 321 } |
166 | 322 |
167 void VisitRRR(InstructionSelector* selector, ArchOpcode opcode, Node* node) { | 323 void VisitRRR(InstructionSelector* selector, ArchOpcode opcode, Node* node) { |
168 S390OperandGenerator g(selector); | 324 S390OperandGenerator g(selector); |
169 selector->Emit(opcode, g.DefineAsRegister(node), | 325 selector->Emit(opcode, g.DefineAsRegister(node), |
170 g.UseRegister(node->InputAt(0)), | 326 g.UseRegister(node->InputAt(0)), |
171 g.UseRegister(node->InputAt(1))); | 327 g.UseRegister(node->InputAt(1))); |
172 } | 328 } |
173 | 329 |
| 330 #if V8_TARGET_ARCH_S390X |
174 void VisitRRO(InstructionSelector* selector, ArchOpcode opcode, Node* node, | 331 void VisitRRO(InstructionSelector* selector, ArchOpcode opcode, Node* node, |
175 ImmediateMode operand_mode) { | 332 OperandModes operand_mode) { |
176 S390OperandGenerator g(selector); | 333 S390OperandGenerator g(selector); |
177 selector->Emit(opcode, g.DefineAsRegister(node), | 334 selector->Emit(opcode, g.DefineAsRegister(node), |
178 g.UseRegister(node->InputAt(0)), | 335 g.UseRegister(node->InputAt(0)), |
179 g.UseOperand(node->InputAt(1), operand_mode)); | 336 g.UseOperand(node->InputAt(1), operand_mode)); |
180 } | 337 } |
181 | 338 |
182 #if V8_TARGET_ARCH_S390X | |
183 void VisitTryTruncateDouble(InstructionSelector* selector, ArchOpcode opcode, | 339 void VisitTryTruncateDouble(InstructionSelector* selector, ArchOpcode opcode, |
184 Node* node) { | 340 Node* node) { |
185 S390OperandGenerator g(selector); | 341 S390OperandGenerator g(selector); |
186 InstructionOperand inputs[] = {g.UseRegister(node->InputAt(0))}; | 342 InstructionOperand inputs[] = {g.UseRegister(node->InputAt(0))}; |
187 InstructionOperand outputs[2]; | 343 InstructionOperand outputs[2]; |
188 size_t output_count = 0; | 344 size_t output_count = 0; |
189 outputs[output_count++] = g.DefineAsRegister(node); | 345 outputs[output_count++] = g.DefineAsRegister(node); |
190 | 346 |
191 Node* success_output = NodeProperties::FindProjection(node, 1); | 347 Node* success_output = NodeProperties::FindProjection(node, 1); |
192 if (success_output) { | 348 if (success_output) { |
193 outputs[output_count++] = g.DefineAsRegister(success_output); | 349 outputs[output_count++] = g.DefineAsRegister(success_output); |
194 } | 350 } |
195 | 351 |
196 selector->Emit(opcode, output_count, outputs, 1, inputs); | 352 selector->Emit(opcode, output_count, outputs, 1, inputs); |
197 } | 353 } |
198 #endif | 354 #endif |
199 | 355 |
200 // Shared routine for multiple binary operations. | 356 // Shared routine for multiple binary operations. |
201 template <typename Matcher> | 357 template <typename Matcher> |
202 void VisitBinop(InstructionSelector* selector, Node* node, | 358 void VisitBinop(InstructionSelector* selector, Node* node, |
203 InstructionCode opcode, ImmediateMode operand_mode, | 359 InstructionCode opcode, OperandModes operand_mode, |
204 FlagsContinuation* cont) { | 360 FlagsContinuation* cont) { |
205 S390OperandGenerator g(selector); | 361 S390OperandGenerator g(selector); |
206 Matcher m(node); | 362 Matcher m(node); |
207 Node* left = m.left().node(); | 363 Node* left = m.left().node(); |
208 Node* right = m.right().node(); | 364 Node* right = m.right().node(); |
209 InstructionOperand inputs[4]; | 365 InstructionOperand inputs[4]; |
210 size_t input_count = 0; | 366 size_t input_count = 0; |
211 InstructionOperand outputs[2]; | 367 InstructionOperand outputs[2]; |
212 size_t output_count = 0; | 368 size_t output_count = 0; |
213 | 369 |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
262 selector->EmitDeoptimize(opcode, output_count, outputs, input_count, inputs, | 418 selector->EmitDeoptimize(opcode, output_count, outputs, input_count, inputs, |
263 cont->reason(), cont->frame_state()); | 419 cont->reason(), cont->frame_state()); |
264 } else { | 420 } else { |
265 selector->Emit(opcode, output_count, outputs, input_count, inputs); | 421 selector->Emit(opcode, output_count, outputs, input_count, inputs); |
266 } | 422 } |
267 } | 423 } |
268 | 424 |
269 // Shared routine for multiple binary operations. | 425 // Shared routine for multiple binary operations. |
270 template <typename Matcher> | 426 template <typename Matcher> |
271 void VisitBinop(InstructionSelector* selector, Node* node, ArchOpcode opcode, | 427 void VisitBinop(InstructionSelector* selector, Node* node, ArchOpcode opcode, |
272 ImmediateMode operand_mode) { | 428 OperandModes operand_mode) { |
273 FlagsContinuation cont; | 429 FlagsContinuation cont; |
274 VisitBinop<Matcher>(selector, node, opcode, operand_mode, &cont); | 430 VisitBinop<Matcher>(selector, node, opcode, operand_mode, &cont); |
275 } | 431 } |
276 | 432 |
| 433 void VisitBin32op(InstructionSelector* selector, Node* node, |
| 434 InstructionCode opcode, OperandModes operand_mode, |
| 435 FlagsContinuation* cont) { |
| 436 S390OperandGenerator g(selector); |
| 437 Int32BinopMatcher m(node); |
| 438 Node* left = m.left().node(); |
| 439 Node* right = m.right().node(); |
| 440 InstructionOperand inputs[8]; |
| 441 size_t input_count = 0; |
| 442 InstructionOperand outputs[2]; |
| 443 size_t output_count = 0; |
| 444 |
| 445 // match left of TruncateInt64ToInt32 |
| 446 if (m.left().IsTruncateInt64ToInt32() && selector->CanCover(node, left)) { |
| 447 left = left->InputAt(0); |
| 448 } |
| 449 // match right of TruncateInt64ToInt32 |
| 450 if (m.right().IsTruncateInt64ToInt32() && selector->CanCover(node, right)) { |
| 451 right = right->InputAt(0); |
| 452 } |
| 453 |
| 454 #if V8_TARGET_ARCH_S390X |
| 455 if ((ZeroExtendsWord32ToWord64(right) || g.CanBeBetterLeftOperand(right)) && |
| 456 node->op()->HasProperty(Operator::kCommutative) && |
| 457 !g.CanBeImmediate(right, operand_mode)) { |
| 458 std::swap(left, right); |
| 459 } |
| 460 #else |
| 461 if (node->op()->HasProperty(Operator::kCommutative) && |
| 462 !g.CanBeImmediate(right, operand_mode) && |
| 463 (g.CanBeBetterLeftOperand(right))) { |
| 464 std::swap(left, right); |
| 465 } |
| 466 #endif |
| 467 |
| 468 // left is always register |
| 469 InstructionOperand const left_input = g.UseRegister(left); |
| 470 inputs[input_count++] = left_input; |
| 471 |
| 472 // TODO(turbofan): match complex addressing modes. |
| 473 if (left == right) { |
| 474 // If both inputs refer to the same operand, enforce allocating a register |
| 475 // for both of them to ensure that we don't end up generating code like |
| 476 // this: |
| 477 // |
| 478 // mov rax, [rbp-0x10] |
| 479 // add rax, [rbp-0x10] |
| 480 // jo label |
| 481 inputs[input_count++] = left_input; |
| 482 // Can only be RR or RRR |
| 483 operand_mode &= OperandMode::kAllowRRR; |
| 484 } else if ((operand_mode & OperandMode::kAllowImmediate) && |
| 485 g.CanBeImmediate(right, operand_mode)) { |
| 486 inputs[input_count++] = g.UseImmediate(right); |
| 487 // Can only be RI or RRI |
| 488 operand_mode &= OperandMode::kAllowImmediate; |
| 489 } else if (operand_mode & OperandMode::kAllowMemoryOperand) { |
| 490 NodeMatcher mright(right); |
| 491 if (mright.IsLoad() && selector->CanCover(node, right) && |
| 492 SelectLoadOpcode(right) == kS390_LoadWordU32) { |
| 493 AddressingMode mode = |
| 494 g.GetEffectiveAddressMemoryOperand(right, inputs, &input_count); |
| 495 opcode |= AddressingModeField::encode(mode); |
| 496 operand_mode &= ~OperandMode::kAllowImmediate; |
| 497 if (operand_mode & OperandMode::kAllowRM) |
| 498 operand_mode &= ~OperandMode::kAllowDistinctOps; |
| 499 } else if (operand_mode & OperandMode::kAllowRM) { |
| 500 DCHECK(!(operand_mode & OperandMode::kAllowRRM)); |
| 501 inputs[input_count++] = g.Use(right); |
| 502 // Can not be Immediate |
| 503 operand_mode &= |
| 504 ~OperandMode::kAllowImmediate & ~OperandMode::kAllowDistinctOps; |
| 505 } else if (operand_mode & OperandMode::kAllowRRM) { |
| 506 DCHECK(!(operand_mode & OperandMode::kAllowRM)); |
| 507 inputs[input_count++] = g.Use(right); |
| 508 // Can not be Immediate |
| 509 operand_mode &= ~OperandMode::kAllowImmediate; |
| 510 } else { |
| 511 UNREACHABLE(); |
| 512 } |
| 513 } else { |
| 514 inputs[input_count++] = g.UseRegister(right); |
| 515 // Can only be RR or RRR |
| 516 operand_mode &= OperandMode::kAllowRRR; |
| 517 } |
| 518 |
| 519 bool doZeroExt = |
| 520 AutoZeroExtendsWord32ToWord64(node) || !ZeroExtendsWord32ToWord64(left); |
| 521 |
| 522 inputs[input_count++] = |
| 523 g.TempImmediate(doZeroExt && (!AutoZeroExtendsWord32ToWord64(node))); |
| 524 |
| 525 if (cont->IsBranch()) { |
| 526 inputs[input_count++] = g.Label(cont->true_block()); |
| 527 inputs[input_count++] = g.Label(cont->false_block()); |
| 528 } |
| 529 |
| 530 if (doZeroExt && (operand_mode & OperandMode::kAllowDistinctOps) && |
| 531 // If we can deoptimize as a result of the binop, we need to make sure |
| 532 // that |
| 533 // the deopt inputs are not overwritten by the binop result. One way |
| 534 // to achieve that is to declare the output register as same-as-first. |
| 535 !cont->IsDeoptimize()) { |
| 536 outputs[output_count++] = g.DefineAsRegister(node); |
| 537 } else { |
| 538 outputs[output_count++] = g.DefineSameAsFirst(node); |
| 539 } |
| 540 |
| 541 if (cont->IsSet()) { |
| 542 outputs[output_count++] = g.DefineAsRegister(cont->result()); |
| 543 } |
| 544 |
| 545 DCHECK_NE(0u, input_count); |
| 546 DCHECK_NE(0u, output_count); |
| 547 DCHECK_GE(arraysize(inputs), input_count); |
| 548 DCHECK_GE(arraysize(outputs), output_count); |
| 549 |
| 550 opcode = cont->Encode(opcode); |
| 551 |
| 552 if (cont->IsDeoptimize()) { |
| 553 selector->EmitDeoptimize(opcode, output_count, outputs, input_count, inputs, |
| 554 cont->reason(), cont->frame_state()); |
| 555 } else { |
| 556 selector->Emit(opcode, output_count, outputs, input_count, inputs); |
| 557 } |
| 558 } |
| 559 |
| 560 void VisitBin32op(InstructionSelector* selector, Node* node, ArchOpcode opcode, |
| 561 OperandModes operand_mode) { |
| 562 FlagsContinuation cont; |
| 563 VisitBin32op(selector, node, opcode, operand_mode, &cont); |
| 564 } |
| 565 |
277 } // namespace | 566 } // namespace |
278 | 567 |
279 void InstructionSelector::VisitLoad(Node* node) { | 568 void InstructionSelector::VisitLoad(Node* node) { |
280 LoadRepresentation load_rep = LoadRepresentationOf(node->op()); | |
281 S390OperandGenerator g(this); | 569 S390OperandGenerator g(this); |
282 ArchOpcode opcode = kArchNop; | 570 ArchOpcode opcode = SelectLoadOpcode(node); |
283 switch (load_rep.representation()) { | |
284 case MachineRepresentation::kFloat32: | |
285 opcode = kS390_LoadFloat32; | |
286 break; | |
287 case MachineRepresentation::kFloat64: | |
288 opcode = kS390_LoadDouble; | |
289 break; | |
290 case MachineRepresentation::kBit: // Fall through. | |
291 case MachineRepresentation::kWord8: | |
292 opcode = load_rep.IsSigned() ? kS390_LoadWordS8 : kS390_LoadWordU8; | |
293 break; | |
294 case MachineRepresentation::kWord16: | |
295 opcode = load_rep.IsSigned() ? kS390_LoadWordS16 : kS390_LoadWordU16; | |
296 break; | |
297 #if !V8_TARGET_ARCH_S390X | |
298 case MachineRepresentation::kTaggedSigned: // Fall through. | |
299 case MachineRepresentation::kTaggedPointer: // Fall through. | |
300 case MachineRepresentation::kTagged: // Fall through. | |
301 #endif | |
302 case MachineRepresentation::kWord32: | |
303 opcode = kS390_LoadWordU32; | |
304 break; | |
305 #if V8_TARGET_ARCH_S390X | |
306 case MachineRepresentation::kTaggedSigned: // Fall through. | |
307 case MachineRepresentation::kTaggedPointer: // Fall through. | |
308 case MachineRepresentation::kTagged: // Fall through. | |
309 case MachineRepresentation::kWord64: | |
310 opcode = kS390_LoadWord64; | |
311 break; | |
312 #else | |
313 case MachineRepresentation::kWord64: // Fall through. | |
314 #endif | |
315 case MachineRepresentation::kSimd128: // Fall through. | |
316 case MachineRepresentation::kNone: | |
317 UNREACHABLE(); | |
318 return; | |
319 } | |
320 InstructionOperand outputs[1]; | 571 InstructionOperand outputs[1]; |
321 outputs[0] = g.DefineAsRegister(node); | 572 outputs[0] = g.DefineAsRegister(node); |
322 InstructionOperand inputs[3]; | 573 InstructionOperand inputs[3]; |
323 size_t input_count = 0; | 574 size_t input_count = 0; |
324 AddressingMode mode = | 575 AddressingMode mode = |
325 g.GetEffectiveAddressMemoryOperand(node, inputs, &input_count); | 576 g.GetEffectiveAddressMemoryOperand(node, inputs, &input_count); |
326 InstructionCode code = opcode | AddressingModeField::encode(mode); | 577 InstructionCode code = opcode | AddressingModeField::encode(mode); |
327 Emit(code, 1, outputs, input_count, inputs); | 578 Emit(code, 1, outputs, input_count, inputs); |
328 } | 579 } |
329 | 580 |
(...skipping 13 matching lines...) Expand all Loading... |
343 MachineRepresentation rep = store_rep.representation(); | 594 MachineRepresentation rep = store_rep.representation(); |
344 | 595 |
345 if (write_barrier_kind != kNoWriteBarrier) { | 596 if (write_barrier_kind != kNoWriteBarrier) { |
346 DCHECK_EQ(MachineRepresentation::kTagged, rep); | 597 DCHECK_EQ(MachineRepresentation::kTagged, rep); |
347 AddressingMode addressing_mode; | 598 AddressingMode addressing_mode; |
348 InstructionOperand inputs[3]; | 599 InstructionOperand inputs[3]; |
349 size_t input_count = 0; | 600 size_t input_count = 0; |
350 inputs[input_count++] = g.UseUniqueRegister(base); | 601 inputs[input_count++] = g.UseUniqueRegister(base); |
351 // OutOfLineRecordWrite uses the offset in an 'AddP' instruction as well as | 602 // OutOfLineRecordWrite uses the offset in an 'AddP' instruction as well as |
352 // for the store itself, so we must check compatibility with both. | 603 // for the store itself, so we must check compatibility with both. |
353 if (g.CanBeImmediate(offset, kInt20Imm)) { | 604 if (g.CanBeImmediate(offset, OperandMode::kInt20Imm)) { |
354 inputs[input_count++] = g.UseImmediate(offset); | 605 inputs[input_count++] = g.UseImmediate(offset); |
355 addressing_mode = kMode_MRI; | 606 addressing_mode = kMode_MRI; |
356 } else { | 607 } else { |
357 inputs[input_count++] = g.UseUniqueRegister(offset); | 608 inputs[input_count++] = g.UseUniqueRegister(offset); |
358 addressing_mode = kMode_MRR; | 609 addressing_mode = kMode_MRR; |
359 } | 610 } |
360 inputs[input_count++] = g.UseUniqueRegister(value); | 611 inputs[input_count++] = g.UseUniqueRegister(value); |
361 RecordWriteMode record_write_mode = RecordWriteMode::kValueIsAny; | 612 RecordWriteMode record_write_mode = RecordWriteMode::kValueIsAny; |
362 switch (write_barrier_kind) { | 613 switch (write_barrier_kind) { |
363 case kNoWriteBarrier: | 614 case kNoWriteBarrier: |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
487 case MachineRepresentation::kWord64: // Fall through. | 738 case MachineRepresentation::kWord64: // Fall through. |
488 #endif | 739 #endif |
489 case MachineRepresentation::kSimd128: // Fall through. | 740 case MachineRepresentation::kSimd128: // Fall through. |
490 case MachineRepresentation::kNone: | 741 case MachineRepresentation::kNone: |
491 UNREACHABLE(); | 742 UNREACHABLE(); |
492 return; | 743 return; |
493 } | 744 } |
494 AddressingMode addressingMode = kMode_MRR; | 745 AddressingMode addressingMode = kMode_MRR; |
495 Emit(opcode | AddressingModeField::encode(addressingMode), | 746 Emit(opcode | AddressingModeField::encode(addressingMode), |
496 g.DefineAsRegister(node), g.UseRegister(base), g.UseRegister(offset), | 747 g.DefineAsRegister(node), g.UseRegister(base), g.UseRegister(offset), |
497 g.UseOperand(length, kUint32Imm)); | 748 g.UseOperand(length, OperandMode::kUint32Imm)); |
498 } | 749 } |
499 | 750 |
500 void InstructionSelector::VisitCheckedStore(Node* node) { | 751 void InstructionSelector::VisitCheckedStore(Node* node) { |
501 MachineRepresentation rep = CheckedStoreRepresentationOf(node->op()); | 752 MachineRepresentation rep = CheckedStoreRepresentationOf(node->op()); |
502 S390OperandGenerator g(this); | 753 S390OperandGenerator g(this); |
503 Node* const base = node->InputAt(0); | 754 Node* const base = node->InputAt(0); |
504 Node* const offset = node->InputAt(1); | 755 Node* const offset = node->InputAt(1); |
505 Node* const length = node->InputAt(2); | 756 Node* const length = node->InputAt(2); |
506 Node* const value = node->InputAt(3); | 757 Node* const value = node->InputAt(3); |
507 ArchOpcode opcode = kArchNop; | 758 ArchOpcode opcode = kArchNop; |
(...skipping 26 matching lines...) Expand all Loading... |
534 case MachineRepresentation::kWord64: // Fall through. | 785 case MachineRepresentation::kWord64: // Fall through. |
535 #endif | 786 #endif |
536 case MachineRepresentation::kSimd128: // Fall through. | 787 case MachineRepresentation::kSimd128: // Fall through. |
537 case MachineRepresentation::kNone: | 788 case MachineRepresentation::kNone: |
538 UNREACHABLE(); | 789 UNREACHABLE(); |
539 return; | 790 return; |
540 } | 791 } |
541 AddressingMode addressingMode = kMode_MRR; | 792 AddressingMode addressingMode = kMode_MRR; |
542 Emit(opcode | AddressingModeField::encode(addressingMode), g.NoOutput(), | 793 Emit(opcode | AddressingModeField::encode(addressingMode), g.NoOutput(), |
543 g.UseRegister(base), g.UseRegister(offset), | 794 g.UseRegister(base), g.UseRegister(offset), |
544 g.UseOperand(length, kUint32Imm), g.UseRegister(value)); | 795 g.UseOperand(length, OperandMode::kUint32Imm), g.UseRegister(value)); |
545 } | 796 } |
546 | 797 |
547 #if 0 | 798 #if 0 |
548 static inline bool IsContiguousMask32(uint32_t value, int* mb, int* me) { | 799 static inline bool IsContiguousMask32(uint32_t value, int* mb, int* me) { |
549 int mask_width = base::bits::CountPopulation32(value); | 800 int mask_width = base::bits::CountPopulation32(value); |
550 int mask_msb = base::bits::CountLeadingZeros32(value); | 801 int mask_msb = base::bits::CountLeadingZeros32(value); |
551 int mask_lsb = base::bits::CountTrailingZeros32(value); | 802 int mask_lsb = base::bits::CountTrailingZeros32(value); |
552 if ((mask_width == 0) || (mask_msb + mask_width + mask_lsb != 32)) | 803 if ((mask_width == 0) || (mask_msb + mask_width + mask_lsb != 32)) |
553 return false; | 804 return false; |
554 *mb = mask_lsb + mask_width - 1; | 805 *mb = mask_lsb + mask_width - 1; |
555 *me = mask_lsb; | 806 *me = mask_lsb; |
556 return true; | 807 return true; |
557 } | 808 } |
558 #endif | 809 #endif |
559 | 810 |
560 #if V8_TARGET_ARCH_S390X | 811 #if V8_TARGET_ARCH_S390X |
561 static inline bool IsContiguousMask64(uint64_t value, int* mb, int* me) { | 812 static inline bool IsContiguousMask64(uint64_t value, int* mb, int* me) { |
562 int mask_width = base::bits::CountPopulation64(value); | 813 int mask_width = base::bits::CountPopulation64(value); |
563 int mask_msb = base::bits::CountLeadingZeros64(value); | 814 int mask_msb = base::bits::CountLeadingZeros64(value); |
564 int mask_lsb = base::bits::CountTrailingZeros64(value); | 815 int mask_lsb = base::bits::CountTrailingZeros64(value); |
565 if ((mask_width == 0) || (mask_msb + mask_width + mask_lsb != 64)) | 816 if ((mask_width == 0) || (mask_msb + mask_width + mask_lsb != 64)) |
566 return false; | 817 return false; |
567 *mb = mask_lsb + mask_width - 1; | 818 *mb = mask_lsb + mask_width - 1; |
568 *me = mask_lsb; | 819 *me = mask_lsb; |
569 return true; | 820 return true; |
570 } | 821 } |
571 #endif | 822 #endif |
572 | 823 |
573 void InstructionSelector::VisitWord32And(Node* node) { | 824 void InstructionSelector::VisitWord32And(Node* node) { |
574 VisitBinop<Int32BinopMatcher>(this, node, kS390_And32, kUint32Imm); | 825 VisitBin32op(this, node, kS390_And32, |
| 826 BitWiseOperandMode | OperandMode::kAllowRM); |
575 } | 827 } |
576 | 828 |
577 #if V8_TARGET_ARCH_S390X | 829 #if V8_TARGET_ARCH_S390X |
578 void InstructionSelector::VisitWord64And(Node* node) { | 830 void InstructionSelector::VisitWord64And(Node* node) { |
579 S390OperandGenerator g(this); | 831 S390OperandGenerator g(this); |
580 Int64BinopMatcher m(node); | 832 Int64BinopMatcher m(node); |
581 int mb = 0; | 833 int mb = 0; |
582 int me = 0; | 834 int me = 0; |
583 if (m.right().HasValue() && IsContiguousMask64(m.right().Value(), &mb, &me)) { | 835 if (m.right().HasValue() && IsContiguousMask64(m.right().Value(), &mb, &me)) { |
584 int sh = 0; | 836 int sh = 0; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
616 opcode = kS390_RotLeftAndClear64; | 868 opcode = kS390_RotLeftAndClear64; |
617 mask = mb; | 869 mask = mb; |
618 } | 870 } |
619 if (match) { | 871 if (match) { |
620 Emit(opcode, g.DefineAsRegister(node), g.UseRegister(left), | 872 Emit(opcode, g.DefineAsRegister(node), g.UseRegister(left), |
621 g.TempImmediate(sh), g.TempImmediate(mask)); | 873 g.TempImmediate(sh), g.TempImmediate(mask)); |
622 return; | 874 return; |
623 } | 875 } |
624 } | 876 } |
625 } | 877 } |
626 VisitBinop<Int64BinopMatcher>(this, node, kS390_And64, kUint32Imm); | 878 VisitBinop<Int64BinopMatcher>(this, node, kS390_And64, |
| 879 OperandMode::kUint32Imm); |
627 } | 880 } |
628 #endif | 881 #endif |
629 | 882 |
630 void InstructionSelector::VisitWord32Or(Node* node) { | 883 void InstructionSelector::VisitWord32Or(Node* node) { |
631 Int32BinopMatcher m(node); | 884 VisitBin32op(this, node, kS390_Or32, |
632 VisitBinop<Int32BinopMatcher>(this, node, kS390_Or32, kUint32Imm); | 885 BitWiseOperandMode | OperandMode::kAllowRM); |
633 } | 886 } |
634 | 887 |
635 #if V8_TARGET_ARCH_S390X | 888 #if V8_TARGET_ARCH_S390X |
636 void InstructionSelector::VisitWord64Or(Node* node) { | 889 void InstructionSelector::VisitWord64Or(Node* node) { |
637 Int64BinopMatcher m(node); | 890 Int64BinopMatcher m(node); |
638 VisitBinop<Int64BinopMatcher>(this, node, kS390_Or64, kUint32Imm); | 891 VisitBinop<Int64BinopMatcher>(this, node, kS390_Or64, |
| 892 OperandMode::kUint32Imm); |
639 } | 893 } |
640 #endif | 894 #endif |
641 | 895 |
642 void InstructionSelector::VisitWord32Xor(Node* node) { | 896 void InstructionSelector::VisitWord32Xor(Node* node) { |
643 S390OperandGenerator g(this); | 897 VisitBin32op(this, node, kS390_Xor32, |
644 Int32BinopMatcher m(node); | 898 BitWiseOperandMode | OperandMode::kAllowRM); |
645 if (m.right().Is(-1)) { | |
646 Emit(kS390_Not32, g.DefineAsRegister(node), g.UseRegister(m.left().node())); | |
647 } else { | |
648 VisitBinop<Int32BinopMatcher>(this, node, kS390_Xor32, kUint32Imm); | |
649 } | |
650 } | 899 } |
651 | 900 |
652 #if V8_TARGET_ARCH_S390X | 901 #if V8_TARGET_ARCH_S390X |
653 void InstructionSelector::VisitWord64Xor(Node* node) { | 902 void InstructionSelector::VisitWord64Xor(Node* node) { |
654 S390OperandGenerator g(this); | 903 VisitBinop<Int64BinopMatcher>(this, node, kS390_Xor64, |
655 Int64BinopMatcher m(node); | 904 OperandMode::kUint32Imm); |
656 if (m.right().Is(-1)) { | |
657 Emit(kS390_Not64, g.DefineAsRegister(node), g.UseRegister(m.left().node())); | |
658 } else { | |
659 VisitBinop<Int64BinopMatcher>(this, node, kS390_Xor64, kUint32Imm); | |
660 } | |
661 } | 905 } |
662 #endif | 906 #endif |
663 | 907 |
664 void InstructionSelector::VisitWord32Shl(Node* node) { | 908 void InstructionSelector::VisitWord32Shl(Node* node) { |
665 VisitRRO(this, kS390_ShiftLeft32, node, kShift32Imm); | 909 VisitBin32op(this, node, kS390_ShiftLeft32, BitWiseOperandMode); |
666 } | 910 } |
667 | 911 |
668 #if V8_TARGET_ARCH_S390X | 912 #if V8_TARGET_ARCH_S390X |
669 void InstructionSelector::VisitWord64Shl(Node* node) { | 913 void InstructionSelector::VisitWord64Shl(Node* node) { |
670 S390OperandGenerator g(this); | 914 S390OperandGenerator g(this); |
671 Int64BinopMatcher m(node); | 915 Int64BinopMatcher m(node); |
672 // TODO(mbrandy): eliminate left sign extension if right >= 32 | 916 // TODO(mbrandy): eliminate left sign extension if right >= 32 |
673 if (m.left().IsWord64And() && m.right().IsInRange(0, 63)) { | 917 if (m.left().IsWord64And() && m.right().IsInRange(0, 63)) { |
674 Int64BinopMatcher mleft(m.left().node()); | 918 Int64BinopMatcher mleft(m.left().node()); |
675 int sh = m.right().Value(); | 919 int sh = m.right().Value(); |
(...skipping 22 matching lines...) Expand all Loading... |
698 } | 942 } |
699 if (match) { | 943 if (match) { |
700 Emit(opcode, g.DefineAsRegister(node), | 944 Emit(opcode, g.DefineAsRegister(node), |
701 g.UseRegister(mleft.left().node()), g.TempImmediate(sh), | 945 g.UseRegister(mleft.left().node()), g.TempImmediate(sh), |
702 g.TempImmediate(mask)); | 946 g.TempImmediate(mask)); |
703 return; | 947 return; |
704 } | 948 } |
705 } | 949 } |
706 } | 950 } |
707 } | 951 } |
708 VisitRRO(this, kS390_ShiftLeft64, node, kShift64Imm); | 952 VisitRRO(this, kS390_ShiftLeft64, node, OperandMode::kShift64Imm); |
709 } | 953 } |
710 #endif | 954 #endif |
711 | 955 |
712 void InstructionSelector::VisitWord32Shr(Node* node) { | 956 void InstructionSelector::VisitWord32Shr(Node* node) { |
713 VisitRRO(this, kS390_ShiftRight32, node, kShift32Imm); | 957 VisitBin32op(this, node, kS390_ShiftRight32, BitWiseOperandMode); |
714 } | 958 } |
715 | 959 |
716 #if V8_TARGET_ARCH_S390X | 960 #if V8_TARGET_ARCH_S390X |
717 void InstructionSelector::VisitWord64Shr(Node* node) { | 961 void InstructionSelector::VisitWord64Shr(Node* node) { |
718 S390OperandGenerator g(this); | 962 S390OperandGenerator g(this); |
719 Int64BinopMatcher m(node); | 963 Int64BinopMatcher m(node); |
720 if (m.left().IsWord64And() && m.right().IsInRange(0, 63)) { | 964 if (m.left().IsWord64And() && m.right().IsInRange(0, 63)) { |
721 Int64BinopMatcher mleft(m.left().node()); | 965 Int64BinopMatcher mleft(m.left().node()); |
722 int sh = m.right().Value(); | 966 int sh = m.right().Value(); |
723 int mb; | 967 int mb; |
(...skipping 18 matching lines...) Expand all Loading... |
742 } | 986 } |
743 if (match) { | 987 if (match) { |
744 Emit(opcode, g.DefineAsRegister(node), | 988 Emit(opcode, g.DefineAsRegister(node), |
745 g.UseRegister(mleft.left().node()), g.TempImmediate(sh), | 989 g.UseRegister(mleft.left().node()), g.TempImmediate(sh), |
746 g.TempImmediate(mask)); | 990 g.TempImmediate(mask)); |
747 return; | 991 return; |
748 } | 992 } |
749 } | 993 } |
750 } | 994 } |
751 } | 995 } |
752 VisitRRO(this, kS390_ShiftRight64, node, kShift64Imm); | 996 VisitRRO(this, kS390_ShiftRight64, node, OperandMode::kShift64Imm); |
753 } | 997 } |
754 #endif | 998 #endif |
755 | 999 |
756 void InstructionSelector::VisitWord32Sar(Node* node) { | 1000 void InstructionSelector::VisitWord32Sar(Node* node) { |
757 S390OperandGenerator g(this); | 1001 S390OperandGenerator g(this); |
758 Int32BinopMatcher m(node); | 1002 Int32BinopMatcher m(node); |
759 // Replace with sign extension for (x << K) >> K where K is 16 or 24. | 1003 // Replace with sign extension for (x << K) >> K where K is 16 or 24. |
760 if (CanCover(node, m.left().node()) && m.left().IsWord32Shl()) { | 1004 if (CanCover(node, m.left().node()) && m.left().IsWord32Shl()) { |
761 Int32BinopMatcher mleft(m.left().node()); | 1005 Int32BinopMatcher mleft(m.left().node()); |
762 if (mleft.right().Is(16) && m.right().Is(16)) { | 1006 if (mleft.right().Is(16) && m.right().Is(16)) { |
763 Emit(kS390_ExtendSignWord16, g.DefineAsRegister(node), | 1007 bool doZeroExt = !ZeroExtendsWord32ToWord64(mleft.left().node()); |
764 g.UseRegister(mleft.left().node())); | 1008 Emit(kS390_ExtendSignWord16, |
| 1009 doZeroExt ? g.DefineAsRegister(node) : g.DefineSameAsFirst(node), |
| 1010 g.UseRegister(mleft.left().node()), g.TempImmediate(doZeroExt)); |
765 return; | 1011 return; |
766 } else if (mleft.right().Is(24) && m.right().Is(24)) { | 1012 } else if (mleft.right().Is(24) && m.right().Is(24)) { |
767 Emit(kS390_ExtendSignWord8, g.DefineAsRegister(node), | 1013 bool doZeroExt = !ZeroExtendsWord32ToWord64(mleft.left().node()); |
768 g.UseRegister(mleft.left().node())); | 1014 Emit(kS390_ExtendSignWord8, |
| 1015 doZeroExt ? g.DefineAsRegister(node) : g.DefineSameAsFirst(node), |
| 1016 g.UseRegister(mleft.left().node()), g.TempImmediate(doZeroExt)); |
769 return; | 1017 return; |
770 } | 1018 } |
771 } | 1019 } |
772 VisitRRO(this, kS390_ShiftRightArith32, node, kShift32Imm); | 1020 VisitBin32op(this, node, kS390_ShiftRightArith32, BitWiseOperandMode); |
773 } | 1021 } |
774 | 1022 |
775 #if !V8_TARGET_ARCH_S390X | 1023 #if !V8_TARGET_ARCH_S390X |
776 void VisitPairBinop(InstructionSelector* selector, InstructionCode opcode, | 1024 void VisitPairBinop(InstructionSelector* selector, InstructionCode opcode, |
777 InstructionCode opcode2, Node* node) { | 1025 InstructionCode opcode2, Node* node) { |
778 S390OperandGenerator g(selector); | 1026 S390OperandGenerator g(selector); |
779 | 1027 |
780 Node* projection1 = NodeProperties::FindProjection(node, 1); | 1028 Node* projection1 = NodeProperties::FindProjection(node, 1); |
781 if (projection1) { | 1029 if (projection1) { |
782 // We use UseUniqueRegister here to avoid register sharing with the output | 1030 // We use UseUniqueRegister here to avoid register sharing with the output |
783 // registers. | 1031 // registers. |
784 InstructionOperand inputs[] = { | 1032 InstructionOperand inputs[] = { |
785 g.UseRegister(node->InputAt(0)), g.UseUniqueRegister(node->InputAt(1)), | 1033 g.UseRegister(node->InputAt(0)), g.UseUniqueRegister(node->InputAt(1)), |
786 g.UseRegister(node->InputAt(2)), g.UseUniqueRegister(node->InputAt(3))}; | 1034 g.UseRegister(node->InputAt(2)), g.UseUniqueRegister(node->InputAt(3))}; |
787 | 1035 |
788 InstructionOperand outputs[] = { | 1036 InstructionOperand outputs[] = { |
789 g.DefineAsRegister(node), | 1037 g.DefineAsRegister(node), |
790 g.DefineAsRegister(NodeProperties::FindProjection(node, 1))}; | 1038 g.DefineAsRegister(NodeProperties::FindProjection(node, 1))}; |
791 | 1039 |
792 selector->Emit(opcode, 2, outputs, 4, inputs); | 1040 selector->Emit(opcode, 2, outputs, 4, inputs); |
793 } else { | 1041 } else { |
794 // The high word of the result is not used, so we emit the standard 32 bit | 1042 // The high word of the result is not used, so we emit the standard 32 bit |
795 // instruction. | 1043 // instruction. |
796 selector->Emit(opcode2, g.DefineSameAsFirst(node), | 1044 selector->Emit(opcode2, g.DefineSameAsFirst(node), |
797 g.UseRegister(node->InputAt(0)), | 1045 g.UseRegister(node->InputAt(0)), |
798 g.UseRegister(node->InputAt(2))); | 1046 g.UseRegister(node->InputAt(2)), g.TempImmediate(0)); |
799 } | 1047 } |
800 } | 1048 } |
801 | 1049 |
802 void InstructionSelector::VisitInt32PairAdd(Node* node) { | 1050 void InstructionSelector::VisitInt32PairAdd(Node* node) { |
803 VisitPairBinop(this, kS390_AddPair, kS390_Add32, node); | 1051 VisitPairBinop(this, kS390_AddPair, kS390_Add32, node); |
804 } | 1052 } |
805 | 1053 |
806 void InstructionSelector::VisitInt32PairSub(Node* node) { | 1054 void InstructionSelector::VisitInt32PairSub(Node* node) { |
807 VisitPairBinop(this, kS390_SubPair, kS390_Sub32, node); | 1055 VisitPairBinop(this, kS390_SubPair, kS390_Sub32, node); |
808 } | 1056 } |
809 | 1057 |
810 void InstructionSelector::VisitInt32PairMul(Node* node) { | 1058 void InstructionSelector::VisitInt32PairMul(Node* node) { |
811 S390OperandGenerator g(this); | 1059 S390OperandGenerator g(this); |
812 Node* projection1 = NodeProperties::FindProjection(node, 1); | 1060 Node* projection1 = NodeProperties::FindProjection(node, 1); |
813 if (projection1) { | 1061 if (projection1) { |
814 InstructionOperand inputs[] = {g.UseUniqueRegister(node->InputAt(0)), | 1062 InstructionOperand inputs[] = {g.UseUniqueRegister(node->InputAt(0)), |
815 g.UseUniqueRegister(node->InputAt(1)), | 1063 g.UseUniqueRegister(node->InputAt(1)), |
816 g.UseUniqueRegister(node->InputAt(2)), | 1064 g.UseUniqueRegister(node->InputAt(2)), |
817 g.UseUniqueRegister(node->InputAt(3))}; | 1065 g.UseUniqueRegister(node->InputAt(3))}; |
818 | 1066 |
819 InstructionOperand outputs[] = { | 1067 InstructionOperand outputs[] = { |
820 g.DefineAsRegister(node), | 1068 g.DefineAsRegister(node), |
821 g.DefineAsRegister(NodeProperties::FindProjection(node, 1))}; | 1069 g.DefineAsRegister(NodeProperties::FindProjection(node, 1))}; |
822 | 1070 |
823 Emit(kS390_MulPair, 2, outputs, 4, inputs); | 1071 Emit(kS390_MulPair, 2, outputs, 4, inputs); |
824 } else { | 1072 } else { |
825 // The high word of the result is not used, so we emit the standard 32 bit | 1073 // The high word of the result is not used, so we emit the standard 32 bit |
826 // instruction. | 1074 // instruction. |
827 Emit(kS390_Mul32, g.DefineSameAsFirst(node), | 1075 Emit(kS390_Mul32, g.DefineSameAsFirst(node), |
828 g.UseRegister(node->InputAt(0)), g.UseRegister(node->InputAt(2))); | 1076 g.UseRegister(node->InputAt(0)), g.Use(node->InputAt(2)), |
| 1077 g.TempImmediate(0)); |
829 } | 1078 } |
830 } | 1079 } |
831 | 1080 |
832 namespace { | 1081 namespace { |
833 // Shared routine for multiple shift operations. | 1082 // Shared routine for multiple shift operations. |
834 void VisitPairShift(InstructionSelector* selector, InstructionCode opcode, | 1083 void VisitPairShift(InstructionSelector* selector, InstructionCode opcode, |
835 Node* node) { | 1084 Node* node) { |
836 S390OperandGenerator g(selector); | 1085 S390OperandGenerator g(selector); |
837 // We use g.UseUniqueRegister here to guarantee that there is | 1086 // We use g.UseUniqueRegister here to guarantee that there is |
838 // no register aliasing of input registers with output registers. | 1087 // no register aliasing of input registers with output registers. |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
874 VisitPairShift(this, kS390_ShiftRightPair, node); | 1123 VisitPairShift(this, kS390_ShiftRightPair, node); |
875 } | 1124 } |
876 | 1125 |
877 void InstructionSelector::VisitWord32PairSar(Node* node) { | 1126 void InstructionSelector::VisitWord32PairSar(Node* node) { |
878 VisitPairShift(this, kS390_ShiftRightArithPair, node); | 1127 VisitPairShift(this, kS390_ShiftRightArithPair, node); |
879 } | 1128 } |
880 #endif | 1129 #endif |
881 | 1130 |
882 #if V8_TARGET_ARCH_S390X | 1131 #if V8_TARGET_ARCH_S390X |
883 void InstructionSelector::VisitWord64Sar(Node* node) { | 1132 void InstructionSelector::VisitWord64Sar(Node* node) { |
884 VisitRRO(this, kS390_ShiftRightArith64, node, kShift64Imm); | 1133 VisitRRO(this, kS390_ShiftRightArith64, node, OperandMode::kShift64Imm); |
885 } | 1134 } |
886 #endif | 1135 #endif |
887 | 1136 |
888 void InstructionSelector::VisitWord32Ror(Node* node) { | 1137 void InstructionSelector::VisitWord32Ror(Node* node) { |
889 VisitRRO(this, kS390_RotRight32, node, kShift32Imm); | 1138 // TODO(john): match dst = ror(src1, src2 + imm) |
| 1139 VisitBin32op(this, node, kS390_RotRight32, |
| 1140 OperandMode::kAllowRI | OperandMode::kAllowRRR | |
| 1141 OperandMode::kAllowRRI | OperandMode::kShift32Imm); |
890 } | 1142 } |
891 | 1143 |
892 #if V8_TARGET_ARCH_S390X | 1144 #if V8_TARGET_ARCH_S390X |
893 void InstructionSelector::VisitWord64Ror(Node* node) { | 1145 void InstructionSelector::VisitWord64Ror(Node* node) { |
894 VisitRRO(this, kS390_RotRight64, node, kShift64Imm); | 1146 VisitRRO(this, kS390_RotRight64, node, OperandMode::kShift64Imm); |
895 } | 1147 } |
896 #endif | 1148 #endif |
897 | 1149 |
898 void InstructionSelector::VisitWord32Clz(Node* node) { | 1150 void InstructionSelector::VisitWord32Clz(Node* node) { |
899 S390OperandGenerator g(this); | 1151 S390OperandGenerator g(this); |
900 Emit(kS390_Cntlz32, g.DefineAsRegister(node), | 1152 Emit(kS390_Cntlz32, g.DefineAsRegister(node), |
901 g.UseRegister(node->InputAt(0))); | 1153 g.UseRegister(node->InputAt(0))); |
902 } | 1154 } |
903 | 1155 |
904 #if V8_TARGET_ARCH_S390X | 1156 #if V8_TARGET_ARCH_S390X |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
954 g.DefineAsRegister(node), g.UseRegister(base), | 1206 g.DefineAsRegister(node), g.UseRegister(base), |
955 g.UseRegister(offset)); | 1207 g.UseRegister(offset)); |
956 return; | 1208 return; |
957 } | 1209 } |
958 } | 1210 } |
959 Emit(kS390_LoadReverse32RR, g.DefineAsRegister(node), | 1211 Emit(kS390_LoadReverse32RR, g.DefineAsRegister(node), |
960 g.UseRegister(node->InputAt(0))); | 1212 g.UseRegister(node->InputAt(0))); |
961 } | 1213 } |
962 | 1214 |
963 void InstructionSelector::VisitInt32Add(Node* node) { | 1215 void InstructionSelector::VisitInt32Add(Node* node) { |
964 VisitBinop<Int32BinopMatcher>(this, node, kS390_Add32, kInt32Imm); | 1216 VisitBin32op(this, node, kS390_Add32, AddOperandMode); |
965 } | 1217 } |
966 | 1218 |
967 #if V8_TARGET_ARCH_S390X | 1219 #if V8_TARGET_ARCH_S390X |
968 void InstructionSelector::VisitInt64Add(Node* node) { | 1220 void InstructionSelector::VisitInt64Add(Node* node) { |
969 VisitBinop<Int64BinopMatcher>(this, node, kS390_Add64, kInt32Imm); | 1221 VisitBinop<Int64BinopMatcher>(this, node, kS390_Add64, |
| 1222 OperandMode::kInt32Imm); |
970 } | 1223 } |
971 #endif | 1224 #endif |
972 | 1225 |
973 void InstructionSelector::VisitInt32Sub(Node* node) { | 1226 void InstructionSelector::VisitInt32Sub(Node* node) { |
974 S390OperandGenerator g(this); | 1227 S390OperandGenerator g(this); |
975 Int32BinopMatcher m(node); | 1228 Int32BinopMatcher m(node); |
976 if (m.left().Is(0)) { | 1229 if (m.left().Is(0)) { |
977 Emit(kS390_Neg32, g.DefineAsRegister(node), | 1230 Node* right = m.right().node(); |
978 g.UseRegister(m.right().node())); | 1231 bool doZeroExt = ZeroExtendsWord32ToWord64(right); |
| 1232 Emit(kS390_Neg32, g.DefineAsRegister(node), g.UseRegister(right), |
| 1233 g.TempImmediate(doZeroExt)); |
979 } else { | 1234 } else { |
980 VisitBinop<Int32BinopMatcher>(this, node, kS390_Sub32, kInt32Imm_Negate); | 1235 VisitBin32op(this, node, kS390_Sub32, SubOperandMode); |
981 } | 1236 } |
982 } | 1237 } |
983 | 1238 |
984 #if V8_TARGET_ARCH_S390X | 1239 #if V8_TARGET_ARCH_S390X |
985 void InstructionSelector::VisitInt64Sub(Node* node) { | 1240 void InstructionSelector::VisitInt64Sub(Node* node) { |
986 S390OperandGenerator g(this); | 1241 S390OperandGenerator g(this); |
987 Int64BinopMatcher m(node); | 1242 Int64BinopMatcher m(node); |
988 if (m.left().Is(0)) { | 1243 if (m.left().Is(0)) { |
989 Emit(kS390_Neg64, g.DefineAsRegister(node), | 1244 Emit(kS390_Neg64, g.DefineAsRegister(node), |
990 g.UseRegister(m.right().node())); | 1245 g.UseRegister(m.right().node())); |
991 } else { | 1246 } else { |
992 VisitBinop<Int64BinopMatcher>(this, node, kS390_Sub64, kInt32Imm_Negate); | 1247 VisitBinop<Int64BinopMatcher>(this, node, kS390_Sub64, |
| 1248 OperandMode::kInt32Imm_Negate); |
993 } | 1249 } |
994 } | 1250 } |
995 #endif | 1251 #endif |
996 | 1252 |
997 namespace { | 1253 namespace { |
998 | 1254 |
999 void VisitCompare(InstructionSelector* selector, InstructionCode opcode, | 1255 void VisitCompare(InstructionSelector* selector, InstructionCode opcode, |
1000 InstructionOperand left, InstructionOperand right, | 1256 InstructionOperand left, InstructionOperand right, |
1001 FlagsContinuation* cont); | 1257 FlagsContinuation* cont); |
1002 void EmitInt32MulWithOverflow(InstructionSelector* selector, Node* node, | |
1003 FlagsContinuation* cont) { | |
1004 S390OperandGenerator g(selector); | |
1005 Int32BinopMatcher m(node); | |
1006 InstructionOperand result_operand = g.DefineAsRegister(node); | |
1007 InstructionOperand high32_operand = g.TempRegister(); | |
1008 InstructionOperand temp_operand = g.TempRegister(); | |
1009 { | |
1010 InstructionOperand outputs[] = {result_operand, high32_operand}; | |
1011 InstructionOperand inputs[] = {g.UseRegister(m.left().node()), | |
1012 g.UseRegister(m.right().node())}; | |
1013 selector->Emit(kS390_Mul32WithHigh32, 2, outputs, 2, inputs); | |
1014 } | |
1015 { | |
1016 InstructionOperand shift_31 = g.UseImmediate(31); | |
1017 InstructionOperand outputs[] = {temp_operand}; | |
1018 InstructionOperand inputs[] = {result_operand, shift_31}; | |
1019 selector->Emit(kS390_ShiftRightArith32, 1, outputs, 2, inputs); | |
1020 } | |
1021 | 1258 |
1022 VisitCompare(selector, kS390_Cmp32, high32_operand, temp_operand, cont); | 1259 #if V8_TARGET_ARCH_S390X |
1023 } | |
1024 | |
1025 void VisitMul(InstructionSelector* selector, Node* node, ArchOpcode opcode) { | 1260 void VisitMul(InstructionSelector* selector, Node* node, ArchOpcode opcode) { |
1026 S390OperandGenerator g(selector); | 1261 S390OperandGenerator g(selector); |
1027 Int32BinopMatcher m(node); | 1262 Int32BinopMatcher m(node); |
1028 Node* left = m.left().node(); | 1263 Node* left = m.left().node(); |
1029 Node* right = m.right().node(); | 1264 Node* right = m.right().node(); |
1030 if (g.CanBeImmediate(right, kInt32Imm)) { | 1265 if (g.CanBeImmediate(right, OperandMode::kInt32Imm)) { |
1031 selector->Emit(opcode, g.DefineSameAsFirst(node), g.UseRegister(left), | 1266 selector->Emit(opcode, g.DefineSameAsFirst(node), g.UseRegister(left), |
1032 g.UseImmediate(right)); | 1267 g.UseImmediate(right)); |
1033 } else { | 1268 } else { |
1034 if (g.CanBeBetterLeftOperand(right)) { | 1269 if (g.CanBeBetterLeftOperand(right)) { |
1035 std::swap(left, right); | 1270 std::swap(left, right); |
1036 } | 1271 } |
1037 selector->Emit(opcode, g.DefineSameAsFirst(node), g.UseRegister(left), | 1272 selector->Emit(opcode, g.DefineSameAsFirst(node), g.UseRegister(left), |
1038 g.Use(right)); | 1273 g.Use(right)); |
1039 } | 1274 } |
1040 } | 1275 } |
| 1276 #endif |
1041 | 1277 |
1042 } // namespace | 1278 } // namespace |
1043 | 1279 |
1044 void InstructionSelector::VisitInt32MulWithOverflow(Node* node) { | 1280 void InstructionSelector::VisitInt32MulWithOverflow(Node* node) { |
1045 if (Node* ovf = NodeProperties::FindProjection(node, 1)) { | 1281 if (Node* ovf = NodeProperties::FindProjection(node, 1)) { |
1046 FlagsContinuation cont = FlagsContinuation::ForSet(kNotEqual, ovf); | 1282 FlagsContinuation cont = FlagsContinuation::ForSet(kNotEqual, ovf); |
1047 return EmitInt32MulWithOverflow(this, node, &cont); | 1283 return VisitBin32op(this, node, kS390_Mul32WithOverflow, |
| 1284 OperandMode::kInt32Imm | OperandMode::kAllowDistinctOps, |
| 1285 &cont); |
1048 } | 1286 } |
1049 VisitMul(this, node, kS390_Mul32); | 1287 VisitBin32op(this, node, kS390_Mul32, MulOperandMode); |
1050 // FlagsContinuation cont; | |
1051 // EmitInt32MulWithOverflow(this, node, &cont); | |
1052 } | 1288 } |
1053 | 1289 |
1054 void InstructionSelector::VisitInt32Mul(Node* node) { | 1290 void InstructionSelector::VisitInt32Mul(Node* node) { |
1055 S390OperandGenerator g(this); | 1291 S390OperandGenerator g(this); |
1056 Int32BinopMatcher m(node); | 1292 Int32BinopMatcher m(node); |
1057 Node* left = m.left().node(); | 1293 Node* left = m.left().node(); |
1058 Node* right = m.right().node(); | 1294 Node* right = m.right().node(); |
1059 if (g.CanBeImmediate(right, kInt32Imm) && | 1295 if (g.CanBeImmediate(right, OperandMode::kInt32Imm) && |
1060 base::bits::IsPowerOfTwo32(g.GetImmediate(right))) { | 1296 base::bits::IsPowerOfTwo32(g.GetImmediate(right))) { |
1061 int power = 31 - base::bits::CountLeadingZeros32(g.GetImmediate(right)); | 1297 int power = 31 - base::bits::CountLeadingZeros32(g.GetImmediate(right)); |
1062 Emit(kS390_ShiftLeft32, g.DefineSameAsFirst(node), g.UseRegister(left), | 1298 bool doZeroExt = !ZeroExtendsWord32ToWord64(left); |
1063 g.UseImmediate(power)); | 1299 InstructionOperand dst = |
| 1300 (doZeroExt && CpuFeatures::IsSupported(DISTINCT_OPS)) |
| 1301 ? g.DefineAsRegister(node) |
| 1302 : g.DefineSameAsFirst(node); |
| 1303 |
| 1304 Emit(kS390_ShiftLeft32, dst, g.UseRegister(left), g.UseImmediate(power), |
| 1305 g.TempImmediate(doZeroExt)); |
1064 return; | 1306 return; |
1065 } | 1307 } |
1066 VisitMul(this, node, kS390_Mul32); | 1308 VisitBin32op(this, node, kS390_Mul32, MulOperandMode); |
1067 } | 1309 } |
1068 | 1310 |
1069 #if V8_TARGET_ARCH_S390X | 1311 #if V8_TARGET_ARCH_S390X |
1070 void InstructionSelector::VisitInt64Mul(Node* node) { | 1312 void InstructionSelector::VisitInt64Mul(Node* node) { |
1071 S390OperandGenerator g(this); | 1313 S390OperandGenerator g(this); |
1072 Int64BinopMatcher m(node); | 1314 Int64BinopMatcher m(node); |
1073 Node* left = m.left().node(); | 1315 Node* left = m.left().node(); |
1074 Node* right = m.right().node(); | 1316 Node* right = m.right().node(); |
1075 if (g.CanBeImmediate(right, kInt32Imm) && | 1317 if (g.CanBeImmediate(right, OperandMode::kInt32Imm) && |
1076 base::bits::IsPowerOfTwo64(g.GetImmediate(right))) { | 1318 base::bits::IsPowerOfTwo64(g.GetImmediate(right))) { |
1077 int power = 63 - base::bits::CountLeadingZeros64(g.GetImmediate(right)); | 1319 int power = 63 - base::bits::CountLeadingZeros64(g.GetImmediate(right)); |
1078 Emit(kS390_ShiftLeft64, g.DefineSameAsFirst(node), g.UseRegister(left), | 1320 Emit(kS390_ShiftLeft64, g.DefineSameAsFirst(node), g.UseRegister(left), |
1079 g.UseImmediate(power)); | 1321 g.UseImmediate(power)); |
1080 return; | 1322 return; |
1081 } | 1323 } |
1082 VisitMul(this, node, kS390_Mul64); | 1324 VisitMul(this, node, kS390_Mul64); |
1083 } | 1325 } |
1084 #endif | 1326 #endif |
1085 | 1327 |
1086 void InstructionSelector::VisitInt32MulHigh(Node* node) { | 1328 void InstructionSelector::VisitInt32MulHigh(Node* node) { |
1087 S390OperandGenerator g(this); | 1329 VisitBin32op(this, node, kS390_MulHigh32, |
1088 Int32BinopMatcher m(node); | 1330 OperandMode::kInt32Imm | OperandMode::kAllowDistinctOps); |
1089 Node* left = m.left().node(); | |
1090 Node* right = m.right().node(); | |
1091 if (g.CanBeBetterLeftOperand(right)) { | |
1092 std::swap(left, right); | |
1093 } | |
1094 Emit(kS390_MulHigh32, g.DefineAsRegister(node), g.UseRegister(left), | |
1095 g.Use(right)); | |
1096 } | 1331 } |
1097 | 1332 |
1098 void InstructionSelector::VisitUint32MulHigh(Node* node) { | 1333 void InstructionSelector::VisitUint32MulHigh(Node* node) { |
1099 S390OperandGenerator g(this); | 1334 S390OperandGenerator g(this); |
1100 Int32BinopMatcher m(node); | 1335 Int32BinopMatcher m(node); |
1101 Node* left = m.left().node(); | 1336 Node* left = m.left().node(); |
1102 Node* right = m.right().node(); | 1337 Node* right = m.right().node(); |
1103 if (g.CanBeBetterLeftOperand(right)) { | 1338 if (g.CanBeBetterLeftOperand(right)) { |
1104 std::swap(left, right); | 1339 std::swap(left, right); |
1105 } | 1340 } |
1106 Emit(kS390_MulHighU32, g.DefineAsRegister(node), g.UseRegister(left), | 1341 Emit(kS390_MulHighU32, g.DefineAsRegister(node), g.UseRegister(left), |
1107 g.Use(right)); | 1342 g.Use(right)); |
1108 } | 1343 } |
1109 | 1344 |
1110 void InstructionSelector::VisitInt32Div(Node* node) { | 1345 void InstructionSelector::VisitInt32Div(Node* node) { |
1111 VisitRRR(this, kS390_Div32, node); | 1346 VisitBin32op(this, node, kS390_Div32, |
| 1347 OperandMode::kAllowRRM | OperandMode::kAllowRRR); |
1112 } | 1348 } |
1113 | 1349 |
1114 #if V8_TARGET_ARCH_S390X | 1350 #if V8_TARGET_ARCH_S390X |
1115 void InstructionSelector::VisitInt64Div(Node* node) { | 1351 void InstructionSelector::VisitInt64Div(Node* node) { |
1116 VisitRRR(this, kS390_Div64, node); | 1352 VisitRRR(this, kS390_Div64, node); |
1117 } | 1353 } |
1118 #endif | 1354 #endif |
1119 | 1355 |
1120 void InstructionSelector::VisitUint32Div(Node* node) { | 1356 void InstructionSelector::VisitUint32Div(Node* node) { |
1121 VisitRRR(this, kS390_DivU32, node); | 1357 VisitBin32op(this, node, kS390_DivU32, |
| 1358 OperandMode::kAllowRRM | OperandMode::kAllowRRR); |
1122 } | 1359 } |
1123 | 1360 |
1124 #if V8_TARGET_ARCH_S390X | 1361 #if V8_TARGET_ARCH_S390X |
1125 void InstructionSelector::VisitUint64Div(Node* node) { | 1362 void InstructionSelector::VisitUint64Div(Node* node) { |
1126 VisitRRR(this, kS390_DivU64, node); | 1363 VisitRRR(this, kS390_DivU64, node); |
1127 } | 1364 } |
1128 #endif | 1365 #endif |
1129 | 1366 |
1130 void InstructionSelector::VisitInt32Mod(Node* node) { | 1367 void InstructionSelector::VisitInt32Mod(Node* node) { |
1131 VisitRRR(this, kS390_Mod32, node); | 1368 VisitRRR(this, kS390_Mod32, node); |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1195 void InstructionSelector::VisitTryTruncateFloat64ToUint64(Node* node) { | 1432 void InstructionSelector::VisitTryTruncateFloat64ToUint64(Node* node) { |
1196 VisitTryTruncateDouble(this, kS390_DoubleToUint64, node); | 1433 VisitTryTruncateDouble(this, kS390_DoubleToUint64, node); |
1197 } | 1434 } |
1198 | 1435 |
1199 void InstructionSelector::VisitChangeInt32ToInt64(Node* node) { | 1436 void InstructionSelector::VisitChangeInt32ToInt64(Node* node) { |
1200 // TODO(mbrandy): inspect input to see if nop is appropriate. | 1437 // TODO(mbrandy): inspect input to see if nop is appropriate. |
1201 VisitRR(this, kS390_ExtendSignWord32, node); | 1438 VisitRR(this, kS390_ExtendSignWord32, node); |
1202 } | 1439 } |
1203 | 1440 |
1204 void InstructionSelector::VisitChangeUint32ToUint64(Node* node) { | 1441 void InstructionSelector::VisitChangeUint32ToUint64(Node* node) { |
1205 // TODO(mbrandy): inspect input to see if nop is appropriate. | 1442 S390OperandGenerator g(this); |
| 1443 Node* value = node->InputAt(0); |
| 1444 if (ZeroExtendsWord32ToWord64(value)) { |
| 1445 // These 32-bit operations implicitly zero-extend to 64-bit on x64, so the |
| 1446 // zero-extension is a no-op. |
| 1447 return EmitIdentity(node); |
| 1448 } |
1206 VisitRR(this, kS390_Uint32ToUint64, node); | 1449 VisitRR(this, kS390_Uint32ToUint64, node); |
1207 } | 1450 } |
1208 #endif | 1451 #endif |
1209 | 1452 |
1210 void InstructionSelector::VisitTruncateFloat64ToFloat32(Node* node) { | 1453 void InstructionSelector::VisitTruncateFloat64ToFloat32(Node* node) { |
1211 VisitRR(this, kS390_DoubleToFloat32, node); | 1454 VisitRR(this, kS390_DoubleToFloat32, node); |
1212 } | 1455 } |
1213 | 1456 |
1214 void InstructionSelector::VisitTruncateFloat64ToWord32(Node* node) { | 1457 void InstructionSelector::VisitTruncateFloat64ToWord32(Node* node) { |
1215 VisitRR(this, kArchTruncateDoubleToI, node); | 1458 VisitRR(this, kArchTruncateDoubleToI, node); |
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1401 | 1644 |
1402 void InstructionSelector::VisitFloat32Neg(Node* node) { | 1645 void InstructionSelector::VisitFloat32Neg(Node* node) { |
1403 VisitRR(this, kS390_NegFloat, node); | 1646 VisitRR(this, kS390_NegFloat, node); |
1404 } | 1647 } |
1405 | 1648 |
1406 void InstructionSelector::VisitFloat64Neg(Node* node) { | 1649 void InstructionSelector::VisitFloat64Neg(Node* node) { |
1407 VisitRR(this, kS390_NegDouble, node); | 1650 VisitRR(this, kS390_NegDouble, node); |
1408 } | 1651 } |
1409 | 1652 |
1410 void InstructionSelector::VisitInt32AddWithOverflow(Node* node) { | 1653 void InstructionSelector::VisitInt32AddWithOverflow(Node* node) { |
| 1654 OperandModes mode = AddOperandMode; |
1411 if (Node* ovf = NodeProperties::FindProjection(node, 1)) { | 1655 if (Node* ovf = NodeProperties::FindProjection(node, 1)) { |
1412 FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf); | 1656 FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf); |
1413 return VisitBinop<Int32BinopMatcher>(this, node, kS390_Add32, kInt32Imm, | 1657 return VisitBin32op(this, node, kS390_Add32, mode, &cont); |
1414 &cont); | |
1415 } | 1658 } |
1416 FlagsContinuation cont; | 1659 FlagsContinuation cont; |
1417 VisitBinop<Int32BinopMatcher>(this, node, kS390_Add32, kInt32Imm, &cont); | 1660 VisitBin32op(this, node, kS390_Add32, mode, &cont); |
1418 } | 1661 } |
1419 | 1662 |
1420 void InstructionSelector::VisitInt32SubWithOverflow(Node* node) { | 1663 void InstructionSelector::VisitInt32SubWithOverflow(Node* node) { |
| 1664 OperandModes mode = SubOperandMode; |
1421 if (Node* ovf = NodeProperties::FindProjection(node, 1)) { | 1665 if (Node* ovf = NodeProperties::FindProjection(node, 1)) { |
1422 FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf); | 1666 FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf); |
1423 return VisitBinop<Int32BinopMatcher>(this, node, kS390_Sub32, | 1667 return VisitBin32op(this, node, kS390_Sub32, mode, &cont); |
1424 kInt32Imm_Negate, &cont); | |
1425 } | 1668 } |
1426 FlagsContinuation cont; | 1669 FlagsContinuation cont; |
1427 VisitBinop<Int32BinopMatcher>(this, node, kS390_Sub32, kInt32Imm_Negate, | 1670 VisitBin32op(this, node, kS390_Sub32, mode, &cont); |
1428 &cont); | |
1429 } | 1671 } |
1430 | 1672 |
1431 #if V8_TARGET_ARCH_S390X | 1673 #if V8_TARGET_ARCH_S390X |
1432 void InstructionSelector::VisitInt64AddWithOverflow(Node* node) { | 1674 void InstructionSelector::VisitInt64AddWithOverflow(Node* node) { |
1433 if (Node* ovf = NodeProperties::FindProjection(node, 1)) { | 1675 if (Node* ovf = NodeProperties::FindProjection(node, 1)) { |
1434 FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf); | 1676 FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf); |
1435 return VisitBinop<Int64BinopMatcher>(this, node, kS390_Add64, kInt32Imm, | 1677 return VisitBinop<Int64BinopMatcher>(this, node, kS390_Add64, |
1436 &cont); | 1678 OperandMode::kInt32Imm, &cont); |
1437 } | 1679 } |
1438 FlagsContinuation cont; | 1680 FlagsContinuation cont; |
1439 VisitBinop<Int64BinopMatcher>(this, node, kS390_Add64, kInt32Imm, &cont); | 1681 VisitBinop<Int64BinopMatcher>(this, node, kS390_Add64, OperandMode::kInt32Imm, |
| 1682 &cont); |
1440 } | 1683 } |
1441 | 1684 |
1442 void InstructionSelector::VisitInt64SubWithOverflow(Node* node) { | 1685 void InstructionSelector::VisitInt64SubWithOverflow(Node* node) { |
1443 if (Node* ovf = NodeProperties::FindProjection(node, 1)) { | 1686 if (Node* ovf = NodeProperties::FindProjection(node, 1)) { |
1444 FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf); | 1687 FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf); |
1445 return VisitBinop<Int64BinopMatcher>(this, node, kS390_Sub64, | 1688 return VisitBinop<Int64BinopMatcher>(this, node, kS390_Sub64, |
1446 kInt32Imm_Negate, &cont); | 1689 OperandMode::kInt32Imm_Negate, &cont); |
1447 } | 1690 } |
1448 FlagsContinuation cont; | 1691 FlagsContinuation cont; |
1449 VisitBinop<Int64BinopMatcher>(this, node, kS390_Sub64, kInt32Imm_Negate, | 1692 VisitBinop<Int64BinopMatcher>(this, node, kS390_Sub64, |
1450 &cont); | 1693 OperandMode::kInt32Imm_Negate, &cont); |
1451 } | 1694 } |
1452 #endif | 1695 #endif |
1453 | 1696 |
1454 static bool CompareLogical(FlagsContinuation* cont) { | 1697 static bool CompareLogical(FlagsContinuation* cont) { |
1455 switch (cont->condition()) { | 1698 switch (cont->condition()) { |
1456 case kUnsignedLessThan: | 1699 case kUnsignedLessThan: |
1457 case kUnsignedGreaterThanOrEqual: | 1700 case kUnsignedGreaterThanOrEqual: |
1458 case kUnsignedLessThanOrEqual: | 1701 case kUnsignedLessThanOrEqual: |
1459 case kUnsignedGreaterThan: | 1702 case kUnsignedGreaterThan: |
1460 return true; | 1703 return true; |
(...skipping 20 matching lines...) Expand all Loading... |
1481 cont->frame_state()); | 1724 cont->frame_state()); |
1482 } else { | 1725 } else { |
1483 DCHECK(cont->IsSet()); | 1726 DCHECK(cont->IsSet()); |
1484 selector->Emit(opcode, g.DefineAsRegister(cont->result()), left, right); | 1727 selector->Emit(opcode, g.DefineAsRegister(cont->result()), left, right); |
1485 } | 1728 } |
1486 } | 1729 } |
1487 | 1730 |
1488 // Shared routine for multiple word compare operations. | 1731 // Shared routine for multiple word compare operations. |
1489 void VisitWordCompare(InstructionSelector* selector, Node* node, | 1732 void VisitWordCompare(InstructionSelector* selector, Node* node, |
1490 InstructionCode opcode, FlagsContinuation* cont, | 1733 InstructionCode opcode, FlagsContinuation* cont, |
1491 bool commutative, ImmediateMode immediate_mode) { | 1734 bool commutative, OperandModes immediate_mode) { |
1492 S390OperandGenerator g(selector); | 1735 S390OperandGenerator g(selector); |
1493 Node* left = node->InputAt(0); | 1736 Node* left = node->InputAt(0); |
1494 Node* right = node->InputAt(1); | 1737 Node* right = node->InputAt(1); |
1495 | 1738 |
1496 // Match immediates on left or right side of comparison. | 1739 // Match immediates on left or right side of comparison. |
1497 if (g.CanBeImmediate(right, immediate_mode)) { | 1740 if (g.CanBeImmediate(right, immediate_mode)) { |
1498 VisitCompare(selector, opcode, g.UseRegister(left), g.UseImmediate(right), | 1741 VisitCompare(selector, opcode, g.UseRegister(left), g.UseImmediate(right), |
1499 cont); | 1742 cont); |
1500 } else if (g.CanBeImmediate(left, immediate_mode)) { | 1743 } else if (g.CanBeImmediate(left, immediate_mode)) { |
1501 if (!commutative) cont->Commute(); | 1744 if (!commutative) cont->Commute(); |
1502 VisitCompare(selector, opcode, g.UseRegister(right), g.UseImmediate(left), | 1745 VisitCompare(selector, opcode, g.UseRegister(right), g.UseImmediate(left), |
1503 cont); | 1746 cont); |
1504 } else { | 1747 } else { |
1505 VisitCompare(selector, opcode, g.UseRegister(left), g.UseRegister(right), | 1748 VisitCompare(selector, opcode, g.UseRegister(left), g.UseRegister(right), |
1506 cont); | 1749 cont); |
1507 } | 1750 } |
1508 } | 1751 } |
1509 | 1752 |
1510 void VisitWord32Compare(InstructionSelector* selector, Node* node, | 1753 void VisitWord32Compare(InstructionSelector* selector, Node* node, |
1511 FlagsContinuation* cont) { | 1754 FlagsContinuation* cont) { |
1512 ImmediateMode mode = (CompareLogical(cont) ? kUint32Imm : kInt32Imm); | 1755 OperandModes mode = |
| 1756 (CompareLogical(cont) ? OperandMode::kUint32Imm : OperandMode::kInt32Imm); |
1513 VisitWordCompare(selector, node, kS390_Cmp32, cont, false, mode); | 1757 VisitWordCompare(selector, node, kS390_Cmp32, cont, false, mode); |
1514 } | 1758 } |
1515 | 1759 |
1516 #if V8_TARGET_ARCH_S390X | 1760 #if V8_TARGET_ARCH_S390X |
1517 void VisitWord64Compare(InstructionSelector* selector, Node* node, | 1761 void VisitWord64Compare(InstructionSelector* selector, Node* node, |
1518 FlagsContinuation* cont) { | 1762 FlagsContinuation* cont) { |
1519 ImmediateMode mode = (CompareLogical(cont) ? kUint32Imm : kUint32Imm); | 1763 OperandModes mode = |
| 1764 (CompareLogical(cont) ? OperandMode::kUint32Imm : OperandMode::kInt32Imm); |
1520 VisitWordCompare(selector, node, kS390_Cmp64, cont, false, mode); | 1765 VisitWordCompare(selector, node, kS390_Cmp64, cont, false, mode); |
1521 } | 1766 } |
1522 #endif | 1767 #endif |
1523 | 1768 |
1524 // Shared routine for multiple float32 compare operations. | 1769 // Shared routine for multiple float32 compare operations. |
1525 void VisitFloat32Compare(InstructionSelector* selector, Node* node, | 1770 void VisitFloat32Compare(InstructionSelector* selector, Node* node, |
1526 FlagsContinuation* cont) { | 1771 FlagsContinuation* cont) { |
1527 S390OperandGenerator g(selector); | 1772 S390OperandGenerator g(selector); |
1528 Node* left = node->InputAt(0); | 1773 Node* left = node->InputAt(0); |
1529 Node* right = node->InputAt(1); | 1774 Node* right = node->InputAt(1); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1564 if (m.right().Is(0)) { | 1809 if (m.right().Is(0)) { |
1565 // Try to combine the branch with a comparison. | 1810 // Try to combine the branch with a comparison. |
1566 Node* const user = m.node(); | 1811 Node* const user = m.node(); |
1567 Node* const value = m.left().node(); | 1812 Node* const value = m.left().node(); |
1568 if (selector->CanCover(user, value)) { | 1813 if (selector->CanCover(user, value)) { |
1569 switch (value->opcode()) { | 1814 switch (value->opcode()) { |
1570 case IrOpcode::kInt32Sub: | 1815 case IrOpcode::kInt32Sub: |
1571 return VisitWord32Compare(selector, value, cont); | 1816 return VisitWord32Compare(selector, value, cont); |
1572 case IrOpcode::kWord32And: | 1817 case IrOpcode::kWord32And: |
1573 return VisitWordCompare(selector, value, kS390_Tst64, cont, | 1818 return VisitWordCompare(selector, value, kS390_Tst64, cont, |
1574 true, kUint32Imm); | 1819 true, OperandMode::kUint32Imm); |
1575 default: | 1820 default: |
1576 break; | 1821 break; |
1577 } | 1822 } |
1578 } | 1823 } |
1579 } | 1824 } |
1580 return VisitWord32Compare(selector, value, cont); | 1825 return VisitWord32Compare(selector, value, cont); |
1581 } | 1826 } |
1582 case IrOpcode::kInt32LessThan: | 1827 case IrOpcode::kInt32LessThan: |
1583 cont->OverwriteAndNegateIfEqual(kSignedLessThan); | 1828 cont->OverwriteAndNegateIfEqual(kSignedLessThan); |
1584 return VisitWord32Compare(selector, value, cont); | 1829 return VisitWord32Compare(selector, value, cont); |
(...skipping 13 matching lines...) Expand all Loading... |
1598 if (m.right().Is(0)) { | 1843 if (m.right().Is(0)) { |
1599 // Try to combine the branch with a comparison. | 1844 // Try to combine the branch with a comparison. |
1600 Node* const user = m.node(); | 1845 Node* const user = m.node(); |
1601 Node* const value = m.left().node(); | 1846 Node* const value = m.left().node(); |
1602 if (selector->CanCover(user, value)) { | 1847 if (selector->CanCover(user, value)) { |
1603 switch (value->opcode()) { | 1848 switch (value->opcode()) { |
1604 case IrOpcode::kInt64Sub: | 1849 case IrOpcode::kInt64Sub: |
1605 return VisitWord64Compare(selector, value, cont); | 1850 return VisitWord64Compare(selector, value, cont); |
1606 case IrOpcode::kWord64And: | 1851 case IrOpcode::kWord64And: |
1607 return VisitWordCompare(selector, value, kS390_Tst64, cont, | 1852 return VisitWordCompare(selector, value, kS390_Tst64, cont, |
1608 true, kUint32Imm); | 1853 true, OperandMode::kUint32Imm); |
1609 default: | 1854 default: |
1610 break; | 1855 break; |
1611 } | 1856 } |
1612 } | 1857 } |
1613 } | 1858 } |
1614 return VisitWord64Compare(selector, value, cont); | 1859 return VisitWord64Compare(selector, value, cont); |
1615 } | 1860 } |
1616 case IrOpcode::kInt64LessThan: | 1861 case IrOpcode::kInt64LessThan: |
1617 cont->OverwriteAndNegateIfEqual(kSignedLessThan); | 1862 cont->OverwriteAndNegateIfEqual(kSignedLessThan); |
1618 return VisitWord64Compare(selector, value, cont); | 1863 return VisitWord64Compare(selector, value, cont); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1652 // unless the 0th projection (the use of the actual value of the | 1897 // unless the 0th projection (the use of the actual value of the |
1653 // <Operation> is either nullptr, which means there's no use of the | 1898 // <Operation> is either nullptr, which means there's no use of the |
1654 // actual value, or was already defined, which means it is scheduled | 1899 // actual value, or was already defined, which means it is scheduled |
1655 // *AFTER* this branch). | 1900 // *AFTER* this branch). |
1656 Node* const node = value->InputAt(0); | 1901 Node* const node = value->InputAt(0); |
1657 Node* const result = NodeProperties::FindProjection(node, 0); | 1902 Node* const result = NodeProperties::FindProjection(node, 0); |
1658 if (result == nullptr || selector->IsDefined(result)) { | 1903 if (result == nullptr || selector->IsDefined(result)) { |
1659 switch (node->opcode()) { | 1904 switch (node->opcode()) { |
1660 case IrOpcode::kInt32AddWithOverflow: | 1905 case IrOpcode::kInt32AddWithOverflow: |
1661 cont->OverwriteAndNegateIfEqual(kOverflow); | 1906 cont->OverwriteAndNegateIfEqual(kOverflow); |
1662 return VisitBinop<Int32BinopMatcher>( | 1907 return VisitBin32op(selector, node, kS390_Add32, AddOperandMode, |
1663 selector, node, kS390_Add32, kInt32Imm, cont); | 1908 cont); |
1664 case IrOpcode::kInt32SubWithOverflow: | 1909 case IrOpcode::kInt32SubWithOverflow: |
1665 cont->OverwriteAndNegateIfEqual(kOverflow); | 1910 cont->OverwriteAndNegateIfEqual(kOverflow); |
1666 return VisitBinop<Int32BinopMatcher>( | 1911 return VisitBin32op(selector, node, kS390_Sub32, SubOperandMode, |
1667 selector, node, kS390_Sub32, kInt32Imm_Negate, cont); | 1912 cont); |
1668 case IrOpcode::kInt32MulWithOverflow: | 1913 case IrOpcode::kInt32MulWithOverflow: |
1669 cont->OverwriteAndNegateIfEqual(kNotEqual); | 1914 cont->OverwriteAndNegateIfEqual(kNotEqual); |
1670 return EmitInt32MulWithOverflow(selector, node, cont); | 1915 return VisitBin32op( |
| 1916 selector, node, kS390_Mul32WithOverflow, |
| 1917 OperandMode::kInt32Imm | OperandMode::kAllowDistinctOps, |
| 1918 cont); |
1671 #if V8_TARGET_ARCH_S390X | 1919 #if V8_TARGET_ARCH_S390X |
1672 case IrOpcode::kInt64AddWithOverflow: | 1920 case IrOpcode::kInt64AddWithOverflow: |
1673 cont->OverwriteAndNegateIfEqual(kOverflow); | 1921 cont->OverwriteAndNegateIfEqual(kOverflow); |
1674 return VisitBinop<Int64BinopMatcher>( | 1922 return VisitBinop<Int64BinopMatcher>( |
1675 selector, node, kS390_Add64, kInt32Imm, cont); | 1923 selector, node, kS390_Add64, OperandMode::kInt32Imm, cont); |
1676 case IrOpcode::kInt64SubWithOverflow: | 1924 case IrOpcode::kInt64SubWithOverflow: |
1677 cont->OverwriteAndNegateIfEqual(kOverflow); | 1925 cont->OverwriteAndNegateIfEqual(kOverflow); |
1678 return VisitBinop<Int64BinopMatcher>( | 1926 return VisitBinop<Int64BinopMatcher>( |
1679 selector, node, kS390_Sub64, kInt32Imm_Negate, cont); | 1927 selector, node, kS390_Sub64, OperandMode::kInt32Imm_Negate, |
| 1928 cont); |
1680 #endif | 1929 #endif |
1681 default: | 1930 default: |
1682 break; | 1931 break; |
1683 } | 1932 } |
1684 } | 1933 } |
1685 } | 1934 } |
1686 break; | 1935 break; |
1687 case IrOpcode::kInt32Sub: | 1936 case IrOpcode::kInt32Sub: |
1688 return VisitWord32Compare(selector, value, cont); | 1937 return VisitWord32Compare(selector, value, cont); |
1689 case IrOpcode::kWord32And: | 1938 case IrOpcode::kWord32And: |
1690 return VisitWordCompare(selector, value, kS390_Tst32, cont, true, | 1939 return VisitWordCompare(selector, value, kS390_Tst32, cont, true, |
1691 kUint32Imm); | 1940 OperandMode::kUint32Imm); |
1692 // TODO(mbrandy): Handle? | 1941 // TODO(mbrandy): Handle? |
1693 // case IrOpcode::kInt32Add: | 1942 // case IrOpcode::kInt32Add: |
1694 // case IrOpcode::kWord32Or: | 1943 // case IrOpcode::kWord32Or: |
1695 // case IrOpcode::kWord32Xor: | 1944 // case IrOpcode::kWord32Xor: |
1696 // case IrOpcode::kWord32Sar: | 1945 // case IrOpcode::kWord32Sar: |
1697 // case IrOpcode::kWord32Shl: | 1946 // case IrOpcode::kWord32Shl: |
1698 // case IrOpcode::kWord32Shr: | 1947 // case IrOpcode::kWord32Shr: |
1699 // case IrOpcode::kWord32Ror: | 1948 // case IrOpcode::kWord32Ror: |
1700 #if V8_TARGET_ARCH_S390X | 1949 #if V8_TARGET_ARCH_S390X |
1701 case IrOpcode::kInt64Sub: | 1950 case IrOpcode::kInt64Sub: |
1702 return VisitWord64Compare(selector, value, cont); | 1951 return VisitWord64Compare(selector, value, cont); |
1703 case IrOpcode::kWord64And: | 1952 case IrOpcode::kWord64And: |
1704 return VisitWordCompare(selector, value, kS390_Tst64, cont, true, | 1953 return VisitWordCompare(selector, value, kS390_Tst64, cont, true, |
1705 kUint32Imm); | 1954 OperandMode::kUint32Imm); |
1706 // TODO(mbrandy): Handle? | 1955 // TODO(mbrandy): Handle? |
1707 // case IrOpcode::kInt64Add: | 1956 // case IrOpcode::kInt64Add: |
1708 // case IrOpcode::kWord64Or: | 1957 // case IrOpcode::kWord64Or: |
1709 // case IrOpcode::kWord64Xor: | 1958 // case IrOpcode::kWord64Xor: |
1710 // case IrOpcode::kWord64Sar: | 1959 // case IrOpcode::kWord64Sar: |
1711 // case IrOpcode::kWord64Shl: | 1960 // case IrOpcode::kWord64Shl: |
1712 // case IrOpcode::kWord64Shr: | 1961 // case IrOpcode::kWord64Shr: |
1713 // case IrOpcode::kWord64Ror: | 1962 // case IrOpcode::kWord64Ror: |
1714 #endif | 1963 #endif |
1715 default: | 1964 default: |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1773 size_t table_time_cost = 3; | 2022 size_t table_time_cost = 3; |
1774 size_t lookup_space_cost = 3 + 2 * sw.case_count; | 2023 size_t lookup_space_cost = 3 + 2 * sw.case_count; |
1775 size_t lookup_time_cost = sw.case_count; | 2024 size_t lookup_time_cost = sw.case_count; |
1776 if (sw.case_count > 0 && | 2025 if (sw.case_count > 0 && |
1777 table_space_cost + 3 * table_time_cost <= | 2026 table_space_cost + 3 * table_time_cost <= |
1778 lookup_space_cost + 3 * lookup_time_cost && | 2027 lookup_space_cost + 3 * lookup_time_cost && |
1779 sw.min_value > std::numeric_limits<int32_t>::min()) { | 2028 sw.min_value > std::numeric_limits<int32_t>::min()) { |
1780 InstructionOperand index_operand = value_operand; | 2029 InstructionOperand index_operand = value_operand; |
1781 if (sw.min_value) { | 2030 if (sw.min_value) { |
1782 index_operand = g.TempRegister(); | 2031 index_operand = g.TempRegister(); |
1783 Emit(kS390_Sub32, index_operand, value_operand, | 2032 Emit(kS390_Lay | AddressingModeField::encode(kMode_MRI), index_operand, |
1784 g.TempImmediate(sw.min_value)); | 2033 value_operand, g.TempImmediate(-sw.min_value)); |
1785 } | 2034 } |
| 2035 #if V8_TARGET_ARCH_S390X |
| 2036 InstructionOperand index_operand_zero_ext = g.TempRegister(); |
| 2037 Emit(kS390_Uint32ToUint64, index_operand_zero_ext, index_operand); |
| 2038 index_operand = index_operand_zero_ext; |
| 2039 #endif |
1786 // Generate a table lookup. | 2040 // Generate a table lookup. |
1787 return EmitTableSwitch(sw, index_operand); | 2041 return EmitTableSwitch(sw, index_operand); |
1788 } | 2042 } |
1789 | 2043 |
1790 // Generate a sequence of conditional jumps. | 2044 // Generate a sequence of conditional jumps. |
1791 return EmitLookupSwitch(sw, value_operand); | 2045 return EmitLookupSwitch(sw, value_operand); |
1792 } | 2046 } |
1793 | 2047 |
1794 void InstructionSelector::VisitWord32Equal(Node* const node) { | 2048 void InstructionSelector::VisitWord32Equal(Node* const node) { |
1795 FlagsContinuation cont = FlagsContinuation::ForSet(kEqual, node); | 2049 FlagsContinuation cont = FlagsContinuation::ForSet(kEqual, node); |
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2046 // static | 2300 // static |
2047 MachineOperatorBuilder::AlignmentRequirements | 2301 MachineOperatorBuilder::AlignmentRequirements |
2048 InstructionSelector::AlignmentRequirements() { | 2302 InstructionSelector::AlignmentRequirements() { |
2049 return MachineOperatorBuilder::AlignmentRequirements:: | 2303 return MachineOperatorBuilder::AlignmentRequirements:: |
2050 FullUnalignedAccessSupport(); | 2304 FullUnalignedAccessSupport(); |
2051 } | 2305 } |
2052 | 2306 |
2053 } // namespace compiler | 2307 } // namespace compiler |
2054 } // namespace internal | 2308 } // namespace internal |
2055 } // namespace v8 | 2309 } // namespace v8 |
OLD | NEW |