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

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

Issue 2722313003: s390: optimize for int 64-bit operation and cleanup (Closed)
Patch Set: Created 3 years, 9 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/code-generator-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
(...skipping 25 matching lines...) Expand all
36 kArithmeticCommonMode = kAllowRM | kAllowRI 36 kArithmeticCommonMode = kAllowRM | kAllowRI
37 }; 37 };
38 38
39 typedef base::Flags<OperandMode, uint32_t> OperandModes; 39 typedef base::Flags<OperandMode, uint32_t> OperandModes;
40 DEFINE_OPERATORS_FOR_FLAGS(OperandModes); 40 DEFINE_OPERATORS_FOR_FLAGS(OperandModes);
41 OperandModes immediateModeMask = 41 OperandModes immediateModeMask =
42 OperandMode::kShift32Imm | OperandMode::kShift64Imm | 42 OperandMode::kShift32Imm | OperandMode::kShift64Imm |
43 OperandMode::kInt32Imm | OperandMode::kInt32Imm_Negate | 43 OperandMode::kInt32Imm | OperandMode::kInt32Imm_Negate |
44 OperandMode::kUint32Imm | OperandMode::kInt20Imm; 44 OperandMode::kUint32Imm | OperandMode::kInt20Imm;
45 45
46 #define AndOperandMode \ 46 #define AndCommonMode \
47 ((OperandMode::kBitWiseCommonMode | OperandMode::kUint32Imm | \ 47 ((OperandMode::kAllowRM | \
48 OperandMode::kAllowRM | (CpuFeatures::IsSupported(DISTINCT_OPS) \ 48 (CpuFeatures::IsSupported(DISTINCT_OPS) ? OperandMode::kAllowRRR \
49 ? OperandMode::kAllowRRR \ 49 : OperandMode::kNone)))
50 : OperandMode::kBitWiseCommonMode))) 50 #define And64OperandMode AndCommonMode
51 #define Or64OperandMode And64OperandMode
52 #define Xor64OperandMode And64OperandMode
51 53
52 #define OrOperandMode AndOperandMode 54 #define And32OperandMode \
53 #define XorOperandMode AndOperandMode 55 (AndCommonMode | OperandMode::kAllowRI | OperandMode::kUint32Imm)
56 #define Or32OperandMode And32OperandMode
57 #define Xor32OperandMode And32OperandMode
54 58
55 #define ShiftOperandMode \ 59 #define Shift32OperandMode \
56 ((OperandMode::kBitWiseCommonMode | OperandMode::kShift64Imm | \ 60 ((OperandMode::kAllowRI | OperandMode::kShift64Imm | \
57 (CpuFeatures::IsSupported(DISTINCT_OPS) \ 61 (CpuFeatures::IsSupported(DISTINCT_OPS) \
58 ? OperandMode::kAllowRRR \ 62 ? (OperandMode::kAllowRRR | OperandMode::kAllowRRI) \
59 : OperandMode::kBitWiseCommonMode))) 63 : OperandMode::kNone)))
64
65 #define Shift64OperandMode \
66 ((OperandMode::kAllowRI | OperandMode::kShift64Imm | \
67 OperandMode::kAllowRRR | OperandMode::kAllowRRI))
60 68
61 #define AddOperandMode \ 69 #define AddOperandMode \
62 ((OperandMode::kArithmeticCommonMode | OperandMode::kInt32Imm | \ 70 ((OperandMode::kArithmeticCommonMode | OperandMode::kInt32Imm | \
63 (CpuFeatures::IsSupported(DISTINCT_OPS) \ 71 (CpuFeatures::IsSupported(DISTINCT_OPS) \
64 ? (OperandMode::kAllowRRR | OperandMode::kAllowRRI) \ 72 ? (OperandMode::kAllowRRR | OperandMode::kAllowRRI) \
65 : OperandMode::kArithmeticCommonMode))) 73 : OperandMode::kArithmeticCommonMode)))
66 #define SubOperandMode \ 74 #define SubOperandMode \
67 ((OperandMode::kArithmeticCommonMode | OperandMode::kInt32Imm_Negate | \ 75 ((OperandMode::kArithmeticCommonMode | OperandMode::kInt32Imm_Negate | \
68 (CpuFeatures::IsSupported(DISTINCT_OPS) \ 76 (CpuFeatures::IsSupported(DISTINCT_OPS) \
69 ? (OperandMode::kAllowRRR | OperandMode::kAllowRRI) \ 77 ? (OperandMode::kAllowRRR | OperandMode::kAllowRRI) \
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
234 242
235 bool Is64BitOperand(Node* node) { 243 bool Is64BitOperand(Node* node) {
236 return MachineRepresentation::kWord64 == GetRepresentation(node); 244 return MachineRepresentation::kWord64 == GetRepresentation(node);
237 } 245 }
238 }; 246 };
239 247
240 namespace { 248 namespace {
241 249
242 bool S390OpcodeOnlySupport12BitDisp(ArchOpcode opcode) { 250 bool S390OpcodeOnlySupport12BitDisp(ArchOpcode opcode) {
243 switch (opcode) { 251 switch (opcode) {
252 case kS390_AddFloat:
253 case kS390_AddDouble:
244 case kS390_CmpFloat: 254 case kS390_CmpFloat:
245 case kS390_CmpDouble: 255 case kS390_CmpDouble:
256 case kS390_Float32ToDouble:
246 return true; 257 return true;
247 default: 258 default:
248 return false; 259 return false;
249 } 260 }
250 } 261 }
251 262
252 bool S390OpcodeOnlySupport12BitDisp(InstructionCode op) { 263 bool S390OpcodeOnlySupport12BitDisp(InstructionCode op) {
253 ArchOpcode opcode = ArchOpcodeField::decode(op); 264 ArchOpcode opcode = ArchOpcodeField::decode(op);
254 return S390OpcodeOnlySupport12BitDisp(opcode); 265 return S390OpcodeOnlySupport12BitDisp(opcode);
255 } 266 }
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
312 #else 323 #else
313 switch (node->opcode()) { 324 switch (node->opcode()) {
314 case IrOpcode::kInt32Div: 325 case IrOpcode::kInt32Div:
315 case IrOpcode::kUint32Div: 326 case IrOpcode::kUint32Div:
316 case IrOpcode::kInt32MulHigh: 327 case IrOpcode::kInt32MulHigh:
317 case IrOpcode::kUint32MulHigh: 328 case IrOpcode::kUint32MulHigh:
318 case IrOpcode::kInt32Mod: 329 case IrOpcode::kInt32Mod:
319 case IrOpcode::kUint32Mod: 330 case IrOpcode::kUint32Mod:
320 case IrOpcode::kWord32Clz: 331 case IrOpcode::kWord32Clz:
321 case IrOpcode::kWord32Popcnt: 332 case IrOpcode::kWord32Popcnt:
333 case IrOpcode::kChangeUint32ToUint64:
322 return true; 334 return true;
323 default: 335 default:
324 return false; 336 return false;
325 } 337 }
326 return false; 338 return false;
327 #endif 339 #endif
328 } 340 }
329 341
330 bool ZeroExtendsWord32ToWord64(Node* node) { 342 bool ZeroExtendsWord32ToWord64(Node* node) {
331 #if !V8_TARGET_ARCH_S390X 343 #if !V8_TARGET_ARCH_S390X
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
385 } 397 }
386 #endif 398 #endif
387 } 399 }
388 400
389 void VisitRR(InstructionSelector* selector, ArchOpcode opcode, Node* node) { 401 void VisitRR(InstructionSelector* selector, ArchOpcode opcode, Node* node) {
390 S390OperandGenerator g(selector); 402 S390OperandGenerator g(selector);
391 selector->Emit(opcode, g.DefineAsRegister(node), 403 selector->Emit(opcode, g.DefineAsRegister(node),
392 g.UseRegister(node->InputAt(0))); 404 g.UseRegister(node->InputAt(0)));
393 } 405 }
394 406
395 void VisitRRR(InstructionSelector* selector, ArchOpcode opcode, Node* node) { 407 // TODO(john.yan): Create VisiteShift to match dst = src shift (R+I)
396 S390OperandGenerator g(selector); 408 #if 0
397 selector->Emit(opcode, g.DefineAsRegister(node), 409 void VisitShift() { }
398 g.UseRegister(node->InputAt(0)), 410 #endif
399 g.UseRegister(node->InputAt(1)));
400 }
401 411
402 #if V8_TARGET_ARCH_S390X 412 #if V8_TARGET_ARCH_S390X
403 void VisitRRO(InstructionSelector* selector, ArchOpcode opcode, Node* node,
404 OperandModes operand_mode) {
405 S390OperandGenerator g(selector);
406 selector->Emit(opcode, g.DefineAsRegister(node),
407 g.UseRegister(node->InputAt(0)),
408 g.UseOperand(node->InputAt(1), operand_mode));
409 }
410
411 void VisitTryTruncateDouble(InstructionSelector* selector, ArchOpcode opcode, 413 void VisitTryTruncateDouble(InstructionSelector* selector, ArchOpcode opcode,
412 Node* node) { 414 Node* node) {
413 S390OperandGenerator g(selector); 415 S390OperandGenerator g(selector);
414 InstructionOperand inputs[] = {g.UseRegister(node->InputAt(0))}; 416 InstructionOperand inputs[] = {g.UseRegister(node->InputAt(0))};
415 InstructionOperand outputs[2]; 417 InstructionOperand outputs[2];
416 size_t output_count = 0; 418 size_t output_count = 0;
417 outputs[output_count++] = g.DefineAsRegister(node); 419 outputs[output_count++] = g.DefineAsRegister(node);
418 420
419 Node* success_output = NodeProperties::FindProjection(node, 1); 421 Node* success_output = NodeProperties::FindProjection(node, 1);
420 if (success_output) { 422 if (success_output) {
421 outputs[output_count++] = g.DefineAsRegister(success_output); 423 outputs[output_count++] = g.DefineAsRegister(success_output);
422 } 424 }
423 425
424 selector->Emit(opcode, output_count, outputs, 1, inputs); 426 selector->Emit(opcode, output_count, outputs, 1, inputs);
425 } 427 }
426 #endif 428 #endif
427 429
428 // Shared routine for multiple binary operations. 430 template <class CanCombineWithLoad>
429 template <typename Matcher> 431 void GenerateRightOperands(InstructionSelector* selector, Node* node,
430 void VisitBinop(InstructionSelector* selector, Node* node, 432 Node* right, InstructionCode& opcode,
433 OperandModes& operand_mode,
434 InstructionOperand* inputs, size_t& input_count,
435 CanCombineWithLoad canCombineWithLoad) {
436 S390OperandGenerator g(selector);
437
438 if ((operand_mode & OperandMode::kAllowImmediate) &&
439 g.CanBeImmediate(right, operand_mode)) {
440 inputs[input_count++] = g.UseImmediate(right);
441 // Can only be RI or RRI
442 operand_mode &= OperandMode::kAllowImmediate;
443 } else if (operand_mode & OperandMode::kAllowMemoryOperand) {
444 NodeMatcher mright(right);
445 if (mright.IsLoad() && selector->CanCover(node, right) &&
446 canCombineWithLoad(SelectLoadOpcode(right))) {
447 AddressingMode mode = g.GetEffectiveAddressMemoryOperand(
448 right, inputs, &input_count, OpcodeImmMode(opcode));
449 opcode |= AddressingModeField::encode(mode);
450 operand_mode &= ~OperandMode::kAllowImmediate;
451 if (operand_mode & OperandMode::kAllowRM)
452 operand_mode &= ~OperandMode::kAllowDistinctOps;
453 } else if (operand_mode & OperandMode::kAllowRM) {
454 DCHECK(!(operand_mode & OperandMode::kAllowRRM));
455 inputs[input_count++] = g.UseAnyExceptImmediate(right);
456 // Can not be Immediate
457 operand_mode &=
458 ~OperandMode::kAllowImmediate & ~OperandMode::kAllowDistinctOps;
459 } else if (operand_mode & OperandMode::kAllowRRM) {
460 DCHECK(!(operand_mode & OperandMode::kAllowRM));
461 inputs[input_count++] = g.UseAnyExceptImmediate(right);
462 // Can not be Immediate
463 operand_mode &= ~OperandMode::kAllowImmediate;
464 } else {
465 UNREACHABLE();
466 }
467 } else {
468 inputs[input_count++] = g.UseRegister(right);
469 // Can only be RR or RRR
470 operand_mode &= OperandMode::kAllowRRR;
471 }
472 }
473
474 template <class CanCombineWithLoad>
475 void GenerateBinOpOperands(InstructionSelector* selector, Node* node,
476 Node* left, Node* right, InstructionCode& opcode,
477 OperandModes& operand_mode,
478 InstructionOperand* inputs, size_t& input_count,
479 CanCombineWithLoad canCombineWithLoad) {
480 S390OperandGenerator g(selector);
481 // left is always register
482 InstructionOperand const left_input = g.UseRegister(left);
483 inputs[input_count++] = left_input;
484
485 if (left == right) {
486 inputs[input_count++] = left_input;
487 // Can only be RR or RRR
488 operand_mode &= OperandMode::kAllowRRR;
489 } else {
490 GenerateRightOperands(selector, node, right, opcode, operand_mode, inputs,
491 input_count, canCombineWithLoad);
492 }
493 }
494
495 template <class CanCombineWithLoad>
496 void VisitUnaryOp(InstructionSelector* selector, Node* node,
497 InstructionCode opcode, OperandModes operand_mode,
498 FlagsContinuation* cont,
499 CanCombineWithLoad canCombineWithLoad);
500
501 template <class CanCombineWithLoad>
502 void VisitBinOp(InstructionSelector* selector, Node* node,
431 InstructionCode opcode, OperandModes operand_mode, 503 InstructionCode opcode, OperandModes operand_mode,
432 FlagsContinuation* cont) { 504 FlagsContinuation* cont, CanCombineWithLoad canCombineWithLoad);
505
506 #define VISIT_OP_LIST(V) \
507 V(Word64, Unary, \
508 [](ArchOpcode opcode) { return opcode == kS390_LoadWord64; }) \
509 V(Word64, Bin, [](ArchOpcode opcode) { return opcode == kS390_LoadWord64; }) \
510 V(Float32, Unary, \
511 [](ArchOpcode opcode) { return opcode == kS390_LoadFloat32; }) \
512 V(Float64, Unary, \
513 [](ArchOpcode opcode) { return opcode == kS390_LoadDouble; }) \
514 V(Float32, Bin, \
515 [](ArchOpcode opcode) { return opcode == kS390_LoadFloat32; }) \
516 V(Float64, Bin, [](ArchOpcode opcode) { return opcode == kS390_LoadDouble; })
517
518 #define DECLARE_VISIT_HELPER_FUNCTIONS(type1, type2, canCombineWithLoad) \
519 void Visit##type1##type2##Op( \
520 InstructionSelector* selector, Node* node, InstructionCode opcode, \
521 OperandModes operand_mode, FlagsContinuation* cont) { \
522 Visit##type2##Op(selector, node, opcode, operand_mode, cont, \
523 canCombineWithLoad); \
524 } \
525 void Visit##type1##type2##Op(InstructionSelector* selector, Node* node, \
526 InstructionCode opcode, \
527 OperandModes operand_mode) { \
528 FlagsContinuation cont; \
529 Visit##type1##type2##Op(selector, node, opcode, operand_mode, &cont); \
530 }
531 VISIT_OP_LIST(DECLARE_VISIT_HELPER_FUNCTIONS);
532 #undef DECLARE_VISIT_HELPER_FUNCTIONS
533
534 template <class CanCombineWithLoad>
535 void VisitUnaryOp(InstructionSelector* selector, Node* node,
536 InstructionCode opcode, OperandModes operand_mode,
537 FlagsContinuation* cont,
538 CanCombineWithLoad canCombineWithLoad) {
539 // Just to get rid of unused function warning
540 #define USE_VISITOR(type1, type2, canCombineWithLoad) \
541 { \
542 VisiterType dummy = Visit##type1##type2##Op; \
543 USE(dummy); \
544 }
545 typedef void (*VisiterType)(InstructionSelector * selector, Node * node,
546 InstructionCode opcode,
547 OperandModes operand_mode);
548 VISIT_OP_LIST(USE_VISITOR);
549 #undef USE_VISITOR
550
433 S390OperandGenerator g(selector); 551 S390OperandGenerator g(selector);
434 Matcher m(node); 552 InstructionOperand inputs[8];
435 Node* left = m.left().node();
436 Node* right = m.right().node();
437 InstructionOperand inputs[4];
438 size_t input_count = 0; 553 size_t input_count = 0;
439 InstructionOperand outputs[2]; 554 InstructionOperand outputs[2];
440 size_t output_count = 0; 555 size_t output_count = 0;
556 Node* input = node->InputAt(0);
441 557
442 // TODO(turbofan): match complex addressing modes. 558 GenerateRightOperands(selector, node, input, opcode, operand_mode, inputs,
443 if (left == right) { 559 input_count, canCombineWithLoad);
444 // If both inputs refer to the same operand, enforce allocating a register
445 // for both of them to ensure that we don't end up generating code like
446 // this:
447 //
448 // mov rax, [rbp-0x10]
449 // add rax, [rbp-0x10]
450 // jo label
451 InstructionOperand const input = g.UseRegister(left);
452 inputs[input_count++] = input;
453 inputs[input_count++] = input;
454 } else if (g.CanBeImmediate(right, operand_mode)) {
455 inputs[input_count++] = g.UseRegister(left);
456 inputs[input_count++] = g.UseImmediate(right);
457 } else {
458 if (node->op()->HasProperty(Operator::kCommutative) &&
459 g.CanBeBetterLeftOperand(right)) {
460 std::swap(left, right);
461 }
462 inputs[input_count++] = g.UseRegister(left);
463 inputs[input_count++] = g.UseRegister(right);
464 }
465 560
466 if (cont->IsBranch()) { 561 if (cont->IsBranch()) {
467 inputs[input_count++] = g.Label(cont->true_block()); 562 inputs[input_count++] = g.Label(cont->true_block());
468 inputs[input_count++] = g.Label(cont->false_block()); 563 inputs[input_count++] = g.Label(cont->false_block());
469 } 564 }
470 565
471 if (cont->IsDeoptimize()) { 566 if (!cont->IsDeoptimize()) {
472 // If we can deoptimize as a result of the binop, we need to make sure that 567 // If we can deoptimize as a result of the binop, we need to make sure
473 // the deopt inputs are not overwritten by the binop result. One way 568 // that the deopt inputs are not overwritten by the binop result. One way
474 // to achieve that is to declare the output register as same-as-first. 569 // to achieve that is to declare the output register as same-as-first.
570 outputs[output_count++] = g.DefineAsRegister(node);
571 } else {
475 outputs[output_count++] = g.DefineSameAsFirst(node); 572 outputs[output_count++] = g.DefineSameAsFirst(node);
476 } else {
477 outputs[output_count++] = g.DefineAsRegister(node);
478 } 573 }
574
479 if (cont->IsSet()) { 575 if (cont->IsSet()) {
480 outputs[output_count++] = g.DefineAsRegister(cont->result()); 576 outputs[output_count++] = g.DefineAsRegister(cont->result());
481 } 577 }
482 578
483 DCHECK_NE(0u, input_count); 579 DCHECK_NE(0u, input_count);
484 DCHECK_NE(0u, output_count); 580 DCHECK_NE(0u, output_count);
485 DCHECK_GE(arraysize(inputs), input_count); 581 DCHECK_GE(arraysize(inputs), input_count);
486 DCHECK_GE(arraysize(outputs), output_count); 582 DCHECK_GE(arraysize(outputs), output_count);
487 583
488 opcode = cont->Encode(opcode); 584 opcode = cont->Encode(opcode);
585
489 if (cont->IsDeoptimize()) { 586 if (cont->IsDeoptimize()) {
490 selector->EmitDeoptimize(opcode, output_count, outputs, input_count, inputs, 587 selector->EmitDeoptimize(opcode, output_count, outputs, input_count, inputs,
491 cont->kind(), cont->reason(), cont->frame_state()); 588 cont->kind(), cont->reason(), cont->frame_state());
492 } else if (cont->IsTrap()) { 589 } else if (cont->IsTrap()) {
493 inputs[input_count++] = g.UseImmediate(cont->trap_id()); 590 inputs[input_count++] = g.UseImmediate(cont->trap_id());
494 selector->Emit(opcode, output_count, outputs, input_count, inputs); 591 selector->Emit(opcode, output_count, outputs, input_count, inputs);
495 } else { 592 } else {
496 selector->Emit(opcode, output_count, outputs, input_count, inputs); 593 selector->Emit(opcode, output_count, outputs, input_count, inputs);
497 } 594 }
498 } 595 }
499 596
500 // Shared routine for multiple binary operations. 597 template <class CanCombineWithLoad>
501 template <typename Matcher> 598 void VisitBinOp(InstructionSelector* selector, Node* node,
502 void VisitBinop(InstructionSelector* selector, Node* node, ArchOpcode opcode, 599 InstructionCode opcode, OperandModes operand_mode,
503 OperandModes operand_mode) { 600 FlagsContinuation* cont,
504 FlagsContinuation cont; 601 CanCombineWithLoad canCombineWithLoad) {
505 VisitBinop<Matcher>(selector, node, opcode, operand_mode, &cont); 602 S390OperandGenerator g(selector);
603 Int32BinopMatcher m(node);
604 Node* left = m.left().node();
605 Node* right = m.right().node();
606 InstructionOperand inputs[8];
607 size_t input_count = 0;
608 InstructionOperand outputs[2];
609 size_t output_count = 0;
610
611 if (node->op()->HasProperty(Operator::kCommutative) &&
612 !g.CanBeImmediate(right, operand_mode) &&
613 (g.CanBeBetterLeftOperand(right))) {
614 std::swap(left, right);
615 }
616
617 GenerateBinOpOperands(selector, node, left, right, opcode, operand_mode,
618 inputs, input_count, canCombineWithLoad);
619
620 if (cont->IsBranch()) {
621 inputs[input_count++] = g.Label(cont->true_block());
622 inputs[input_count++] = g.Label(cont->false_block());
623 }
624
625 if ((operand_mode & OperandMode::kAllowDistinctOps) &&
626 // If we can deoptimize as a result of the binop, we need to make sure
627 // that the deopt inputs are not overwritten by the binop result. One way
628 // to achieve that is to declare the output register as same-as-first.
629 !cont->IsDeoptimize()) {
630 outputs[output_count++] = g.DefineAsRegister(node);
631 } else {
632 outputs[output_count++] = g.DefineSameAsFirst(node);
633 }
634
635 if (cont->IsSet()) {
636 outputs[output_count++] = g.DefineAsRegister(cont->result());
637 }
638
639 DCHECK_NE(0u, input_count);
640 DCHECK_NE(0u, output_count);
641 DCHECK_GE(arraysize(inputs), input_count);
642 DCHECK_GE(arraysize(outputs), output_count);
643
644 opcode = cont->Encode(opcode);
645
646 if (cont->IsDeoptimize()) {
647 selector->EmitDeoptimize(opcode, output_count, outputs, input_count, inputs,
648 cont->kind(), cont->reason(), cont->frame_state());
649 } else if (cont->IsTrap()) {
650 inputs[input_count++] = g.UseImmediate(cont->trap_id());
651 selector->Emit(opcode, output_count, outputs, input_count, inputs);
652 } else {
653 selector->Emit(opcode, output_count, outputs, input_count, inputs);
654 }
506 } 655 }
507 656
508 void VisitBin32op(InstructionSelector* selector, Node* node, 657 void VisitBin32op(InstructionSelector* selector, Node* node,
509 InstructionCode opcode, OperandModes operand_mode, 658 InstructionCode opcode, OperandModes operand_mode,
510 FlagsContinuation* cont) { 659 FlagsContinuation* cont) {
511 S390OperandGenerator g(selector); 660 S390OperandGenerator g(selector);
512 Int32BinopMatcher m(node); 661 Int32BinopMatcher m(node);
513 Node* left = m.left().node(); 662 Node* left = m.left().node();
514 Node* right = m.right().node(); 663 Node* right = m.right().node();
515 InstructionOperand inputs[8]; 664 InstructionOperand inputs[8];
(...skipping 17 matching lines...) Expand all
533 std::swap(left, right); 682 std::swap(left, right);
534 } 683 }
535 #else 684 #else
536 if (node->op()->HasProperty(Operator::kCommutative) && 685 if (node->op()->HasProperty(Operator::kCommutative) &&
537 !g.CanBeImmediate(right, operand_mode) && 686 !g.CanBeImmediate(right, operand_mode) &&
538 (g.CanBeBetterLeftOperand(right))) { 687 (g.CanBeBetterLeftOperand(right))) {
539 std::swap(left, right); 688 std::swap(left, right);
540 } 689 }
541 #endif 690 #endif
542 691
543 // left is always register 692 GenerateBinOpOperands(selector, node, left, right, opcode, operand_mode,
544 InstructionOperand const left_input = g.UseRegister(left); 693 inputs, input_count, [](ArchOpcode opcode) {
545 inputs[input_count++] = left_input; 694 return opcode == kS390_LoadWordU32 ||
546 695 opcode == kS390_LoadWordS32;
547 // TODO(turbofan): match complex addressing modes. 696 });
548 if (left == right) {
549 // If both inputs refer to the same operand, enforce allocating a register
550 // for both of them to ensure that we don't end up generating code like
551 // this:
552 //
553 // mov rax, [rbp-0x10]
554 // add rax, [rbp-0x10]
555 // jo label
556 inputs[input_count++] = left_input;
557 // Can only be RR or RRR
558 operand_mode &= OperandMode::kAllowRRR;
559 } else if ((operand_mode & OperandMode::kAllowImmediate) &&
560 g.CanBeImmediate(right, operand_mode)) {
561 inputs[input_count++] = g.UseImmediate(right);
562 // Can only be RI or RRI
563 operand_mode &= OperandMode::kAllowImmediate;
564 } else if (operand_mode & OperandMode::kAllowMemoryOperand) {
565 NodeMatcher mright(right);
566 if (mright.IsLoad() && selector->CanCover(node, right) &&
567 SelectLoadOpcode(right) == kS390_LoadWordU32) {
568 AddressingMode mode =
569 g.GetEffectiveAddressMemoryOperand(right, inputs, &input_count);
570 opcode |= AddressingModeField::encode(mode);
571 operand_mode &= ~OperandMode::kAllowImmediate;
572 if (operand_mode & OperandMode::kAllowRM)
573 operand_mode &= ~OperandMode::kAllowDistinctOps;
574 } else if (operand_mode & OperandMode::kAllowRM) {
575 DCHECK(!(operand_mode & OperandMode::kAllowRRM));
576 inputs[input_count++] = g.Use(right);
577 // Can not be Immediate
578 operand_mode &=
579 ~OperandMode::kAllowImmediate & ~OperandMode::kAllowDistinctOps;
580 } else if (operand_mode & OperandMode::kAllowRRM) {
581 DCHECK(!(operand_mode & OperandMode::kAllowRM));
582 inputs[input_count++] = g.Use(right);
583 // Can not be Immediate
584 operand_mode &= ~OperandMode::kAllowImmediate;
585 } else {
586 UNREACHABLE();
587 }
588 } else {
589 inputs[input_count++] = g.UseRegister(right);
590 // Can only be RR or RRR
591 operand_mode &= OperandMode::kAllowRRR;
592 }
593 697
594 bool doZeroExt = 698 bool doZeroExt =
595 AutoZeroExtendsWord32ToWord64(node) || !ZeroExtendsWord32ToWord64(left); 699 AutoZeroExtendsWord32ToWord64(node) || !ZeroExtendsWord32ToWord64(left);
596 700
597 inputs[input_count++] = 701 inputs[input_count++] =
598 g.TempImmediate(doZeroExt && (!AutoZeroExtendsWord32ToWord64(node))); 702 g.TempImmediate(doZeroExt && (!AutoZeroExtendsWord32ToWord64(node)));
599 703
600 if (cont->IsBranch()) { 704 if (cont->IsBranch()) {
601 inputs[input_count++] = g.Label(cont->true_block()); 705 inputs[input_count++] = g.Label(cont->true_block());
602 inputs[input_count++] = g.Label(cont->false_block()); 706 inputs[input_count++] = g.Label(cont->false_block());
(...skipping 30 matching lines...) Expand all
633 } else { 737 } else {
634 selector->Emit(opcode, output_count, outputs, input_count, inputs); 738 selector->Emit(opcode, output_count, outputs, input_count, inputs);
635 } 739 }
636 } 740 }
637 741
638 void VisitBin32op(InstructionSelector* selector, Node* node, ArchOpcode opcode, 742 void VisitBin32op(InstructionSelector* selector, Node* node, ArchOpcode opcode,
639 OperandModes operand_mode) { 743 OperandModes operand_mode) {
640 FlagsContinuation cont; 744 FlagsContinuation cont;
641 VisitBin32op(selector, node, opcode, operand_mode, &cont); 745 VisitBin32op(selector, node, opcode, operand_mode, &cont);
642 } 746 }
747 #undef VISIT_OP_LIST
643 748
644 } // namespace 749 } // namespace
645 750
646 void InstructionSelector::VisitLoad(Node* node) { 751 void InstructionSelector::VisitLoad(Node* node) {
647 S390OperandGenerator g(this); 752 S390OperandGenerator g(this);
648 ArchOpcode opcode = SelectLoadOpcode(node); 753 ArchOpcode opcode = SelectLoadOpcode(node);
649 InstructionOperand outputs[1]; 754 InstructionOperand outputs[1];
650 outputs[0] = g.DefineAsRegister(node); 755 outputs[0] = g.DefineAsRegister(node);
651 InstructionOperand inputs[3]; 756 InstructionOperand inputs[3];
652 size_t input_count = 0; 757 size_t input_count = 0;
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after
901 int mask_msb = base::bits::CountLeadingZeros64(value); 1006 int mask_msb = base::bits::CountLeadingZeros64(value);
902 int mask_lsb = base::bits::CountTrailingZeros64(value); 1007 int mask_lsb = base::bits::CountTrailingZeros64(value);
903 if ((mask_width == 0) || (mask_msb + mask_width + mask_lsb != 64)) 1008 if ((mask_width == 0) || (mask_msb + mask_width + mask_lsb != 64))
904 return false; 1009 return false;
905 *mb = mask_lsb + mask_width - 1; 1010 *mb = mask_lsb + mask_width - 1;
906 *me = mask_lsb; 1011 *me = mask_lsb;
907 return true; 1012 return true;
908 } 1013 }
909 #endif 1014 #endif
910 1015
911 void InstructionSelector::VisitWord32And(Node* node) { 1016 // TODO(john.yan): use list to simplify general instructions
912 VisitBin32op(this, node, kS390_And32, AndOperandMode); 1017 #define WORD32_BIN_OP_LIST(V) \
913 } 1018 /* V(name, ArchOpcode, OperandModes) */ \
1019 V(Word32And, kS390_And32, And32OperandMode) \
1020 V(Word32Or, kS390_Or32, Or32OperandMode) \
1021 V(Word32Xor, kS390_Xor32, Xor32OperandMode) \
1022 V(Word32Shl, kS390_ShiftLeft32, Shift32OperandMode) \
1023 V(Word32Shr, kS390_ShiftRight32, Shift32OperandMode)
1024
1025 #define VISITOR(name, op, mode) \
1026 void InstructionSelector::Visit##name(Node* node) { \
1027 VisitBin32op(this, node, op, mode); \
1028 }
1029 WORD32_BIN_OP_LIST(VISITOR);
1030 #undef VISITOR
1031 #undef WORD32_BIN_OP_LIST
914 1032
915 #if V8_TARGET_ARCH_S390X 1033 #if V8_TARGET_ARCH_S390X
916 void InstructionSelector::VisitWord64And(Node* node) { 1034 void InstructionSelector::VisitWord64And(Node* node) {
917 S390OperandGenerator g(this); 1035 S390OperandGenerator g(this);
918 Int64BinopMatcher m(node); 1036 Int64BinopMatcher m(node);
919 int mb = 0; 1037 int mb = 0;
920 int me = 0; 1038 int me = 0;
921 if (m.right().HasValue() && IsContiguousMask64(m.right().Value(), &mb, &me)) { 1039 if (m.right().HasValue() && IsContiguousMask64(m.right().Value(), &mb, &me)) {
922 int sh = 0; 1040 int sh = 0;
923 Node* left = m.left().node(); 1041 Node* left = m.left().node();
(...skipping 23 matching lines...) Expand all
947 mask = mb; 1065 mask = mb;
948 } else if (mb == 63) { 1066 } else if (mb == 63) {
949 match = true; 1067 match = true;
950 opcode = kS390_RotLeftAndClearRight64; 1068 opcode = kS390_RotLeftAndClearRight64;
951 mask = me; 1069 mask = me;
952 } else if (sh && me <= sh && m.left().IsWord64Shl()) { 1070 } else if (sh && me <= sh && m.left().IsWord64Shl()) {
953 match = true; 1071 match = true;
954 opcode = kS390_RotLeftAndClear64; 1072 opcode = kS390_RotLeftAndClear64;
955 mask = mb; 1073 mask = mb;
956 } 1074 }
957 if (match) { 1075 if (match && CpuFeatures::IsSupported(GENERAL_INSTR_EXT)) {
958 Emit(opcode, g.DefineAsRegister(node), g.UseRegister(left), 1076 Emit(opcode, g.DefineAsRegister(node), g.UseRegister(left),
959 g.TempImmediate(sh), g.TempImmediate(mask)); 1077 g.TempImmediate(sh), g.TempImmediate(mask));
960 return; 1078 return;
961 } 1079 }
962 } 1080 }
963 } 1081 }
964 VisitBinop<Int64BinopMatcher>(this, node, kS390_And64, 1082 VisitWord64BinOp(this, node, kS390_And64, And64OperandMode);
965 OperandMode::kUint32Imm);
966 }
967 #endif
968
969 void InstructionSelector::VisitWord32Or(Node* node) {
970 VisitBin32op(this, node, kS390_Or32, OrOperandMode);
971 } 1083 }
972 1084
973 #if V8_TARGET_ARCH_S390X
974 void InstructionSelector::VisitWord64Or(Node* node) { 1085 void InstructionSelector::VisitWord64Or(Node* node) {
975 Int64BinopMatcher m(node); 1086 VisitWord64BinOp(this, node, kS390_Or64, Or64OperandMode);
976 VisitBinop<Int64BinopMatcher>(this, node, kS390_Or64,
977 OperandMode::kUint32Imm);
978 }
979 #endif
980
981 void InstructionSelector::VisitWord32Xor(Node* node) {
982 VisitBin32op(this, node, kS390_Xor32, XorOperandMode);
983 } 1087 }
984 1088
985 #if V8_TARGET_ARCH_S390X
986 void InstructionSelector::VisitWord64Xor(Node* node) { 1089 void InstructionSelector::VisitWord64Xor(Node* node) {
987 VisitBinop<Int64BinopMatcher>(this, node, kS390_Xor64, 1090 VisitWord64BinOp(this, node, kS390_Xor64, Xor64OperandMode);
988 OperandMode::kUint32Imm);
989 }
990 #endif
991
992 void InstructionSelector::VisitWord32Shl(Node* node) {
993 VisitBin32op(this, node, kS390_ShiftLeft32, ShiftOperandMode);
994 } 1091 }
995 1092
996 #if V8_TARGET_ARCH_S390X
997 void InstructionSelector::VisitWord64Shl(Node* node) { 1093 void InstructionSelector::VisitWord64Shl(Node* node) {
998 S390OperandGenerator g(this); 1094 S390OperandGenerator g(this);
999 Int64BinopMatcher m(node); 1095 Int64BinopMatcher m(node);
1000 // TODO(mbrandy): eliminate left sign extension if right >= 32 1096 // TODO(mbrandy): eliminate left sign extension if right >= 32
1001 if (m.left().IsWord64And() && m.right().IsInRange(0, 63)) { 1097 if (m.left().IsWord64And() && m.right().IsInRange(0, 63)) {
1002 Int64BinopMatcher mleft(m.left().node()); 1098 Int64BinopMatcher mleft(m.left().node());
1003 int sh = m.right().Value(); 1099 int sh = m.right().Value();
1004 int mb; 1100 int mb;
1005 int me; 1101 int me;
1006 if (mleft.right().HasValue() && 1102 if (mleft.right().HasValue() &&
(...skipping 10 matching lines...) Expand all
1017 mask = mb; 1113 mask = mb;
1018 } else if (mb == 63) { 1114 } else if (mb == 63) {
1019 match = true; 1115 match = true;
1020 opcode = kS390_RotLeftAndClearRight64; 1116 opcode = kS390_RotLeftAndClearRight64;
1021 mask = me; 1117 mask = me;
1022 } else if (sh && me <= sh) { 1118 } else if (sh && me <= sh) {
1023 match = true; 1119 match = true;
1024 opcode = kS390_RotLeftAndClear64; 1120 opcode = kS390_RotLeftAndClear64;
1025 mask = mb; 1121 mask = mb;
1026 } 1122 }
1027 if (match) { 1123 if (match && CpuFeatures::IsSupported(GENERAL_INSTR_EXT)) {
1028 Emit(opcode, g.DefineAsRegister(node), 1124 Emit(opcode, g.DefineAsRegister(node),
1029 g.UseRegister(mleft.left().node()), g.TempImmediate(sh), 1125 g.UseRegister(mleft.left().node()), g.TempImmediate(sh),
1030 g.TempImmediate(mask)); 1126 g.TempImmediate(mask));
1031 return; 1127 return;
1032 } 1128 }
1033 } 1129 }
1034 } 1130 }
1035 } 1131 }
1036 VisitRRO(this, kS390_ShiftLeft64, node, OperandMode::kShift64Imm); 1132 VisitWord64BinOp(this, node, kS390_ShiftLeft64, Shift64OperandMode);
1037 }
1038 #endif
1039
1040 void InstructionSelector::VisitWord32Shr(Node* node) {
1041 VisitBin32op(this, node, kS390_ShiftRight32, ShiftOperandMode);
1042 } 1133 }
1043 1134
1044 #if V8_TARGET_ARCH_S390X
1045 void InstructionSelector::VisitWord64Shr(Node* node) { 1135 void InstructionSelector::VisitWord64Shr(Node* node) {
1046 S390OperandGenerator g(this); 1136 S390OperandGenerator g(this);
1047 Int64BinopMatcher m(node); 1137 Int64BinopMatcher m(node);
1048 if (m.left().IsWord64And() && m.right().IsInRange(0, 63)) { 1138 if (m.left().IsWord64And() && m.right().IsInRange(0, 63)) {
1049 Int64BinopMatcher mleft(m.left().node()); 1139 Int64BinopMatcher mleft(m.left().node());
1050 int sh = m.right().Value(); 1140 int sh = m.right().Value();
1051 int mb; 1141 int mb;
1052 int me; 1142 int me;
1053 if (mleft.right().HasValue() && 1143 if (mleft.right().HasValue() &&
1054 IsContiguousMask64((uint64_t)(mleft.right().Value()) >> sh, &mb, &me)) { 1144 IsContiguousMask64((uint64_t)(mleft.right().Value()) >> sh, &mb, &me)) {
(...skipping 15 matching lines...) Expand all
1070 } 1160 }
1071 if (match) { 1161 if (match) {
1072 Emit(opcode, g.DefineAsRegister(node), 1162 Emit(opcode, g.DefineAsRegister(node),
1073 g.UseRegister(mleft.left().node()), g.TempImmediate(sh), 1163 g.UseRegister(mleft.left().node()), g.TempImmediate(sh),
1074 g.TempImmediate(mask)); 1164 g.TempImmediate(mask));
1075 return; 1165 return;
1076 } 1166 }
1077 } 1167 }
1078 } 1168 }
1079 } 1169 }
1080 VisitRRO(this, kS390_ShiftRight64, node, OperandMode::kShift64Imm); 1170 VisitWord64BinOp(this, node, kS390_ShiftRight64, Shift64OperandMode);
1081 } 1171 }
1082 #endif 1172 #endif
1083 1173
1084 void InstructionSelector::VisitWord32Sar(Node* node) { 1174 void InstructionSelector::VisitWord32Sar(Node* node) {
1085 S390OperandGenerator g(this); 1175 S390OperandGenerator g(this);
1086 Int32BinopMatcher m(node); 1176 Int32BinopMatcher m(node);
1087 // Replace with sign extension for (x << K) >> K where K is 16 or 24. 1177 // Replace with sign extension for (x << K) >> K where K is 16 or 24.
1088 if (CanCover(node, m.left().node()) && m.left().IsWord32Shl()) { 1178 if (CanCover(node, m.left().node()) && m.left().IsWord32Shl()) {
1089 Int32BinopMatcher mleft(m.left().node()); 1179 Int32BinopMatcher mleft(m.left().node());
1090 if (mleft.right().Is(16) && m.right().Is(16)) { 1180 if (mleft.right().Is(16) && m.right().Is(16)) {
1091 bool doZeroExt = !ZeroExtendsWord32ToWord64(mleft.left().node()); 1181 bool doZeroExt = !ZeroExtendsWord32ToWord64(mleft.left().node());
1092 Emit(kS390_ExtendSignWord16, 1182 Emit(kS390_ExtendSignWord16,
1093 doZeroExt ? g.DefineAsRegister(node) : g.DefineSameAsFirst(node), 1183 doZeroExt ? g.DefineAsRegister(node) : g.DefineSameAsFirst(node),
1094 g.UseRegister(mleft.left().node()), g.TempImmediate(doZeroExt)); 1184 g.UseRegister(mleft.left().node()), g.TempImmediate(doZeroExt));
1095 return; 1185 return;
1096 } else if (mleft.right().Is(24) && m.right().Is(24)) { 1186 } else if (mleft.right().Is(24) && m.right().Is(24)) {
1097 bool doZeroExt = !ZeroExtendsWord32ToWord64(mleft.left().node()); 1187 bool doZeroExt = !ZeroExtendsWord32ToWord64(mleft.left().node());
1098 Emit(kS390_ExtendSignWord8, 1188 Emit(kS390_ExtendSignWord8,
1099 doZeroExt ? g.DefineAsRegister(node) : g.DefineSameAsFirst(node), 1189 doZeroExt ? g.DefineAsRegister(node) : g.DefineSameAsFirst(node),
1100 g.UseRegister(mleft.left().node()), g.TempImmediate(doZeroExt)); 1190 g.UseRegister(mleft.left().node()), g.TempImmediate(doZeroExt));
1101 return; 1191 return;
1102 } 1192 }
1103 } 1193 }
1104 VisitBin32op(this, node, kS390_ShiftRightArith32, ShiftOperandMode); 1194 VisitBin32op(this, node, kS390_ShiftRightArith32, Shift32OperandMode);
1105 } 1195 }
1106 1196
1107 #if !V8_TARGET_ARCH_S390X 1197 #if !V8_TARGET_ARCH_S390X
1108 void VisitPairBinop(InstructionSelector* selector, InstructionCode opcode, 1198 void VisitPairBinop(InstructionSelector* selector, InstructionCode opcode,
1109 InstructionCode opcode2, Node* node) { 1199 InstructionCode opcode2, Node* node) {
1110 S390OperandGenerator g(selector); 1200 S390OperandGenerator g(selector);
1111 1201
1112 Node* projection1 = NodeProperties::FindProjection(node, 1); 1202 Node* projection1 = NodeProperties::FindProjection(node, 1);
1113 if (projection1) { 1203 if (projection1) {
1114 // We use UseUniqueRegister here to avoid register sharing with the output 1204 // We use UseUniqueRegister here to avoid register sharing with the output
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
1207 VisitPairShift(this, kS390_ShiftRightPair, node); 1297 VisitPairShift(this, kS390_ShiftRightPair, node);
1208 } 1298 }
1209 1299
1210 void InstructionSelector::VisitWord32PairSar(Node* node) { 1300 void InstructionSelector::VisitWord32PairSar(Node* node) {
1211 VisitPairShift(this, kS390_ShiftRightArithPair, node); 1301 VisitPairShift(this, kS390_ShiftRightArithPair, node);
1212 } 1302 }
1213 #endif 1303 #endif
1214 1304
1215 #if V8_TARGET_ARCH_S390X 1305 #if V8_TARGET_ARCH_S390X
1216 void InstructionSelector::VisitWord64Sar(Node* node) { 1306 void InstructionSelector::VisitWord64Sar(Node* node) {
1217 VisitRRO(this, kS390_ShiftRightArith64, node, OperandMode::kShift64Imm); 1307 VisitWord64BinOp(this, node, kS390_ShiftRightArith64, Shift64OperandMode);
1218 } 1308 }
1219 #endif 1309 #endif
1220 1310
1221 void InstructionSelector::VisitWord32Ror(Node* node) { 1311 void InstructionSelector::VisitWord32Ror(Node* node) {
1222 // TODO(john): match dst = ror(src1, src2 + imm) 1312 // TODO(john): match dst = ror(src1, src2 + imm)
1223 VisitBin32op(this, node, kS390_RotRight32, 1313 VisitBin32op(this, node, kS390_RotRight32,
1224 OperandMode::kAllowRI | OperandMode::kAllowRRR | 1314 OperandMode::kAllowRI | OperandMode::kAllowRRR |
1225 OperandMode::kAllowRRI | OperandMode::kShift32Imm); 1315 OperandMode::kAllowRRI | OperandMode::kShift32Imm);
1226 } 1316 }
1227 1317
1228 #if V8_TARGET_ARCH_S390X 1318 #if V8_TARGET_ARCH_S390X
1229 void InstructionSelector::VisitWord64Ror(Node* node) { 1319 void InstructionSelector::VisitWord64Ror(Node* node) {
1230 VisitRRO(this, kS390_RotRight64, node, OperandMode::kShift64Imm); 1320 VisitWord64BinOp(this, node, kS390_RotRight64, Shift64OperandMode);
1231 } 1321 }
1232 #endif 1322 #endif
1233 1323
1234 void InstructionSelector::VisitWord32Clz(Node* node) { 1324 void InstructionSelector::VisitWord32Clz(Node* node) {
1235 VisitRR(this, kS390_Cntlz32, node); 1325 VisitRR(this, kS390_Cntlz32, node);
1236 } 1326 }
1237 1327
1238 #if V8_TARGET_ARCH_S390X 1328 #if V8_TARGET_ARCH_S390X
1239 void InstructionSelector::VisitWord64Clz(Node* node) { 1329 void InstructionSelector::VisitWord64Clz(Node* node) {
1240 S390OperandGenerator g(this); 1330 S390OperandGenerator g(this);
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
1293 Emit(kS390_LoadReverse32RR, g.DefineAsRegister(node), 1383 Emit(kS390_LoadReverse32RR, g.DefineAsRegister(node),
1294 g.UseRegister(node->InputAt(0))); 1384 g.UseRegister(node->InputAt(0)));
1295 } 1385 }
1296 1386
1297 void InstructionSelector::VisitInt32Add(Node* node) { 1387 void InstructionSelector::VisitInt32Add(Node* node) {
1298 VisitBin32op(this, node, kS390_Add32, AddOperandMode); 1388 VisitBin32op(this, node, kS390_Add32, AddOperandMode);
1299 } 1389 }
1300 1390
1301 #if V8_TARGET_ARCH_S390X 1391 #if V8_TARGET_ARCH_S390X
1302 void InstructionSelector::VisitInt64Add(Node* node) { 1392 void InstructionSelector::VisitInt64Add(Node* node) {
1303 VisitBinop<Int64BinopMatcher>(this, node, kS390_Add64, 1393 VisitWord64BinOp(this, node, kS390_Add64, AddOperandMode);
1304 OperandMode::kInt32Imm);
1305 } 1394 }
1306 #endif 1395 #endif
1307 1396
1308 void InstructionSelector::VisitInt32Sub(Node* node) { 1397 void InstructionSelector::VisitInt32Sub(Node* node) {
1309 S390OperandGenerator g(this); 1398 S390OperandGenerator g(this);
1310 Int32BinopMatcher m(node); 1399 Int32BinopMatcher m(node);
1311 if (m.left().Is(0)) { 1400 if (m.left().Is(0)) {
1312 Node* right = m.right().node(); 1401 Node* right = m.right().node();
1313 bool doZeroExt = ZeroExtendsWord32ToWord64(right); 1402 bool doZeroExt = ZeroExtendsWord32ToWord64(right);
1314 Emit(kS390_Neg32, g.DefineAsRegister(node), g.UseRegister(right), 1403 Emit(kS390_Neg32, g.DefineAsRegister(node), g.UseRegister(right),
1315 g.TempImmediate(doZeroExt)); 1404 g.TempImmediate(doZeroExt));
1316 } else { 1405 } else {
1317 VisitBin32op(this, node, kS390_Sub32, SubOperandMode); 1406 VisitBin32op(this, node, kS390_Sub32, SubOperandMode);
1318 } 1407 }
1319 } 1408 }
1320 1409
1321 #if V8_TARGET_ARCH_S390X 1410 #if V8_TARGET_ARCH_S390X
1322 void InstructionSelector::VisitInt64Sub(Node* node) { 1411 void InstructionSelector::VisitInt64Sub(Node* node) {
1323 S390OperandGenerator g(this); 1412 S390OperandGenerator g(this);
1324 Int64BinopMatcher m(node); 1413 Int64BinopMatcher m(node);
1325 if (m.left().Is(0)) { 1414 if (m.left().Is(0)) {
1326 Emit(kS390_Neg64, g.DefineAsRegister(node), 1415 Emit(kS390_Neg64, g.DefineAsRegister(node),
1327 g.UseRegister(m.right().node())); 1416 g.UseRegister(m.right().node()));
1328 } else { 1417 } else {
1329 VisitBinop<Int64BinopMatcher>(this, node, kS390_Sub64, 1418 VisitWord64BinOp(this, node, kS390_Sub64, SubOperandMode);
1330 OperandMode::kInt32Imm_Negate);
1331 } 1419 }
1332 } 1420 }
1333 #endif 1421 #endif
1334 1422
1335 namespace {
1336
1337 void VisitCompare(InstructionSelector* selector, InstructionCode opcode,
1338 InstructionOperand left, InstructionOperand right,
1339 FlagsContinuation* cont);
1340
1341 #if V8_TARGET_ARCH_S390X
1342 void VisitMul(InstructionSelector* selector, Node* node, ArchOpcode opcode) {
1343 S390OperandGenerator g(selector);
1344 Int32BinopMatcher m(node);
1345 Node* left = m.left().node();
1346 Node* right = m.right().node();
1347 if (g.CanBeImmediate(right, OperandMode::kInt32Imm)) {
1348 selector->Emit(opcode, g.DefineSameAsFirst(node), g.UseRegister(left),
1349 g.UseImmediate(right));
1350 } else {
1351 if (g.CanBeBetterLeftOperand(right)) {
1352 std::swap(left, right);
1353 }
1354 selector->Emit(opcode, g.DefineSameAsFirst(node), g.UseRegister(left),
1355 g.Use(right));
1356 }
1357 }
1358 #endif
1359
1360 } // namespace
1361
1362 void InstructionSelector::VisitInt32MulWithOverflow(Node* node) { 1423 void InstructionSelector::VisitInt32MulWithOverflow(Node* node) {
1363 if (Node* ovf = NodeProperties::FindProjection(node, 1)) { 1424 if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
1364 FlagsContinuation cont = FlagsContinuation::ForSet(kNotEqual, ovf); 1425 FlagsContinuation cont = FlagsContinuation::ForSet(kNotEqual, ovf);
1365 return VisitBin32op(this, node, kS390_Mul32WithOverflow, 1426 return VisitBin32op(this, node, kS390_Mul32WithOverflow,
1366 OperandMode::kInt32Imm | OperandMode::kAllowDistinctOps, 1427 OperandMode::kInt32Imm | OperandMode::kAllowDistinctOps,
1367 &cont); 1428 &cont);
1368 } 1429 }
1369 VisitBin32op(this, node, kS390_Mul32, MulOperandMode); 1430 VisitBin32op(this, node, kS390_Mul32, MulOperandMode);
1370 } 1431 }
1371 1432
(...skipping 24 matching lines...) Expand all
1396 Int64BinopMatcher m(node); 1457 Int64BinopMatcher m(node);
1397 Node* left = m.left().node(); 1458 Node* left = m.left().node();
1398 Node* right = m.right().node(); 1459 Node* right = m.right().node();
1399 if (g.CanBeImmediate(right, OperandMode::kInt32Imm) && 1460 if (g.CanBeImmediate(right, OperandMode::kInt32Imm) &&
1400 base::bits::IsPowerOfTwo64(g.GetImmediate(right))) { 1461 base::bits::IsPowerOfTwo64(g.GetImmediate(right))) {
1401 int power = 63 - base::bits::CountLeadingZeros64(g.GetImmediate(right)); 1462 int power = 63 - base::bits::CountLeadingZeros64(g.GetImmediate(right));
1402 Emit(kS390_ShiftLeft64, g.DefineSameAsFirst(node), g.UseRegister(left), 1463 Emit(kS390_ShiftLeft64, g.DefineSameAsFirst(node), g.UseRegister(left),
1403 g.UseImmediate(power)); 1464 g.UseImmediate(power));
1404 return; 1465 return;
1405 } 1466 }
1406 VisitMul(this, node, kS390_Mul64); 1467 VisitWord64BinOp(this, node, kS390_Mul64, MulOperandMode);
1407 } 1468 }
1408 #endif 1469 #endif
1409 1470
1410 void InstructionSelector::VisitInt32MulHigh(Node* node) { 1471 void InstructionSelector::VisitInt32MulHigh(Node* node) {
1411 VisitBin32op(this, node, kS390_MulHigh32, 1472 VisitBin32op(this, node, kS390_MulHigh32,
1412 OperandMode::kInt32Imm | OperandMode::kAllowDistinctOps); 1473 OperandMode::kInt32Imm | OperandMode::kAllowDistinctOps);
1413 } 1474 }
1414 1475
1415 void InstructionSelector::VisitUint32MulHigh(Node* node) { 1476 void InstructionSelector::VisitUint32MulHigh(Node* node) {
1416 VisitBin32op(this, node, kS390_MulHighU32, 1477 VisitBin32op(this, node, kS390_MulHighU32,
1417 OperandMode::kAllowRRM | OperandMode::kAllowRRR); 1478 OperandMode::kAllowRRM | OperandMode::kAllowRRR);
1418 } 1479 }
1419 1480
1420 void InstructionSelector::VisitInt32Div(Node* node) { 1481 void InstructionSelector::VisitInt32Div(Node* node) {
1421 VisitBin32op(this, node, kS390_Div32, 1482 VisitBin32op(this, node, kS390_Div32,
1422 OperandMode::kAllowRRM | OperandMode::kAllowRRR); 1483 OperandMode::kAllowRRM | OperandMode::kAllowRRR);
1423 } 1484 }
1424 1485
1425 #if V8_TARGET_ARCH_S390X 1486 #if V8_TARGET_ARCH_S390X
1426 void InstructionSelector::VisitInt64Div(Node* node) { 1487 void InstructionSelector::VisitInt64Div(Node* node) {
1427 VisitRRR(this, kS390_Div64, node); 1488 VisitWord64BinOp(this, node, kS390_Div64,
1489 OperandMode::kAllowRRM | OperandMode::kAllowRRR);
1428 } 1490 }
1429 #endif 1491 #endif
1430 1492
1431 void InstructionSelector::VisitUint32Div(Node* node) { 1493 void InstructionSelector::VisitUint32Div(Node* node) {
1432 VisitBin32op(this, node, kS390_DivU32, 1494 VisitBin32op(this, node, kS390_DivU32,
1433 OperandMode::kAllowRRM | OperandMode::kAllowRRR); 1495 OperandMode::kAllowRRM | OperandMode::kAllowRRR);
1434 } 1496 }
1435 1497
1436 #if V8_TARGET_ARCH_S390X 1498 #if V8_TARGET_ARCH_S390X
1437 void InstructionSelector::VisitUint64Div(Node* node) { 1499 void InstructionSelector::VisitUint64Div(Node* node) {
1438 VisitRRR(this, kS390_DivU64, node); 1500 VisitWord64BinOp(this, node, kS390_DivU64,
1501 OperandMode::kAllowRRM | OperandMode::kAllowRRR);
1439 } 1502 }
1440 #endif 1503 #endif
1441 1504
1442 void InstructionSelector::VisitInt32Mod(Node* node) { 1505 void InstructionSelector::VisitInt32Mod(Node* node) {
1443 VisitBin32op(this, node, kS390_Mod32, 1506 VisitBin32op(this, node, kS390_Mod32,
1444 OperandMode::kAllowRRM | OperandMode::kAllowRRR); 1507 OperandMode::kAllowRRM | OperandMode::kAllowRRR);
1445 } 1508 }
1446 1509
1447 #if V8_TARGET_ARCH_S390X 1510 #if V8_TARGET_ARCH_S390X
1448 void InstructionSelector::VisitInt64Mod(Node* node) { 1511 void InstructionSelector::VisitInt64Mod(Node* node) {
1449 VisitRRR(this, kS390_Mod64, node); 1512 VisitWord64BinOp(this, node, kS390_Mod64,
1513 OperandMode::kAllowRRM | OperandMode::kAllowRRR);
1450 } 1514 }
1451 #endif 1515 #endif
1452 1516
1453 void InstructionSelector::VisitUint32Mod(Node* node) { 1517 void InstructionSelector::VisitUint32Mod(Node* node) {
1454 VisitBin32op(this, node, kS390_ModU32, 1518 VisitBin32op(this, node, kS390_ModU32,
1455 OperandMode::kAllowRRM | OperandMode::kAllowRRR); 1519 OperandMode::kAllowRRM | OperandMode::kAllowRRR);
1456 } 1520 }
1457 1521
1458 #if V8_TARGET_ARCH_S390X 1522 #if V8_TARGET_ARCH_S390X
1459 void InstructionSelector::VisitUint64Mod(Node* node) { 1523 void InstructionSelector::VisitUint64Mod(Node* node) {
1460 VisitRRR(this, kS390_ModU64, node); 1524 VisitWord64BinOp(this, node, kS390_ModU64,
1525 OperandMode::kAllowRRM | OperandMode::kAllowRRR);
1461 } 1526 }
1462 #endif 1527 #endif
1463 1528
1464 void InstructionSelector::VisitChangeFloat32ToFloat64(Node* node) { 1529 // TODO(john.yan): place kAllowRM where available
1465 VisitRR(this, kS390_Float32ToDouble, node); 1530 #define VISIT_FLOAT_UNARY_OP_LIST(V) \
1466 } 1531 V(Float32, ChangeFloat32ToFloat64, kS390_Float32ToDouble, \
1532 OperandMode::kAllowRM) \
1533 V(Float32, BitcastFloat32ToInt32, kS390_BitcastFloat32ToInt32, \
1534 OperandMode::kNone) \
1535 V(Float64, TruncateFloat64ToFloat32, kS390_DoubleToFloat32, \
1536 OperandMode::kNone) \
1537 V(Float64, TruncateFloat64ToWord32, kArchTruncateDoubleToI, \
1538 OperandMode::kNone) \
1539 V(Float64, RoundFloat64ToInt32, kS390_DoubleToInt32, OperandMode::kNone) \
1540 V(Float32, TruncateFloat32ToInt32, kS390_Float32ToInt32, OperandMode::kNone) \
1541 V(Float32, TruncateFloat32ToUint32, kS390_Float32ToUint32, \
1542 OperandMode::kNone) \
1543 V(Float64, ChangeFloat64ToInt32, kS390_DoubleToInt32, OperandMode::kNone) \
1544 V(Float64, ChangeFloat64ToUint32, kS390_DoubleToUint32, OperandMode::kNone) \
1545 V(Float64, TruncateFloat64ToUint32, kS390_DoubleToUint32, \
1546 OperandMode::kNone) \
1547 V(Float64, Float64SilenceNaN, kS390_Float64SilenceNaN, OperandMode::kNone) \
1548 V(Float32, Float32Abs, kS390_AbsFloat, OperandMode::kNone) \
1549 V(Float64, Float64Abs, kS390_AbsDouble, OperandMode::kNone) \
1550 V(Float32, Float32Sqrt, kS390_SqrtFloat, OperandMode::kNone) \
1551 V(Float64, Float64Sqrt, kS390_SqrtDouble, OperandMode::kNone) \
1552 V(Float32, Float32RoundDown, kS390_FloorFloat, OperandMode::kNone) \
1553 V(Float64, Float64RoundDown, kS390_FloorDouble, OperandMode::kNone) \
1554 V(Float32, Float32RoundUp, kS390_CeilFloat, OperandMode::kNone) \
1555 V(Float64, Float64RoundUp, kS390_CeilDouble, OperandMode::kNone) \
1556 V(Float32, Float32RoundTruncate, kS390_TruncateFloat, OperandMode::kNone) \
1557 V(Float64, Float64RoundTruncate, kS390_TruncateDouble, OperandMode::kNone) \
1558 V(Float64, Float64RoundTiesAway, kS390_RoundDouble, OperandMode::kNone) \
1559 V(Float32, Float32Neg, kS390_NegFloat, OperandMode::kNone) \
1560 V(Float64, Float64Neg, kS390_NegDouble, OperandMode::kNone)
1561
1562 #define VISIT_WORD64_UNARY_OP_LIST(V) \
1563 V(Word64, TruncateInt64ToInt32, kS390_Int64ToInt32, OperandMode::kNone) \
1564 V(Word64, RoundInt64ToFloat32, kS390_Int64ToFloat32, OperandMode::kNone) \
1565 V(Word64, RoundInt64ToFloat64, kS390_Int64ToDouble, OperandMode::kNone) \
1566 V(Word64, RoundUint64ToFloat32, kS390_Uint64ToFloat32, OperandMode::kNone) \
1567 V(Word64, RoundUint64ToFloat64, kS390_Uint64ToDouble, OperandMode::kNone) \
1568 V(Word64, BitcastInt64ToFloat64, kS390_BitcastInt64ToDouble, \
1569 OperandMode::kNone) \
1570 V(Float64, BitcastFloat64ToInt64, kS390_BitcastDoubleToInt64, \
1571 OperandMode::kNone)
1572
1573 #define DECLARE_UNARY_OP(type, name, op, mode) \
1574 void InstructionSelector::Visit##name(Node* node) { \
1575 Visit##type##UnaryOp(this, node, op, mode); \
1576 }
1577
1578 VISIT_FLOAT_UNARY_OP_LIST(DECLARE_UNARY_OP);
1579
1580 #if V8_TARGET_ARCH_S390X
1581 VISIT_WORD64_UNARY_OP_LIST(DECLARE_UNARY_OP)
1582 #endif
1583
1584 #undef DECLARE_UNARY_OP
1585 #undef VISIT_WORD64_UNARY_OP_LIST
1586 #undef VISIT_FLOAT_UNARY_OP_LIST
1467 1587
1468 void InstructionSelector::VisitRoundInt32ToFloat32(Node* node) { 1588 void InstructionSelector::VisitRoundInt32ToFloat32(Node* node) {
1469 VisitRR(this, kS390_Int32ToFloat32, node); 1589 VisitRR(this, kS390_Int32ToFloat32, node);
1470 } 1590 }
1471 1591
1472 void InstructionSelector::VisitRoundUint32ToFloat32(Node* node) { 1592 void InstructionSelector::VisitRoundUint32ToFloat32(Node* node) {
1473 VisitRR(this, kS390_Uint32ToFloat32, node); 1593 VisitRR(this, kS390_Uint32ToFloat32, node);
1474 } 1594 }
1475 1595
1476 void InstructionSelector::VisitChangeInt32ToFloat64(Node* node) { 1596 void InstructionSelector::VisitChangeInt32ToFloat64(Node* node) {
1477 VisitRR(this, kS390_Int32ToDouble, node); 1597 VisitRR(this, kS390_Int32ToDouble, node);
1478 } 1598 }
1479 1599
1480 void InstructionSelector::VisitChangeUint32ToFloat64(Node* node) { 1600 void InstructionSelector::VisitChangeUint32ToFloat64(Node* node) {
1481 VisitRR(this, kS390_Uint32ToDouble, node); 1601 VisitRR(this, kS390_Uint32ToDouble, node);
1482 } 1602 }
1483 1603
1484 void InstructionSelector::VisitChangeFloat64ToInt32(Node* node) {
1485 VisitRR(this, kS390_DoubleToInt32, node);
1486 }
1487
1488 void InstructionSelector::VisitChangeFloat64ToUint32(Node* node) {
1489 VisitRR(this, kS390_DoubleToUint32, node);
1490 }
1491
1492 void InstructionSelector::VisitTruncateFloat64ToUint32(Node* node) {
1493 VisitRR(this, kS390_DoubleToUint32, node);
1494 }
1495
1496 #if V8_TARGET_ARCH_S390X 1604 #if V8_TARGET_ARCH_S390X
1497 void InstructionSelector::VisitTryTruncateFloat32ToInt64(Node* node) { 1605 void InstructionSelector::VisitTryTruncateFloat32ToInt64(Node* node) {
1498 VisitTryTruncateDouble(this, kS390_Float32ToInt64, node); 1606 VisitTryTruncateDouble(this, kS390_Float32ToInt64, node);
1499 } 1607 }
1500 1608
1501 void InstructionSelector::VisitTryTruncateFloat64ToInt64(Node* node) { 1609 void InstructionSelector::VisitTryTruncateFloat64ToInt64(Node* node) {
1502 VisitTryTruncateDouble(this, kS390_DoubleToInt64, node); 1610 VisitTryTruncateDouble(this, kS390_DoubleToInt64, node);
1503 } 1611 }
1504 1612
1505 void InstructionSelector::VisitTryTruncateFloat32ToUint64(Node* node) { 1613 void InstructionSelector::VisitTryTruncateFloat32ToUint64(Node* node) {
(...skipping 14 matching lines...) Expand all
1520 Node* value = node->InputAt(0); 1628 Node* value = node->InputAt(0);
1521 if (ZeroExtendsWord32ToWord64(value)) { 1629 if (ZeroExtendsWord32ToWord64(value)) {
1522 // These 32-bit operations implicitly zero-extend to 64-bit on x64, so the 1630 // These 32-bit operations implicitly zero-extend to 64-bit on x64, so the
1523 // zero-extension is a no-op. 1631 // zero-extension is a no-op.
1524 return EmitIdentity(node); 1632 return EmitIdentity(node);
1525 } 1633 }
1526 VisitRR(this, kS390_Uint32ToUint64, node); 1634 VisitRR(this, kS390_Uint32ToUint64, node);
1527 } 1635 }
1528 #endif 1636 #endif
1529 1637
1530 void InstructionSelector::VisitTruncateFloat64ToFloat32(Node* node) {
1531 VisitRR(this, kS390_DoubleToFloat32, node);
1532 }
1533
1534 void InstructionSelector::VisitTruncateFloat64ToWord32(Node* node) {
1535 VisitRR(this, kArchTruncateDoubleToI, node);
1536 }
1537
1538 void InstructionSelector::VisitRoundFloat64ToInt32(Node* node) {
1539 VisitRR(this, kS390_DoubleToInt32, node);
1540 }
1541
1542 void InstructionSelector::VisitTruncateFloat32ToInt32(Node* node) {
1543 VisitRR(this, kS390_Float32ToInt32, node);
1544 }
1545
1546 void InstructionSelector::VisitTruncateFloat32ToUint32(Node* node) {
1547 VisitRR(this, kS390_Float32ToUint32, node);
1548 }
1549
1550 #if V8_TARGET_ARCH_S390X
1551 void InstructionSelector::VisitTruncateInt64ToInt32(Node* node) {
1552 // TODO(mbrandy): inspect input to see if nop is appropriate.
1553 VisitRR(this, kS390_Int64ToInt32, node);
1554 }
1555
1556 void InstructionSelector::VisitRoundInt64ToFloat32(Node* node) {
1557 VisitRR(this, kS390_Int64ToFloat32, node);
1558 }
1559
1560 void InstructionSelector::VisitRoundInt64ToFloat64(Node* node) {
1561 VisitRR(this, kS390_Int64ToDouble, node);
1562 }
1563
1564 void InstructionSelector::VisitRoundUint64ToFloat32(Node* node) {
1565 VisitRR(this, kS390_Uint64ToFloat32, node);
1566 }
1567
1568 void InstructionSelector::VisitRoundUint64ToFloat64(Node* node) {
1569 VisitRR(this, kS390_Uint64ToDouble, node);
1570 }
1571 #endif
1572
1573 void InstructionSelector::VisitBitcastFloat32ToInt32(Node* node) {
1574 VisitRR(this, kS390_BitcastFloat32ToInt32, node);
1575 }
1576
1577 #if V8_TARGET_ARCH_S390X
1578 void InstructionSelector::VisitBitcastFloat64ToInt64(Node* node) {
1579 VisitRR(this, kS390_BitcastDoubleToInt64, node);
1580 }
1581 #endif
1582
1583 void InstructionSelector::VisitBitcastInt32ToFloat32(Node* node) { 1638 void InstructionSelector::VisitBitcastInt32ToFloat32(Node* node) {
1584 VisitRR(this, kS390_BitcastInt32ToFloat32, node); 1639 VisitRR(this, kS390_BitcastInt32ToFloat32, node);
1585 } 1640 }
1586 1641
1587 #if V8_TARGET_ARCH_S390X
1588 void InstructionSelector::VisitBitcastInt64ToFloat64(Node* node) {
1589 VisitRR(this, kS390_BitcastInt64ToDouble, node);
1590 }
1591 #endif
1592
1593 void InstructionSelector::VisitFloat32Add(Node* node) { 1642 void InstructionSelector::VisitFloat32Add(Node* node) {
1594 VisitRRR(this, kS390_AddFloat, node); 1643 return VisitFloat32BinOp(this, node, kS390_AddFloat, OperandMode::kAllowRM);
1595 } 1644 }
1596 1645
1597 void InstructionSelector::VisitFloat64Add(Node* node) { 1646 void InstructionSelector::VisitFloat64Add(Node* node) {
1598 // TODO(mbrandy): detect multiply-add 1647 // TODO(mbrandy): detect multiply-add
1599 VisitRRR(this, kS390_AddDouble, node); 1648 return VisitFloat64BinOp(this, node, kS390_AddDouble, OperandMode::kAllowRM);
1600 } 1649 }
1601 1650
1602 void InstructionSelector::VisitFloat32Sub(Node* node) { 1651 void InstructionSelector::VisitFloat32Sub(Node* node) {
1603 VisitRRR(this, kS390_SubFloat, node); 1652 return VisitFloat32BinOp(this, node, kS390_SubFloat, OperandMode::kAllowRM);
1604 } 1653 }
1605 1654
1606 void InstructionSelector::VisitFloat64Sub(Node* node) { 1655 void InstructionSelector::VisitFloat64Sub(Node* node) {
1607 // TODO(mbrandy): detect multiply-subtract 1656 // TODO(mbrandy): detect multiply-subtract
1608 VisitRRR(this, kS390_SubDouble, node); 1657 return VisitFloat64BinOp(this, node, kS390_SubDouble, OperandMode::kAllowRM);
1609 } 1658 }
1610 1659
1611 void InstructionSelector::VisitFloat32Mul(Node* node) { 1660 void InstructionSelector::VisitFloat32Mul(Node* node) {
1612 VisitRRR(this, kS390_MulFloat, node); 1661 return VisitFloat32BinOp(this, node, kS390_MulFloat, OperandMode::kAllowRM);
1613 } 1662 }
1614 1663
1615 void InstructionSelector::VisitFloat64Mul(Node* node) { 1664 void InstructionSelector::VisitFloat64Mul(Node* node) {
1616 // TODO(mbrandy): detect negate 1665 // TODO(mbrandy): detect negate
1617 VisitRRR(this, kS390_MulDouble, node); 1666 return VisitFloat64BinOp(this, node, kS390_MulDouble, OperandMode::kAllowRM);
1618 } 1667 }
1619 1668
1620 void InstructionSelector::VisitFloat32Div(Node* node) { 1669 void InstructionSelector::VisitFloat32Div(Node* node) {
1621 VisitRRR(this, kS390_DivFloat, node); 1670 return VisitFloat32BinOp(this, node, kS390_DivFloat, OperandMode::kAllowRM);
1622 } 1671 }
1623 1672
1624 void InstructionSelector::VisitFloat64Div(Node* node) { 1673 void InstructionSelector::VisitFloat64Div(Node* node) {
1625 VisitRRR(this, kS390_DivDouble, node); 1674 return VisitFloat64BinOp(this, node, kS390_DivDouble, OperandMode::kAllowRM);
1626 } 1675 }
1627 1676
1628 void InstructionSelector::VisitFloat64Mod(Node* node) { 1677 void InstructionSelector::VisitFloat64Mod(Node* node) {
1629 S390OperandGenerator g(this); 1678 S390OperandGenerator g(this);
1630 Emit(kS390_ModDouble, g.DefineAsFixed(node, d1), 1679 Emit(kS390_ModDouble, g.DefineAsFixed(node, d1),
1631 g.UseFixed(node->InputAt(0), d1), g.UseFixed(node->InputAt(1), d2)) 1680 g.UseFixed(node->InputAt(0), d1), g.UseFixed(node->InputAt(1), d2))
1632 ->MarkAsCall(); 1681 ->MarkAsCall();
1633 } 1682 }
1634 1683
1635 void InstructionSelector::VisitFloat32Max(Node* node) { 1684 void InstructionSelector::VisitFloat32Max(Node* node) {
1636 VisitRRR(this, kS390_MaxFloat, node); 1685 return VisitFloat32BinOp(this, node, kS390_MaxFloat, OperandMode::kNone);
1637 } 1686 }
1638 1687
1639 void InstructionSelector::VisitFloat64Max(Node* node) { 1688 void InstructionSelector::VisitFloat64Max(Node* node) {
1640 VisitRRR(this, kS390_MaxDouble, node); 1689 return VisitFloat64BinOp(this, node, kS390_MaxDouble, OperandMode::kNone);
1641 }
1642
1643 void InstructionSelector::VisitFloat64SilenceNaN(Node* node) {
1644 VisitRR(this, kS390_Float64SilenceNaN, node);
1645 } 1690 }
1646 1691
1647 void InstructionSelector::VisitFloat32Min(Node* node) { 1692 void InstructionSelector::VisitFloat32Min(Node* node) {
1648 VisitRRR(this, kS390_MinFloat, node); 1693 return VisitFloat32BinOp(this, node, kS390_MinFloat, OperandMode::kNone);
1649 } 1694 }
1650 1695
1651 void InstructionSelector::VisitFloat64Min(Node* node) { 1696 void InstructionSelector::VisitFloat64Min(Node* node) {
1652 VisitRRR(this, kS390_MinDouble, node); 1697 return VisitFloat64BinOp(this, node, kS390_MinDouble, OperandMode::kNone);
1653 }
1654
1655 void InstructionSelector::VisitFloat32Abs(Node* node) {
1656 VisitRR(this, kS390_AbsFloat, node);
1657 }
1658
1659 void InstructionSelector::VisitFloat64Abs(Node* node) {
1660 VisitRR(this, kS390_AbsDouble, node);
1661 }
1662
1663 void InstructionSelector::VisitFloat32Sqrt(Node* node) {
1664 VisitRR(this, kS390_SqrtFloat, node);
1665 } 1698 }
1666 1699
1667 void InstructionSelector::VisitFloat64Ieee754Unop(Node* node, 1700 void InstructionSelector::VisitFloat64Ieee754Unop(Node* node,
1668 InstructionCode opcode) { 1701 InstructionCode opcode) {
1669 S390OperandGenerator g(this); 1702 S390OperandGenerator g(this);
1670 Emit(opcode, g.DefineAsFixed(node, d1), g.UseFixed(node->InputAt(0), d1)) 1703 Emit(opcode, g.DefineAsFixed(node, d1), g.UseFixed(node->InputAt(0), d1))
1671 ->MarkAsCall(); 1704 ->MarkAsCall();
1672 } 1705 }
1673 1706
1674 void InstructionSelector::VisitFloat64Ieee754Binop(Node* node, 1707 void InstructionSelector::VisitFloat64Ieee754Binop(Node* node,
1675 InstructionCode opcode) { 1708 InstructionCode opcode) {
1676 S390OperandGenerator g(this); 1709 S390OperandGenerator g(this);
1677 Emit(opcode, g.DefineAsFixed(node, d1), g.UseFixed(node->InputAt(0), d1), 1710 Emit(opcode, g.DefineAsFixed(node, d1), g.UseFixed(node->InputAt(0), d1),
1678 g.UseFixed(node->InputAt(1), d2)) 1711 g.UseFixed(node->InputAt(1), d2))
1679 ->MarkAsCall(); 1712 ->MarkAsCall();
1680 } 1713 }
1681 1714
1682 void InstructionSelector::VisitFloat64Sqrt(Node* node) {
1683 VisitRR(this, kS390_SqrtDouble, node);
1684 }
1685
1686 void InstructionSelector::VisitFloat32RoundDown(Node* node) {
1687 VisitRR(this, kS390_FloorFloat, node);
1688 }
1689
1690 void InstructionSelector::VisitFloat64RoundDown(Node* node) {
1691 VisitRR(this, kS390_FloorDouble, node);
1692 }
1693
1694 void InstructionSelector::VisitFloat32RoundUp(Node* node) {
1695 VisitRR(this, kS390_CeilFloat, node);
1696 }
1697
1698 void InstructionSelector::VisitFloat64RoundUp(Node* node) {
1699 VisitRR(this, kS390_CeilDouble, node);
1700 }
1701
1702 void InstructionSelector::VisitFloat32RoundTruncate(Node* node) {
1703 VisitRR(this, kS390_TruncateFloat, node);
1704 }
1705
1706 void InstructionSelector::VisitFloat64RoundTruncate(Node* node) {
1707 VisitRR(this, kS390_TruncateDouble, node);
1708 }
1709
1710 void InstructionSelector::VisitFloat64RoundTiesAway(Node* node) {
1711 VisitRR(this, kS390_RoundDouble, node);
1712 }
1713
1714 void InstructionSelector::VisitFloat32RoundTiesEven(Node* node) { 1715 void InstructionSelector::VisitFloat32RoundTiesEven(Node* node) {
1715 UNREACHABLE(); 1716 UNREACHABLE();
1716 } 1717 }
1717 1718
1718 void InstructionSelector::VisitFloat64RoundTiesEven(Node* node) { 1719 void InstructionSelector::VisitFloat64RoundTiesEven(Node* node) {
1719 UNREACHABLE(); 1720 UNREACHABLE();
1720 } 1721 }
1721 1722
1722 void InstructionSelector::VisitFloat32Neg(Node* node) {
1723 VisitRR(this, kS390_NegFloat, node);
1724 }
1725
1726 void InstructionSelector::VisitFloat64Neg(Node* node) {
1727 VisitRR(this, kS390_NegDouble, node);
1728 }
1729
1730 void InstructionSelector::VisitInt32AddWithOverflow(Node* node) { 1723 void InstructionSelector::VisitInt32AddWithOverflow(Node* node) {
1731 OperandModes mode = AddOperandMode; 1724 OperandModes mode = AddOperandMode;
1732 if (Node* ovf = NodeProperties::FindProjection(node, 1)) { 1725 if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
1733 FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf); 1726 FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf);
1734 return VisitBin32op(this, node, kS390_Add32, mode, &cont); 1727 return VisitBin32op(this, node, kS390_Add32, mode, &cont);
1735 } 1728 }
1736 FlagsContinuation cont; 1729 FlagsContinuation cont;
1737 VisitBin32op(this, node, kS390_Add32, mode, &cont); 1730 VisitBin32op(this, node, kS390_Add32, mode, &cont);
1738 } 1731 }
1739 1732
1740 void InstructionSelector::VisitInt32SubWithOverflow(Node* node) { 1733 void InstructionSelector::VisitInt32SubWithOverflow(Node* node) {
1741 OperandModes mode = SubOperandMode; 1734 OperandModes mode = SubOperandMode;
1742 if (Node* ovf = NodeProperties::FindProjection(node, 1)) { 1735 if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
1743 FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf); 1736 FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf);
1744 return VisitBin32op(this, node, kS390_Sub32, mode, &cont); 1737 return VisitBin32op(this, node, kS390_Sub32, mode, &cont);
1745 } 1738 }
1746 FlagsContinuation cont; 1739 FlagsContinuation cont;
1747 VisitBin32op(this, node, kS390_Sub32, mode, &cont); 1740 VisitBin32op(this, node, kS390_Sub32, mode, &cont);
1748 } 1741 }
1749 1742
1750 #if V8_TARGET_ARCH_S390X 1743 #if V8_TARGET_ARCH_S390X
1751 void InstructionSelector::VisitInt64AddWithOverflow(Node* node) { 1744 void InstructionSelector::VisitInt64AddWithOverflow(Node* node) {
1752 if (Node* ovf = NodeProperties::FindProjection(node, 1)) { 1745 if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
1753 FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf); 1746 FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf);
1754 return VisitBinop<Int64BinopMatcher>(this, node, kS390_Add64, 1747 return VisitWord64BinOp(this, node, kS390_Add64, AddOperandMode, &cont);
1755 OperandMode::kInt32Imm, &cont);
1756 } 1748 }
1757 FlagsContinuation cont; 1749 VisitWord64BinOp(this, node, kS390_Add64, AddOperandMode);
1758 VisitBinop<Int64BinopMatcher>(this, node, kS390_Add64, OperandMode::kInt32Imm,
1759 &cont);
1760 } 1750 }
1761 1751
1762 void InstructionSelector::VisitInt64SubWithOverflow(Node* node) { 1752 void InstructionSelector::VisitInt64SubWithOverflow(Node* node) {
1763 if (Node* ovf = NodeProperties::FindProjection(node, 1)) { 1753 if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
1764 FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf); 1754 FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf);
1765 return VisitBinop<Int64BinopMatcher>(this, node, kS390_Sub64, 1755 return VisitWord64BinOp(this, node, kS390_Sub64, SubOperandMode, &cont);
1766 OperandMode::kInt32Imm_Negate, &cont);
1767 } 1756 }
1768 FlagsContinuation cont; 1757 VisitWord64BinOp(this, node, kS390_Sub64, SubOperandMode);
1769 VisitBinop<Int64BinopMatcher>(this, node, kS390_Sub64,
1770 OperandMode::kInt32Imm_Negate, &cont);
1771 } 1758 }
1772 #endif 1759 #endif
1773 1760
1774 static bool CompareLogical(FlagsContinuation* cont) { 1761 static bool CompareLogical(FlagsContinuation* cont) {
1775 switch (cont->condition()) { 1762 switch (cont->condition()) {
1776 case kUnsignedLessThan: 1763 case kUnsignedLessThan:
1777 case kUnsignedGreaterThanOrEqual: 1764 case kUnsignedGreaterThanOrEqual:
1778 case kUnsignedLessThanOrEqual: 1765 case kUnsignedLessThanOrEqual:
1779 case kUnsignedGreaterThan: 1766 case kUnsignedGreaterThan:
1780 return true; 1767 return true;
(...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after
2122 cont); 2109 cont);
2123 case IrOpcode::kInt32MulWithOverflow: 2110 case IrOpcode::kInt32MulWithOverflow:
2124 cont->OverwriteAndNegateIfEqual(kNotEqual); 2111 cont->OverwriteAndNegateIfEqual(kNotEqual);
2125 return VisitBin32op( 2112 return VisitBin32op(
2126 selector, node, kS390_Mul32WithOverflow, 2113 selector, node, kS390_Mul32WithOverflow,
2127 OperandMode::kInt32Imm | OperandMode::kAllowDistinctOps, 2114 OperandMode::kInt32Imm | OperandMode::kAllowDistinctOps,
2128 cont); 2115 cont);
2129 #if V8_TARGET_ARCH_S390X 2116 #if V8_TARGET_ARCH_S390X
2130 case IrOpcode::kInt64AddWithOverflow: 2117 case IrOpcode::kInt64AddWithOverflow:
2131 cont->OverwriteAndNegateIfEqual(kOverflow); 2118 cont->OverwriteAndNegateIfEqual(kOverflow);
2132 return VisitBinop<Int64BinopMatcher>( 2119 return VisitWord64BinOp(selector, node, kS390_Add64,
2133 selector, node, kS390_Add64, OperandMode::kInt32Imm, cont); 2120 AddOperandMode, cont);
2134 case IrOpcode::kInt64SubWithOverflow: 2121 case IrOpcode::kInt64SubWithOverflow:
2135 cont->OverwriteAndNegateIfEqual(kOverflow); 2122 cont->OverwriteAndNegateIfEqual(kOverflow);
2136 return VisitBinop<Int64BinopMatcher>( 2123 return VisitWord64BinOp(selector, node, kS390_Sub64,
2137 selector, node, kS390_Sub64, OperandMode::kInt32Imm_Negate, 2124 SubOperandMode, cont);
2138 cont);
2139 #endif 2125 #endif
2140 default: 2126 default:
2141 break; 2127 break;
2142 } 2128 }
2143 } 2129 }
2144 } 2130 }
2145 break; 2131 break;
2146 case IrOpcode::kInt32Sub: 2132 case IrOpcode::kInt32Sub:
2147 if (fc == kNotEqual || fc == kEqual) 2133 if (fc == kNotEqual || fc == kEqual)
2148 return VisitWord32Compare(selector, value, cont); 2134 return VisitWord32Compare(selector, value, cont);
2149 break; 2135 break;
2150 case IrOpcode::kWord32And: 2136 case IrOpcode::kWord32And:
2151 return VisitTestUnderMask(selector, value, cont); 2137 return VisitTestUnderMask(selector, value, cont);
2152 case IrOpcode::kLoad: { 2138 case IrOpcode::kLoad: {
2153 LoadRepresentation load_rep = LoadRepresentationOf(value->op()); 2139 LoadRepresentation load_rep = LoadRepresentationOf(value->op());
2154 switch (load_rep.representation()) { 2140 switch (load_rep.representation()) {
2155 case MachineRepresentation::kWord32: 2141 case MachineRepresentation::kWord32:
2156 if (opcode == kS390_LoadAndTestWord32) { 2142 if (opcode == kS390_LoadAndTestWord32) {
2157 return VisitLoadAndTest(selector, opcode, user, value, cont); 2143 return VisitLoadAndTest(selector, opcode, user, value, cont);
2158 } 2144 }
2159 default: 2145 default:
2160 break; 2146 break;
2161 } 2147 }
2162 break; 2148 break;
2163 } 2149 }
2164 case IrOpcode::kInt32Add: 2150 case IrOpcode::kInt32Add:
2165 // can't handle overflow case. 2151 // can't handle overflow case.
2166 break; 2152 break;
2167 case IrOpcode::kWord32Or: 2153 case IrOpcode::kWord32Or:
2168 return VisitBin32op(selector, value, kS390_Or32, OrOperandMode, cont); 2154 if (fc == kNotEqual || fc == kEqual)
2155 return VisitBin32op(selector, value, kS390_Or32, Or32OperandMode,
2156 cont);
2157 break;
2169 case IrOpcode::kWord32Xor: 2158 case IrOpcode::kWord32Xor:
2170 return VisitBin32op(selector, value, kS390_Xor32, XorOperandMode, cont); 2159 if (fc == kNotEqual || fc == kEqual)
2160 return VisitBin32op(selector, value, kS390_Xor32, Xor32OperandMode,
2161 cont);
2162 break;
2171 case IrOpcode::kWord32Sar: 2163 case IrOpcode::kWord32Sar:
2172 case IrOpcode::kWord32Shl: 2164 case IrOpcode::kWord32Shl:
2173 case IrOpcode::kWord32Shr: 2165 case IrOpcode::kWord32Shr:
2174 case IrOpcode::kWord32Ror: 2166 case IrOpcode::kWord32Ror:
2175 // doesn't generate cc, so ignore. 2167 // doesn't generate cc, so ignore.
2176 break; 2168 break;
2177 #if V8_TARGET_ARCH_S390X 2169 #if V8_TARGET_ARCH_S390X
2178 case IrOpcode::kInt64Sub: 2170 case IrOpcode::kInt64Sub:
2179 if (fc == kNotEqual || fc == kEqual) 2171 if (fc == kNotEqual || fc == kEqual)
2180 return VisitWord64Compare(selector, value, cont); 2172 return VisitWord64Compare(selector, value, cont);
2181 break; 2173 break;
2182 case IrOpcode::kWord64And: 2174 case IrOpcode::kWord64And:
2183 return VisitTestUnderMask(selector, value, cont); 2175 return VisitTestUnderMask(selector, value, cont);
2184 case IrOpcode::kInt64Add: 2176 case IrOpcode::kInt64Add:
2185 // can't handle overflow case. 2177 // can't handle overflow case.
2186 break; 2178 break;
2187 case IrOpcode::kWord64Or: 2179 case IrOpcode::kWord64Or:
2188 // TODO(john.yan): need to handle 2180 if (fc == kNotEqual || fc == kEqual)
2181 return VisitWord64BinOp(selector, value, kS390_Or64, Or64OperandMode,
2182 cont);
2189 break; 2183 break;
2190 case IrOpcode::kWord64Xor: 2184 case IrOpcode::kWord64Xor:
2191 // TODO(john.yan): need to handle 2185 if (fc == kNotEqual || fc == kEqual)
2186 return VisitWord64BinOp(selector, value, kS390_Xor64,
2187 Xor64OperandMode, cont);
2192 break; 2188 break;
2193 case IrOpcode::kWord64Sar: 2189 case IrOpcode::kWord64Sar:
2194 case IrOpcode::kWord64Shl: 2190 case IrOpcode::kWord64Shl:
2195 case IrOpcode::kWord64Shr: 2191 case IrOpcode::kWord64Shr:
2196 case IrOpcode::kWord64Ror: 2192 case IrOpcode::kWord64Ror:
2197 // doesn't generate cc, so ignore 2193 // doesn't generate cc, so ignore
2198 break; 2194 break;
2199 #endif 2195 #endif
2200 default: 2196 default:
2201 break; 2197 break;
(...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after
2540 // static 2536 // static
2541 MachineOperatorBuilder::AlignmentRequirements 2537 MachineOperatorBuilder::AlignmentRequirements
2542 InstructionSelector::AlignmentRequirements() { 2538 InstructionSelector::AlignmentRequirements() {
2543 return MachineOperatorBuilder::AlignmentRequirements:: 2539 return MachineOperatorBuilder::AlignmentRequirements::
2544 FullUnalignedAccessSupport(); 2540 FullUnalignedAccessSupport();
2545 } 2541 }
2546 2542
2547 } // namespace compiler 2543 } // namespace compiler
2548 } // namespace internal 2544 } // namespace internal
2549 } // namespace v8 2545 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/s390/code-generator-s390.cc ('k') | src/s390/assembler-s390.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698