Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(136)

Side by Side Diff: src/compiler/s390/instruction-selector-s390.cc

Issue 2649113007: s390: TF Codegen Optimization (Closed)
Patch Set: remove 2 unnecessary unreachables Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/compiler/s390/instruction-scheduler-s390.cc ('k') | src/s390/assembler-s390.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/compiler/s390/instruction-scheduler-s390.cc ('k') | src/s390/assembler-s390.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698