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

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

Issue 2756733002: s390: Unify Visit(Word/Float)(32/64)(Unary/Bin)Op (Closed)
Patch Set: remove unnecessary check 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/macro-assembler-s390.cc » ('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 299 matching lines...) Expand 10 before | Expand all | Expand 10 after
310 case MachineRepresentation::kSimd1x4: // Fall through. 310 case MachineRepresentation::kSimd1x4: // Fall through.
311 case MachineRepresentation::kSimd1x8: // Fall through. 311 case MachineRepresentation::kSimd1x8: // Fall through.
312 case MachineRepresentation::kSimd1x16: // Fall through. 312 case MachineRepresentation::kSimd1x16: // Fall through.
313 case MachineRepresentation::kNone: 313 case MachineRepresentation::kNone:
314 default: 314 default:
315 UNREACHABLE(); 315 UNREACHABLE();
316 } 316 }
317 return opcode; 317 return opcode;
318 } 318 }
319 319
320 bool AutoZeroExtendsWord32ToWord64(Node* node) { 320 #define RESULT_IS_WORD32_LIST(V) \
321 /* Float unary op*/ \
322 V(BitcastFloat32ToInt32) \
323 /* V(TruncateFloat64ToWord32) */ \
324 /* V(RoundFloat64ToInt32) */ \
325 /* V(TruncateFloat32ToInt32) */ \
326 /* V(TruncateFloat32ToUint32) */ \
327 /* V(TruncateFloat64ToUint32) */ \
328 /* V(ChangeFloat64ToInt32) */ \
329 /* V(ChangeFloat64ToUint32) */ \
330 /* Word32 unary op */ \
331 V(Word32Clz) \
332 V(Word32Popcnt) \
333 /* Word32 bin op */ \
334 V(Int32Add) \
335 V(Int32Sub) \
336 V(Int32Mul) \
337 V(Int32AddWithOverflow) \
338 V(Int32SubWithOverflow) \
339 V(Int32MulWithOverflow) \
340 V(Int32MulHigh) \
341 V(Uint32MulHigh) \
342 V(Int32Div) \
343 V(Uint32Div) \
344 V(Int32Mod) \
345 V(Uint32Mod) \
346 V(Word32Ror) \
347 V(Word32And) \
348 V(Word32Or) \
349 V(Word32Xor) \
350 V(Word32Shl) \
351 V(Word32Shr) \
352 V(Word32Sar)
353
354 bool ProduceWord32Result(Node* node) {
321 #if !V8_TARGET_ARCH_S390X 355 #if !V8_TARGET_ARCH_S390X
322 return true; 356 return true;
323 #else 357 #else
324 switch (node->opcode()) { 358 switch (node->opcode()) {
325 case IrOpcode::kInt32Div: 359 #define VISITOR(name) case IrOpcode::k##name:
326 case IrOpcode::kUint32Div: 360 RESULT_IS_WORD32_LIST(VISITOR)
327 case IrOpcode::kInt32MulHigh: 361 #undef VISITOR
328 case IrOpcode::kUint32MulHigh: 362 return true;
329 case IrOpcode::kInt32Mod:
330 case IrOpcode::kUint32Mod:
331 case IrOpcode::kWord32Clz:
332 case IrOpcode::kWord32Popcnt:
333 case IrOpcode::kChangeUint32ToUint64:
334 return true;
335 default:
336 return false;
337 }
338 return false;
339 #endif
340 }
341
342 bool ZeroExtendsWord32ToWord64(Node* node) {
343 #if !V8_TARGET_ARCH_S390X
344 return true;
345 #else
346 switch (node->opcode()) {
347 case IrOpcode::kInt32Add:
348 case IrOpcode::kInt32Sub:
349 case IrOpcode::kWord32And:
350 case IrOpcode::kWord32Or:
351 case IrOpcode::kWord32Xor:
352 case IrOpcode::kWord32Shl:
353 case IrOpcode::kWord32Shr:
354 case IrOpcode::kWord32Sar:
355 case IrOpcode::kInt32Mul:
356 case IrOpcode::kWord32Ror:
357 case IrOpcode::kInt32Div:
358 case IrOpcode::kUint32Div:
359 case IrOpcode::kInt32MulHigh:
360 case IrOpcode::kInt32Mod:
361 case IrOpcode::kUint32Mod:
362 case IrOpcode::kWord32Popcnt:
363 return true;
364 // TODO(john.yan): consider the following case to be valid 363 // TODO(john.yan): consider the following case to be valid
365 // case IrOpcode::kWord32Equal: 364 // case IrOpcode::kWord32Equal:
366 // case IrOpcode::kInt32LessThan: 365 // case IrOpcode::kInt32LessThan:
367 // case IrOpcode::kInt32LessThanOrEqual: 366 // case IrOpcode::kInt32LessThanOrEqual:
368 // case IrOpcode::kUint32LessThan: 367 // case IrOpcode::kUint32LessThan:
369 // case IrOpcode::kUint32LessThanOrEqual: 368 // case IrOpcode::kUint32LessThanOrEqual:
370 // case IrOpcode::kUint32MulHigh: 369 // case IrOpcode::kUint32MulHigh:
371 // // These 32-bit operations implicitly zero-extend to 64-bit on x64, so 370 // // These 32-bit operations implicitly zero-extend to 64-bit on x64, so
372 // the 371 // the
373 // // zero-extension is a no-op. 372 // // zero-extension is a no-op.
(...skipping 17 matching lines...) Expand all
391 default: 390 default:
392 return false; 391 return false;
393 } 392 }
394 } 393 }
395 default: 394 default:
396 return false; 395 return false;
397 } 396 }
398 #endif 397 #endif
399 } 398 }
400 399
401 void VisitRR(InstructionSelector* selector, ArchOpcode opcode, Node* node) { 400 static inline bool DoZeroExtForResult(Node* node) {
402 S390OperandGenerator g(selector); 401 #if V8_TARGET_ARCH_S390X
403 selector->Emit(opcode, g.DefineAsRegister(node), 402 return ProduceWord32Result(node);
404 g.UseRegister(node->InputAt(0))); 403 #else
404 return false;
405 #endif
405 } 406 }
406 407
407 // TODO(john.yan): Create VisiteShift to match dst = src shift (R+I) 408 // TODO(john.yan): Create VisiteShift to match dst = src shift (R+I)
408 #if 0 409 #if 0
409 void VisitShift() { } 410 void VisitShift() { }
410 #endif 411 #endif
411 412
412 #if V8_TARGET_ARCH_S390X 413 #if V8_TARGET_ARCH_S390X
413 void VisitTryTruncateDouble(InstructionSelector* selector, ArchOpcode opcode, 414 void VisitTryTruncateDouble(InstructionSelector* selector, ArchOpcode opcode,
414 Node* node) { 415 Node* node) {
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
496 void VisitUnaryOp(InstructionSelector* selector, Node* node, 497 void VisitUnaryOp(InstructionSelector* selector, Node* node,
497 InstructionCode opcode, OperandModes operand_mode, 498 InstructionCode opcode, OperandModes operand_mode,
498 FlagsContinuation* cont, 499 FlagsContinuation* cont,
499 CanCombineWithLoad canCombineWithLoad); 500 CanCombineWithLoad canCombineWithLoad);
500 501
501 template <class CanCombineWithLoad> 502 template <class CanCombineWithLoad>
502 void VisitBinOp(InstructionSelector* selector, Node* node, 503 void VisitBinOp(InstructionSelector* selector, Node* node,
503 InstructionCode opcode, OperandModes operand_mode, 504 InstructionCode opcode, OperandModes operand_mode,
504 FlagsContinuation* cont, CanCombineWithLoad canCombineWithLoad); 505 FlagsContinuation* cont, CanCombineWithLoad canCombineWithLoad);
505 506
506 #define VISIT_OP_LIST(V) \ 507 // Generate The following variations:
507 V(Word64, Unary, \ 508 // VisitWord32UnaryOp, VisitWord32BinOp,
508 [](ArchOpcode opcode) { return opcode == kS390_LoadWord64; }) \ 509 // VisitWord64UnaryOp, VisitWord64BinOp,
509 V(Word64, Bin, [](ArchOpcode opcode) { return opcode == kS390_LoadWord64; }) \ 510 // VisitFloat32UnaryOp, VisitFloat32BinOp,
510 V(Float32, Unary, \ 511 // VisitFloat64UnaryOp, VisitFloat64BinOp
511 [](ArchOpcode opcode) { return opcode == kS390_LoadFloat32; }) \ 512 #define VISIT_OP_LIST_32(V) \
512 V(Float64, Unary, \ 513 V(Word32, Unary, [](ArchOpcode opcode) { \
513 [](ArchOpcode opcode) { return opcode == kS390_LoadDouble; }) \ 514 return opcode == kS390_LoadWordS32 || opcode == kS390_LoadWordU32; \
514 V(Float32, Bin, \ 515 }) \
515 [](ArchOpcode opcode) { return opcode == kS390_LoadFloat32; }) \ 516 V(Float32, Unary, \
517 [](ArchOpcode opcode) { return opcode == kS390_LoadFloat32; }) \
518 V(Float64, Unary, \
519 [](ArchOpcode opcode) { return opcode == kS390_LoadDouble; }) \
520 V(Word32, Bin, [](ArchOpcode opcode) { \
521 return opcode == kS390_LoadWordS32 || opcode == kS390_LoadWordU32; \
522 }) \
523 V(Float32, Bin, \
524 [](ArchOpcode opcode) { return opcode == kS390_LoadFloat32; }) \
516 V(Float64, Bin, [](ArchOpcode opcode) { return opcode == kS390_LoadDouble; }) 525 V(Float64, Bin, [](ArchOpcode opcode) { return opcode == kS390_LoadDouble; })
517 526
527 #if V8_TARGET_ARCH_S390X
528 #define VISIT_OP_LIST(V) \
529 VISIT_OP_LIST_32(V) \
530 V(Word64, Unary, \
531 [](ArchOpcode opcode) { return opcode == kS390_LoadWord64; }) \
532 V(Word64, Bin, [](ArchOpcode opcode) { return opcode == kS390_LoadWord64; })
533 #else
534 #define VISIT_OP_LIST VISIT_OP_LIST_32
535 #endif
536
518 #define DECLARE_VISIT_HELPER_FUNCTIONS(type1, type2, canCombineWithLoad) \ 537 #define DECLARE_VISIT_HELPER_FUNCTIONS(type1, type2, canCombineWithLoad) \
519 void Visit##type1##type2##Op( \ 538 static inline void Visit##type1##type2##Op( \
520 InstructionSelector* selector, Node* node, InstructionCode opcode, \ 539 InstructionSelector* selector, Node* node, InstructionCode opcode, \
521 OperandModes operand_mode, FlagsContinuation* cont) { \ 540 OperandModes operand_mode, FlagsContinuation* cont) { \
522 Visit##type2##Op(selector, node, opcode, operand_mode, cont, \ 541 Visit##type2##Op(selector, node, opcode, operand_mode, cont, \
523 canCombineWithLoad); \ 542 canCombineWithLoad); \
524 } \ 543 } \
525 void Visit##type1##type2##Op(InstructionSelector* selector, Node* node, \ 544 static inline void Visit##type1##type2##Op( \
526 InstructionCode opcode, \ 545 InstructionSelector* selector, Node* node, InstructionCode opcode, \
527 OperandModes operand_mode) { \ 546 OperandModes operand_mode) { \
528 FlagsContinuation cont; \ 547 FlagsContinuation cont; \
529 Visit##type1##type2##Op(selector, node, opcode, operand_mode, &cont); \ 548 Visit##type1##type2##Op(selector, node, opcode, operand_mode, &cont); \
530 } 549 }
531 VISIT_OP_LIST(DECLARE_VISIT_HELPER_FUNCTIONS); 550 VISIT_OP_LIST(DECLARE_VISIT_HELPER_FUNCTIONS);
532 #undef DECLARE_VISIT_HELPER_FUNCTIONS 551 #undef DECLARE_VISIT_HELPER_FUNCTIONS
552 #undef VISIT_OP_LIST_32
553 #undef VISIT_OP_LIST
533 554
534 template <class CanCombineWithLoad> 555 template <class CanCombineWithLoad>
535 void VisitUnaryOp(InstructionSelector* selector, Node* node, 556 void VisitUnaryOp(InstructionSelector* selector, Node* node,
536 InstructionCode opcode, OperandModes operand_mode, 557 InstructionCode opcode, OperandModes operand_mode,
537 FlagsContinuation* cont, 558 FlagsContinuation* cont,
538 CanCombineWithLoad canCombineWithLoad) { 559 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
551 S390OperandGenerator g(selector); 560 S390OperandGenerator g(selector);
552 InstructionOperand inputs[8]; 561 InstructionOperand inputs[8];
553 size_t input_count = 0; 562 size_t input_count = 0;
554 InstructionOperand outputs[2]; 563 InstructionOperand outputs[2];
555 size_t output_count = 0; 564 size_t output_count = 0;
556 Node* input = node->InputAt(0); 565 Node* input = node->InputAt(0);
557 566
558 GenerateRightOperands(selector, node, input, opcode, operand_mode, inputs, 567 GenerateRightOperands(selector, node, input, opcode, operand_mode, inputs,
559 input_count, canCombineWithLoad); 568 input_count, canCombineWithLoad);
560 569
570 bool input_is_word32 = ProduceWord32Result(input);
571
572 bool doZeroExt = DoZeroExtForResult(node);
573 bool canEliminateZeroExt = input_is_word32;
574
575 if (doZeroExt) {
576 // Add zero-ext indication
577 inputs[input_count++] = g.TempImmediate(!canEliminateZeroExt);
578 }
579
561 if (cont->IsBranch()) { 580 if (cont->IsBranch()) {
562 inputs[input_count++] = g.Label(cont->true_block()); 581 inputs[input_count++] = g.Label(cont->true_block());
563 inputs[input_count++] = g.Label(cont->false_block()); 582 inputs[input_count++] = g.Label(cont->false_block());
564 } 583 }
565 584
566 if (!cont->IsDeoptimize()) { 585 if (!cont->IsDeoptimize()) {
567 // If we can deoptimize as a result of the binop, we need to make sure 586 // If we can deoptimize as a result of the binop, we need to make sure
568 // that the deopt inputs are not overwritten by the binop result. One way 587 // that the deopt inputs are not overwritten by the binop result. One way
569 // to achieve that is to declare the output register as same-as-first. 588 // to achieve that is to declare the output register as same-as-first.
570 outputs[output_count++] = g.DefineAsRegister(node); 589 if (doZeroExt && canEliminateZeroExt) {
590 // we have to make sure result and left use the same register
591 outputs[output_count++] = g.DefineSameAsFirst(node);
592 } else {
593 outputs[output_count++] = g.DefineAsRegister(node);
594 }
571 } else { 595 } else {
572 outputs[output_count++] = g.DefineSameAsFirst(node); 596 outputs[output_count++] = g.DefineSameAsFirst(node);
573 } 597 }
574 598
575 if (cont->IsSet()) { 599 if (cont->IsSet()) {
576 outputs[output_count++] = g.DefineAsRegister(cont->result()); 600 outputs[output_count++] = g.DefineAsRegister(cont->result());
577 } 601 }
578 602
579 DCHECK_NE(0u, input_count); 603 DCHECK_NE(0u, input_count);
580 DCHECK_NE(0u, output_count); 604 DCHECK_NE(0u, output_count);
(...skipping 29 matching lines...) Expand all
610 634
611 if (node->op()->HasProperty(Operator::kCommutative) && 635 if (node->op()->HasProperty(Operator::kCommutative) &&
612 !g.CanBeImmediate(right, operand_mode) && 636 !g.CanBeImmediate(right, operand_mode) &&
613 (g.CanBeBetterLeftOperand(right))) { 637 (g.CanBeBetterLeftOperand(right))) {
614 std::swap(left, right); 638 std::swap(left, right);
615 } 639 }
616 640
617 GenerateBinOpOperands(selector, node, left, right, opcode, operand_mode, 641 GenerateBinOpOperands(selector, node, left, right, opcode, operand_mode,
618 inputs, input_count, canCombineWithLoad); 642 inputs, input_count, canCombineWithLoad);
619 643
644 bool left_is_word32 = ProduceWord32Result(left);
645
646 bool doZeroExt = DoZeroExtForResult(node);
647 bool canEliminateZeroExt = left_is_word32;
648
649 if (doZeroExt) {
650 // Add zero-ext indication
651 inputs[input_count++] = g.TempImmediate(!canEliminateZeroExt);
652 }
653
620 if (cont->IsBranch()) { 654 if (cont->IsBranch()) {
621 inputs[input_count++] = g.Label(cont->true_block()); 655 inputs[input_count++] = g.Label(cont->true_block());
622 inputs[input_count++] = g.Label(cont->false_block()); 656 inputs[input_count++] = g.Label(cont->false_block());
623 } 657 }
624 658
625 if ((operand_mode & OperandMode::kAllowDistinctOps) && 659 if ((operand_mode & OperandMode::kAllowDistinctOps) &&
626 // If we can deoptimize as a result of the binop, we need to make sure 660 // 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 661 // 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. 662 // to achieve that is to declare the output register as same-as-first.
629 !cont->IsDeoptimize()) { 663 !cont->IsDeoptimize()) {
630 outputs[output_count++] = g.DefineAsRegister(node); 664 if (doZeroExt && canEliminateZeroExt) {
665 // we have to make sure result and left use the same register
666 outputs[output_count++] = g.DefineSameAsFirst(node);
667 } else {
668 outputs[output_count++] = g.DefineAsRegister(node);
669 }
631 } else { 670 } else {
632 outputs[output_count++] = g.DefineSameAsFirst(node); 671 outputs[output_count++] = g.DefineSameAsFirst(node);
633 } 672 }
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 }
655 }
656
657 void VisitBin32op(InstructionSelector* selector, Node* node,
658 InstructionCode opcode, OperandModes operand_mode,
659 FlagsContinuation* cont) {
660 S390OperandGenerator g(selector);
661 Int32BinopMatcher m(node);
662 Node* left = m.left().node();
663 Node* right = m.right().node();
664 InstructionOperand inputs[8];
665 size_t input_count = 0;
666 InstructionOperand outputs[2];
667 size_t output_count = 0;
668
669 // match left of TruncateInt64ToInt32
670 if (m.left().IsTruncateInt64ToInt32() && selector->CanCover(node, left)) {
671 left = left->InputAt(0);
672 }
673 // match right of TruncateInt64ToInt32
674 if (m.right().IsTruncateInt64ToInt32() && selector->CanCover(node, right)) {
675 right = right->InputAt(0);
676 }
677
678 #if V8_TARGET_ARCH_S390X
679 if ((ZeroExtendsWord32ToWord64(right) || g.CanBeBetterLeftOperand(right)) &&
680 node->op()->HasProperty(Operator::kCommutative) &&
681 !g.CanBeImmediate(right, operand_mode)) {
682 std::swap(left, right);
683 }
684 #else
685 if (node->op()->HasProperty(Operator::kCommutative) &&
686 !g.CanBeImmediate(right, operand_mode) &&
687 (g.CanBeBetterLeftOperand(right))) {
688 std::swap(left, right);
689 }
690 #endif
691
692 GenerateBinOpOperands(selector, node, left, right, opcode, operand_mode,
693 inputs, input_count, [](ArchOpcode opcode) {
694 return opcode == kS390_LoadWordU32 ||
695 opcode == kS390_LoadWordS32;
696 });
697
698 bool doZeroExt =
699 AutoZeroExtendsWord32ToWord64(node) || !ZeroExtendsWord32ToWord64(left);
700
701 inputs[input_count++] =
702 g.TempImmediate(doZeroExt && (!AutoZeroExtendsWord32ToWord64(node)));
703
704 if (cont->IsBranch()) {
705 inputs[input_count++] = g.Label(cont->true_block());
706 inputs[input_count++] = g.Label(cont->false_block());
707 }
708
709 if (doZeroExt && (operand_mode & OperandMode::kAllowDistinctOps) &&
710 // If we can deoptimize as a result of the binop, we need to make sure
711 // that
712 // the deopt inputs are not overwritten by the binop result. One way
713 // to achieve that is to declare the output register as same-as-first.
714 !cont->IsDeoptimize()) {
715 outputs[output_count++] = g.DefineAsRegister(node);
716 } else {
717 outputs[output_count++] = g.DefineSameAsFirst(node);
718 }
719 673
720 if (cont->IsSet()) { 674 if (cont->IsSet()) {
721 outputs[output_count++] = g.DefineAsRegister(cont->result()); 675 outputs[output_count++] = g.DefineAsRegister(cont->result());
722 } 676 }
723 677
724 DCHECK_NE(0u, input_count); 678 DCHECK_NE(0u, input_count);
725 DCHECK_NE(0u, output_count); 679 DCHECK_NE(0u, output_count);
726 DCHECK_GE(arraysize(inputs), input_count); 680 DCHECK_GE(arraysize(inputs), input_count);
727 DCHECK_GE(arraysize(outputs), output_count); 681 DCHECK_GE(arraysize(outputs), output_count);
728 682
729 opcode = cont->Encode(opcode); 683 opcode = cont->Encode(opcode);
730 684
731 if (cont->IsDeoptimize()) { 685 if (cont->IsDeoptimize()) {
732 selector->EmitDeoptimize(opcode, output_count, outputs, input_count, inputs, 686 selector->EmitDeoptimize(opcode, output_count, outputs, input_count, inputs,
733 cont->kind(), cont->reason(), cont->frame_state()); 687 cont->kind(), cont->reason(), cont->frame_state());
734 } else if (cont->IsTrap()) { 688 } else if (cont->IsTrap()) {
735 inputs[input_count++] = g.UseImmediate(cont->trap_id()); 689 inputs[input_count++] = g.UseImmediate(cont->trap_id());
736 selector->Emit(opcode, output_count, outputs, input_count, inputs); 690 selector->Emit(opcode, output_count, outputs, input_count, inputs);
737 } else { 691 } else {
738 selector->Emit(opcode, output_count, outputs, input_count, inputs); 692 selector->Emit(opcode, output_count, outputs, input_count, inputs);
739 } 693 }
740 } 694 }
741 695
742 void VisitBin32op(InstructionSelector* selector, Node* node, ArchOpcode opcode,
743 OperandModes operand_mode) {
744 FlagsContinuation cont;
745 VisitBin32op(selector, node, opcode, operand_mode, &cont);
746 }
747 #undef VISIT_OP_LIST
748
749 } // namespace 696 } // namespace
750 697
751 void InstructionSelector::VisitLoad(Node* node) { 698 void InstructionSelector::VisitLoad(Node* node) {
752 S390OperandGenerator g(this); 699 S390OperandGenerator g(this);
753 ArchOpcode opcode = SelectLoadOpcode(node); 700 ArchOpcode opcode = SelectLoadOpcode(node);
754 InstructionOperand outputs[1]; 701 InstructionOperand outputs[1];
755 outputs[0] = g.DefineAsRegister(node); 702 outputs[0] = g.DefineAsRegister(node);
756 InstructionOperand inputs[3]; 703 InstructionOperand inputs[3];
757 size_t input_count = 0; 704 size_t input_count = 0;
758 AddressingMode mode = 705 AddressingMode mode =
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after
1006 int mask_msb = base::bits::CountLeadingZeros64(value); 953 int mask_msb = base::bits::CountLeadingZeros64(value);
1007 int mask_lsb = base::bits::CountTrailingZeros64(value); 954 int mask_lsb = base::bits::CountTrailingZeros64(value);
1008 if ((mask_width == 0) || (mask_msb + mask_width + mask_lsb != 64)) 955 if ((mask_width == 0) || (mask_msb + mask_width + mask_lsb != 64))
1009 return false; 956 return false;
1010 *mb = mask_lsb + mask_width - 1; 957 *mb = mask_lsb + mask_width - 1;
1011 *me = mask_lsb; 958 *me = mask_lsb;
1012 return true; 959 return true;
1013 } 960 }
1014 #endif 961 #endif
1015 962
1016 // TODO(john.yan): use list to simplify general instructions
1017 #define WORD32_BIN_OP_LIST(V) \
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
1032
1033 #if V8_TARGET_ARCH_S390X 963 #if V8_TARGET_ARCH_S390X
1034 void InstructionSelector::VisitWord64And(Node* node) { 964 void InstructionSelector::VisitWord64And(Node* node) {
1035 S390OperandGenerator g(this); 965 S390OperandGenerator g(this);
1036 Int64BinopMatcher m(node); 966 Int64BinopMatcher m(node);
1037 int mb = 0; 967 int mb = 0;
1038 int me = 0; 968 int me = 0;
1039 if (m.right().HasValue() && IsContiguousMask64(m.right().Value(), &mb, &me)) { 969 if (m.right().HasValue() && IsContiguousMask64(m.right().Value(), &mb, &me)) {
1040 int sh = 0; 970 int sh = 0;
1041 Node* left = m.left().node(); 971 Node* left = m.left().node();
1042 if ((m.left().IsWord64Shr() || m.left().IsWord64Shl()) && 972 if ((m.left().IsWord64Shr() || m.left().IsWord64Shl()) &&
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1075 if (match && CpuFeatures::IsSupported(GENERAL_INSTR_EXT)) { 1005 if (match && CpuFeatures::IsSupported(GENERAL_INSTR_EXT)) {
1076 Emit(opcode, g.DefineAsRegister(node), g.UseRegister(left), 1006 Emit(opcode, g.DefineAsRegister(node), g.UseRegister(left),
1077 g.TempImmediate(sh), g.TempImmediate(mask)); 1007 g.TempImmediate(sh), g.TempImmediate(mask));
1078 return; 1008 return;
1079 } 1009 }
1080 } 1010 }
1081 } 1011 }
1082 VisitWord64BinOp(this, node, kS390_And64, And64OperandMode); 1012 VisitWord64BinOp(this, node, kS390_And64, And64OperandMode);
1083 } 1013 }
1084 1014
1085 void InstructionSelector::VisitWord64Or(Node* node) {
1086 VisitWord64BinOp(this, node, kS390_Or64, Or64OperandMode);
1087 }
1088
1089 void InstructionSelector::VisitWord64Xor(Node* node) {
1090 VisitWord64BinOp(this, node, kS390_Xor64, Xor64OperandMode);
1091 }
1092
1093 void InstructionSelector::VisitWord64Shl(Node* node) { 1015 void InstructionSelector::VisitWord64Shl(Node* node) {
1094 S390OperandGenerator g(this); 1016 S390OperandGenerator g(this);
1095 Int64BinopMatcher m(node); 1017 Int64BinopMatcher m(node);
1096 // TODO(mbrandy): eliminate left sign extension if right >= 32 1018 // TODO(mbrandy): eliminate left sign extension if right >= 32
1097 if (m.left().IsWord64And() && m.right().IsInRange(0, 63)) { 1019 if (m.left().IsWord64And() && m.right().IsInRange(0, 63)) {
1098 Int64BinopMatcher mleft(m.left().node()); 1020 Int64BinopMatcher mleft(m.left().node());
1099 int sh = m.right().Value(); 1021 int sh = m.right().Value();
1100 int mb; 1022 int mb;
1101 int me; 1023 int me;
1102 if (mleft.right().HasValue() && 1024 if (mleft.right().HasValue() &&
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
1164 g.TempImmediate(mask)); 1086 g.TempImmediate(mask));
1165 return; 1087 return;
1166 } 1088 }
1167 } 1089 }
1168 } 1090 }
1169 } 1091 }
1170 VisitWord64BinOp(this, node, kS390_ShiftRight64, Shift64OperandMode); 1092 VisitWord64BinOp(this, node, kS390_ShiftRight64, Shift64OperandMode);
1171 } 1093 }
1172 #endif 1094 #endif
1173 1095
1174 void InstructionSelector::VisitWord32Sar(Node* node) { 1096 static inline bool TryMatchSignExtInt16OrInt8FromWord32Sar(
1175 S390OperandGenerator g(this); 1097 InstructionSelector* selector, Node* node) {
1098 S390OperandGenerator g(selector);
1176 Int32BinopMatcher m(node); 1099 Int32BinopMatcher m(node);
1177 // Replace with sign extension for (x << K) >> K where K is 16 or 24. 1100 if (selector->CanCover(node, m.left().node()) && m.left().IsWord32Shl()) {
1178 if (CanCover(node, m.left().node()) && m.left().IsWord32Shl()) {
1179 Int32BinopMatcher mleft(m.left().node()); 1101 Int32BinopMatcher mleft(m.left().node());
1180 if (mleft.right().Is(16) && m.right().Is(16)) { 1102 if (mleft.right().Is(16) && m.right().Is(16)) {
1181 bool doZeroExt = !ZeroExtendsWord32ToWord64(mleft.left().node()); 1103 bool canEliminateZeroExt = ProduceWord32Result(mleft.left().node());
1182 Emit(kS390_ExtendSignWord16, 1104 selector->Emit(kS390_ExtendSignWord16,
1183 doZeroExt ? g.DefineAsRegister(node) : g.DefineSameAsFirst(node), 1105 canEliminateZeroExt ? g.DefineSameAsFirst(node)
1184 g.UseRegister(mleft.left().node()), g.TempImmediate(doZeroExt)); 1106 : g.DefineAsRegister(node),
1185 return; 1107 g.UseRegister(mleft.left().node()),
1108 g.TempImmediate(!canEliminateZeroExt));
1109 return true;
1186 } else if (mleft.right().Is(24) && m.right().Is(24)) { 1110 } else if (mleft.right().Is(24) && m.right().Is(24)) {
1187 bool doZeroExt = !ZeroExtendsWord32ToWord64(mleft.left().node()); 1111 bool canEliminateZeroExt = ProduceWord32Result(mleft.left().node());
1188 Emit(kS390_ExtendSignWord8, 1112 selector->Emit(kS390_ExtendSignWord8,
1189 doZeroExt ? g.DefineAsRegister(node) : g.DefineSameAsFirst(node), 1113 canEliminateZeroExt ? g.DefineSameAsFirst(node)
1190 g.UseRegister(mleft.left().node()), g.TempImmediate(doZeroExt)); 1114 : g.DefineAsRegister(node),
1191 return; 1115 g.UseRegister(mleft.left().node()),
1116 g.TempImmediate(!canEliminateZeroExt));
1117 return true;
1192 } 1118 }
1193 } 1119 }
1194 VisitBin32op(this, node, kS390_ShiftRightArith32, Shift32OperandMode); 1120 return false;
1195 } 1121 }
1196 1122
1197 #if !V8_TARGET_ARCH_S390X 1123 #if !V8_TARGET_ARCH_S390X
1198 void VisitPairBinop(InstructionSelector* selector, InstructionCode opcode, 1124 void VisitPairBinop(InstructionSelector* selector, InstructionCode opcode,
1199 InstructionCode opcode2, Node* node) { 1125 InstructionCode opcode2, Node* node) {
1200 S390OperandGenerator g(selector); 1126 S390OperandGenerator g(selector);
1201 1127
1202 Node* projection1 = NodeProperties::FindProjection(node, 1); 1128 Node* projection1 = NodeProperties::FindProjection(node, 1);
1203 if (projection1) { 1129 if (projection1) {
1204 // We use UseUniqueRegister here to avoid register sharing with the output 1130 // We use UseUniqueRegister here to avoid register sharing with the output
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
1295 1221
1296 void InstructionSelector::VisitWord32PairShr(Node* node) { 1222 void InstructionSelector::VisitWord32PairShr(Node* node) {
1297 VisitPairShift(this, kS390_ShiftRightPair, node); 1223 VisitPairShift(this, kS390_ShiftRightPair, node);
1298 } 1224 }
1299 1225
1300 void InstructionSelector::VisitWord32PairSar(Node* node) { 1226 void InstructionSelector::VisitWord32PairSar(Node* node) {
1301 VisitPairShift(this, kS390_ShiftRightArithPair, node); 1227 VisitPairShift(this, kS390_ShiftRightArithPair, node);
1302 } 1228 }
1303 #endif 1229 #endif
1304 1230
1305 #if V8_TARGET_ARCH_S390X
1306 void InstructionSelector::VisitWord64Sar(Node* node) {
1307 VisitWord64BinOp(this, node, kS390_ShiftRightArith64, Shift64OperandMode);
1308 }
1309 #endif
1310
1311 void InstructionSelector::VisitWord32Ror(Node* node) {
1312 // TODO(john): match dst = ror(src1, src2 + imm)
1313 VisitBin32op(this, node, kS390_RotRight32,
1314 OperandMode::kAllowRI | OperandMode::kAllowRRR |
1315 OperandMode::kAllowRRI | OperandMode::kShift32Imm);
1316 }
1317
1318 #if V8_TARGET_ARCH_S390X
1319 void InstructionSelector::VisitWord64Ror(Node* node) {
1320 VisitWord64BinOp(this, node, kS390_RotRight64, Shift64OperandMode);
1321 }
1322 #endif
1323
1324 void InstructionSelector::VisitWord32Clz(Node* node) {
1325 VisitRR(this, kS390_Cntlz32, node);
1326 }
1327
1328 #if V8_TARGET_ARCH_S390X
1329 void InstructionSelector::VisitWord64Clz(Node* node) {
1330 S390OperandGenerator g(this);
1331 Emit(kS390_Cntlz64, g.DefineAsRegister(node),
1332 g.UseRegister(node->InputAt(0)));
1333 }
1334 #endif
1335
1336 void InstructionSelector::VisitWord32Popcnt(Node* node) {
1337 S390OperandGenerator g(this);
1338 Node* value = node->InputAt(0);
1339 Emit(kS390_Popcnt32, g.DefineAsRegister(node), g.UseRegister(value));
1340 }
1341
1342 #if V8_TARGET_ARCH_S390X
1343 void InstructionSelector::VisitWord64Popcnt(Node* node) {
1344 S390OperandGenerator g(this);
1345 Emit(kS390_Popcnt64, g.DefineAsRegister(node),
1346 g.UseRegister(node->InputAt(0)));
1347 }
1348 #endif
1349
1350 void InstructionSelector::VisitWord32Ctz(Node* node) { UNREACHABLE(); } 1231 void InstructionSelector::VisitWord32Ctz(Node* node) { UNREACHABLE(); }
1351 1232
1352 #if V8_TARGET_ARCH_S390X 1233 #if V8_TARGET_ARCH_S390X
1353 void InstructionSelector::VisitWord64Ctz(Node* node) { UNREACHABLE(); } 1234 void InstructionSelector::VisitWord64Ctz(Node* node) { UNREACHABLE(); }
1354 #endif 1235 #endif
1355 1236
1356 void InstructionSelector::VisitWord32ReverseBits(Node* node) { UNREACHABLE(); } 1237 void InstructionSelector::VisitWord32ReverseBits(Node* node) { UNREACHABLE(); }
1357 1238
1358 #if V8_TARGET_ARCH_S390X 1239 #if V8_TARGET_ARCH_S390X
1359 void InstructionSelector::VisitWord64ReverseBits(Node* node) { UNREACHABLE(); } 1240 void InstructionSelector::VisitWord64ReverseBits(Node* node) { UNREACHABLE(); }
(...skipping 17 matching lines...) Expand all
1377 // TODO(john.yan): one of the base and offset can be imm. 1258 // TODO(john.yan): one of the base and offset can be imm.
1378 g.DefineAsRegister(node), g.UseRegister(base), 1259 g.DefineAsRegister(node), g.UseRegister(base),
1379 g.UseRegister(offset)); 1260 g.UseRegister(offset));
1380 return; 1261 return;
1381 } 1262 }
1382 } 1263 }
1383 Emit(kS390_LoadReverse32RR, g.DefineAsRegister(node), 1264 Emit(kS390_LoadReverse32RR, g.DefineAsRegister(node),
1384 g.UseRegister(node->InputAt(0))); 1265 g.UseRegister(node->InputAt(0)));
1385 } 1266 }
1386 1267
1387 void InstructionSelector::VisitInt32Add(Node* node) { 1268 template <class Matcher, ArchOpcode neg_opcode>
1388 VisitBin32op(this, node, kS390_Add32, AddOperandMode); 1269 static inline bool TryMatchNegFromSub(InstructionSelector* selector,
1389 } 1270 Node* node) {
1390 1271 S390OperandGenerator g(selector);
1391 #if V8_TARGET_ARCH_S390X 1272 Matcher m(node);
1392 void InstructionSelector::VisitInt64Add(Node* node) { 1273 static_assert(neg_opcode == kS390_Neg32 || neg_opcode == kS390_Neg64,
1393 VisitWord64BinOp(this, node, kS390_Add64, AddOperandMode); 1274 "Provided opcode is not a Neg opcode.");
1394 }
1395 #endif
1396
1397 void InstructionSelector::VisitInt32Sub(Node* node) {
1398 S390OperandGenerator g(this);
1399 Int32BinopMatcher m(node);
1400 if (m.left().Is(0)) { 1275 if (m.left().Is(0)) {
1401 Node* right = m.right().node(); 1276 Node* value = m.right().node();
1402 bool doZeroExt = ZeroExtendsWord32ToWord64(right); 1277 bool doZeroExt = DoZeroExtForResult(node);
1403 Emit(kS390_Neg32, g.DefineAsRegister(node), g.UseRegister(right), 1278 bool canEliminateZeroExt = ProduceWord32Result(value);
1404 g.TempImmediate(doZeroExt)); 1279 if (doZeroExt) {
1405 } else { 1280 selector->Emit(neg_opcode,
1406 VisitBin32op(this, node, kS390_Sub32, SubOperandMode); 1281 canEliminateZeroExt ? g.DefineSameAsFirst(node)
1407 } 1282 : g.DefineAsRegister(node),
1408 } 1283 g.UseRegister(value),
1409 1284 g.TempImmediate(!canEliminateZeroExt));
1410 #if V8_TARGET_ARCH_S390X 1285 } else {
1411 void InstructionSelector::VisitInt64Sub(Node* node) { 1286 selector->Emit(neg_opcode, g.DefineAsRegister(node),
1412 S390OperandGenerator g(this); 1287 g.UseRegister(value));
1413 Int64BinopMatcher m(node); 1288 }
1414 if (m.left().Is(0)) { 1289 return true;
1415 Emit(kS390_Neg64, g.DefineAsRegister(node), 1290 }
1416 g.UseRegister(m.right().node())); 1291 return false;
1417 } else { 1292 }
1418 VisitWord64BinOp(this, node, kS390_Sub64, SubOperandMode); 1293
1419 } 1294 template <class Matcher, ArchOpcode shift_op>
1420 } 1295 bool TryMatchShiftFromMul(InstructionSelector* selector, Node* node) {
1421 #endif 1296 S390OperandGenerator g(selector);
1422 1297 Matcher m(node);
1423 void InstructionSelector::VisitInt32MulWithOverflow(Node* node) {
1424 if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
1425 FlagsContinuation cont = FlagsContinuation::ForSet(kNotEqual, ovf);
1426 return VisitBin32op(this, node, kS390_Mul32WithOverflow,
1427 OperandMode::kInt32Imm | OperandMode::kAllowDistinctOps,
1428 &cont);
1429 }
1430 VisitBin32op(this, node, kS390_Mul32, MulOperandMode);
1431 }
1432
1433 void InstructionSelector::VisitInt32Mul(Node* node) {
1434 S390OperandGenerator g(this);
1435 Int32BinopMatcher m(node);
1436 Node* left = m.left().node();
1437 Node* right = m.right().node();
1438 if (g.CanBeImmediate(right, OperandMode::kInt32Imm) &&
1439 base::bits::IsPowerOfTwo32(g.GetImmediate(right))) {
1440 int power = 31 - base::bits::CountLeadingZeros32(g.GetImmediate(right));
1441 bool doZeroExt = !ZeroExtendsWord32ToWord64(left);
1442 InstructionOperand dst =
1443 (doZeroExt && CpuFeatures::IsSupported(DISTINCT_OPS))
1444 ? g.DefineAsRegister(node)
1445 : g.DefineSameAsFirst(node);
1446
1447 Emit(kS390_ShiftLeft32, dst, g.UseRegister(left), g.UseImmediate(power),
1448 g.TempImmediate(doZeroExt));
1449 return;
1450 }
1451 VisitBin32op(this, node, kS390_Mul32, MulOperandMode);
1452 }
1453
1454 #if V8_TARGET_ARCH_S390X
1455 void InstructionSelector::VisitInt64Mul(Node* node) {
1456 S390OperandGenerator g(this);
1457 Int64BinopMatcher m(node);
1458 Node* left = m.left().node(); 1298 Node* left = m.left().node();
1459 Node* right = m.right().node(); 1299 Node* right = m.right().node();
1460 if (g.CanBeImmediate(right, OperandMode::kInt32Imm) && 1300 if (g.CanBeImmediate(right, OperandMode::kInt32Imm) &&
1461 base::bits::IsPowerOfTwo64(g.GetImmediate(right))) { 1301 base::bits::IsPowerOfTwo64(g.GetImmediate(right))) {
1462 int power = 63 - base::bits::CountLeadingZeros64(g.GetImmediate(right)); 1302 int power = 63 - base::bits::CountLeadingZeros64(g.GetImmediate(right));
1463 Emit(kS390_ShiftLeft64, g.DefineSameAsFirst(node), g.UseRegister(left), 1303 bool doZeroExt = DoZeroExtForResult(node);
1464 g.UseImmediate(power)); 1304 bool canEliminateZeroExt = ProduceWord32Result(left);
1465 return; 1305 InstructionOperand dst = (doZeroExt && !canEliminateZeroExt &&
1466 } 1306 CpuFeatures::IsSupported(DISTINCT_OPS))
1467 VisitWord64BinOp(this, node, kS390_Mul64, MulOperandMode); 1307 ? g.DefineAsRegister(node)
1308 : g.DefineSameAsFirst(node);
1309
1310 if (doZeroExt) {
1311 selector->Emit(shift_op, dst, g.UseRegister(left), g.UseImmediate(power),
1312 g.TempImmediate(!canEliminateZeroExt));
1313 } else {
1314 selector->Emit(shift_op, dst, g.UseRegister(left), g.UseImmediate(power));
1315 }
1316 return true;
1317 }
1318 return false;
1319 }
1320
1321 template <ArchOpcode opcode>
1322 static inline bool TryMatchInt32OpWithOverflow(InstructionSelector* selector,
1323 Node* node, OperandModes mode) {
1324 if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
1325 FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf);
1326 VisitWord32BinOp(selector, node, opcode, mode, &cont);
1327 return true;
1328 }
1329 return false;
1330 }
1331
1332 static inline bool TryMatchInt32AddWithOverflow(InstructionSelector* selector,
1333 Node* node) {
1334 return TryMatchInt32OpWithOverflow<kS390_Add32>(selector, node,
1335 AddOperandMode);
1336 }
1337
1338 static inline bool TryMatchInt32SubWithOverflow(InstructionSelector* selector,
1339 Node* node) {
1340 return TryMatchInt32OpWithOverflow<kS390_Sub32>(selector, node,
1341 SubOperandMode);
1342 }
1343
1344 static inline bool TryMatchInt32MulWithOverflow(InstructionSelector* selector,
1345 Node* node) {
1346 if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
1347 FlagsContinuation cont = FlagsContinuation::ForSet(kNotEqual, ovf);
1348 VisitWord32BinOp(selector, node, kS390_Mul32WithOverflow,
1349 OperandMode::kInt32Imm | OperandMode::kAllowDistinctOps,
1350 &cont);
1351 return true;
1352 }
1353 return TryMatchShiftFromMul<Int32BinopMatcher, kS390_ShiftLeft32>(selector,
1354 node);
1355 }
1356
1357 #if V8_TARGET_ARCH_S390X
1358 template <ArchOpcode opcode>
1359 static inline bool TryMatchInt64OpWithOverflow(InstructionSelector* selector,
1360 Node* node, OperandModes mode) {
1361 if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
1362 FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf);
1363 VisitWord64BinOp(selector, node, opcode, mode, &cont);
1364 return true;
1365 }
1366 return false;
1367 }
1368
1369 static inline bool TryMatchInt64AddWithOverflow(InstructionSelector* selector,
1370 Node* node) {
1371 return TryMatchInt64OpWithOverflow<kS390_Add64>(selector, node,
1372 AddOperandMode);
1373 }
1374
1375 static inline bool TryMatchInt64SubWithOverflow(InstructionSelector* selector,
1376 Node* node) {
1377 return TryMatchInt64OpWithOverflow<kS390_Sub64>(selector, node,
1378 SubOperandMode);
1468 } 1379 }
1469 #endif 1380 #endif
1470 1381
1471 void InstructionSelector::VisitInt32MulHigh(Node* node) { 1382 #define null ([]() { return false; })
1472 VisitBin32op(this, node, kS390_MulHigh32, 1383 // TODO(john.yan): place kAllowRM where available
1473 OperandMode::kInt32Imm | OperandMode::kAllowDistinctOps); 1384 #define FLOAT_UNARY_OP_LIST_32(V) \
1474 } 1385 V(Float32, ChangeFloat32ToFloat64, kS390_Float32ToDouble, \
1475 1386 OperandMode::kAllowRM, null) \
1476 void InstructionSelector::VisitUint32MulHigh(Node* node) { 1387 V(Float32, BitcastFloat32ToInt32, kS390_BitcastFloat32ToInt32, \
1477 VisitBin32op(this, node, kS390_MulHighU32, 1388 OperandMode::kNone, null) \
1478 OperandMode::kAllowRRM | OperandMode::kAllowRRR); 1389 V(Float64, TruncateFloat64ToFloat32, kS390_DoubleToFloat32, \
1479 } 1390 OperandMode::kNone, null) \
1480 1391 V(Float64, TruncateFloat64ToWord32, kArchTruncateDoubleToI, \
1481 void InstructionSelector::VisitInt32Div(Node* node) { 1392 OperandMode::kNone, null) \
1482 VisitBin32op(this, node, kS390_Div32, 1393 V(Float64, RoundFloat64ToInt32, kS390_DoubleToInt32, OperandMode::kNone, \
1483 OperandMode::kAllowRRM | OperandMode::kAllowRRR); 1394 null) \
1484 } 1395 V(Float32, TruncateFloat32ToInt32, kS390_Float32ToInt32, OperandMode::kNone, \
1396 null) \
1397 V(Float32, TruncateFloat32ToUint32, kS390_Float32ToUint32, \
1398 OperandMode::kNone, null) \
1399 V(Float64, TruncateFloat64ToUint32, kS390_DoubleToUint32, \
1400 OperandMode::kNone, null) \
1401 V(Float64, ChangeFloat64ToInt32, kS390_DoubleToInt32, OperandMode::kNone, \
1402 null) \
1403 V(Float64, ChangeFloat64ToUint32, kS390_DoubleToUint32, OperandMode::kNone, \
1404 null) \
1405 V(Float64, Float64SilenceNaN, kS390_Float64SilenceNaN, OperandMode::kNone, \
1406 null) \
1407 V(Float32, Float32Abs, kS390_AbsFloat, OperandMode::kNone, null) \
1408 V(Float64, Float64Abs, kS390_AbsDouble, OperandMode::kNone, null) \
1409 V(Float32, Float32Sqrt, kS390_SqrtFloat, OperandMode::kNone, null) \
1410 V(Float64, Float64Sqrt, kS390_SqrtDouble, OperandMode::kNone, null) \
1411 V(Float32, Float32RoundDown, kS390_FloorFloat, OperandMode::kNone, null) \
1412 V(Float64, Float64RoundDown, kS390_FloorDouble, OperandMode::kNone, null) \
1413 V(Float32, Float32RoundUp, kS390_CeilFloat, OperandMode::kNone, null) \
1414 V(Float64, Float64RoundUp, kS390_CeilDouble, OperandMode::kNone, null) \
1415 V(Float32, Float32RoundTruncate, kS390_TruncateFloat, OperandMode::kNone, \
1416 null) \
1417 V(Float64, Float64RoundTruncate, kS390_TruncateDouble, OperandMode::kNone, \
1418 null) \
1419 V(Float64, Float64RoundTiesAway, kS390_RoundDouble, OperandMode::kNone, \
1420 null) \
1421 V(Float32, Float32Neg, kS390_NegFloat, OperandMode::kNone, null) \
1422 V(Float64, Float64Neg, kS390_NegDouble, OperandMode::kNone, null)
1423
1424 #define FLOAT_BIN_OP_LIST(V) \
1425 V(Float32, Float32Add, kS390_AddFloat, OperandMode::kAllowRM, null) \
1426 V(Float64, Float64Add, kS390_AddDouble, OperandMode::kAllowRM, null) \
1427 V(Float32, Float32Sub, kS390_SubFloat, OperandMode::kAllowRM, null) \
1428 V(Float64, Float64Sub, kS390_SubDouble, OperandMode::kAllowRM, null) \
1429 V(Float32, Float32Mul, kS390_MulFloat, OperandMode::kAllowRM, null) \
1430 V(Float64, Float64Mul, kS390_MulDouble, OperandMode::kAllowRM, null) \
1431 V(Float32, Float32Div, kS390_DivFloat, OperandMode::kAllowRM, null) \
1432 V(Float64, Float64Div, kS390_DivDouble, OperandMode::kAllowRM, null) \
1433 V(Float32, Float32Max, kS390_MaxFloat, OperandMode::kNone, null) \
1434 V(Float64, Float64Max, kS390_MaxDouble, OperandMode::kNone, null) \
1435 V(Float32, Float32Min, kS390_MinFloat, OperandMode::kNone, null) \
1436 V(Float64, Float64Min, kS390_MinDouble, OperandMode::kNone, null)
1437
1438 #define WORD32_UNARY_OP_LIST_32(V) \
1439 V(Word32, Word32Clz, kS390_Cntlz32, OperandMode::kNone, null) \
1440 V(Word32, Word32Popcnt, kS390_Popcnt32, OperandMode::kNone, null) \
1441 V(Word32, RoundInt32ToFloat32, kS390_Int32ToFloat32, OperandMode::kNone, \
1442 null) \
1443 V(Word32, RoundUint32ToFloat32, kS390_Uint32ToFloat32, OperandMode::kNone, \
1444 null) \
1445 V(Word32, ChangeInt32ToFloat64, kS390_Int32ToDouble, OperandMode::kNone, \
1446 null) \
1447 V(Word32, ChangeUint32ToFloat64, kS390_Uint32ToDouble, OperandMode::kNone, \
1448 null) \
1449 V(Word32, BitcastInt32ToFloat32, kS390_BitcastInt32ToFloat32, \
1450 OperandMode::kNone, null)
1451
1452 #ifdef V8_TARGET_ARCH_S390X
1453 #define FLOAT_UNARY_OP_LIST(V) \
1454 FLOAT_UNARY_OP_LIST_32(V) \
1455 V(Float64, ChangeFloat64ToUint64, kS390_DoubleToUint64, OperandMode::kNone, \
1456 null) \
1457 V(Float64, BitcastFloat64ToInt64, kS390_BitcastDoubleToInt64, \
1458 OperandMode::kNone, null)
1459 #define WORD32_UNARY_OP_LIST(V) \
1460 WORD32_UNARY_OP_LIST_32(V) \
1461 V(Word32, ChangeInt32ToInt64, kS390_ExtendSignWord32, OperandMode::kNone, \
1462 null) \
1463 V(Word32, ChangeUint32ToUint64, kS390_Uint32ToUint64, OperandMode::kNone, \
1464 [&]() -> bool { \
1465 if (ProduceWord32Result(node->InputAt(0))) { \
1466 EmitIdentity(node); \
1467 return true; \
1468 } \
1469 return false; \
1470 })
1471
1472 #else
1473 #define FLOAT_UNARY_OP_LIST(V) FLOAT_UNARY_OP_LIST_32(V)
1474 #define WORD32_UNARY_OP_LIST(V) WORD32_UNARY_OP_LIST_32(V)
1475 #endif
1476
1477 #define WORD32_BIN_OP_LIST(V) \
1478 V(Word32, Int32Add, kS390_Add32, AddOperandMode, null) \
1479 V(Word32, Int32Sub, kS390_Sub32, SubOperandMode, ([&]() { \
1480 return TryMatchNegFromSub<Int32BinopMatcher, kS390_Neg32>(this, node); \
1481 })) \
1482 V(Word32, Int32Mul, kS390_Mul32, MulOperandMode, ([&]() { \
1483 return TryMatchShiftFromMul<Int32BinopMatcher, kS390_ShiftLeft32>(this, \
1484 node); \
1485 })) \
1486 V(Word32, Int32AddWithOverflow, kS390_Add32, AddOperandMode, \
1487 ([&]() { return TryMatchInt32AddWithOverflow(this, node); })) \
1488 V(Word32, Int32SubWithOverflow, kS390_Sub32, SubOperandMode, \
1489 ([&]() { return TryMatchInt32SubWithOverflow(this, node); })) \
1490 V(Word32, Int32MulWithOverflow, kS390_Mul32, MulOperandMode, \
1491 ([&]() { return TryMatchInt32MulWithOverflow(this, node); })) \
1492 V(Word32, Int32MulHigh, kS390_MulHigh32, \
1493 OperandMode::kInt32Imm | OperandMode::kAllowDistinctOps, null) \
1494 V(Word32, Uint32MulHigh, kS390_MulHighU32, \
1495 OperandMode::kAllowRRM | OperandMode::kAllowRRR, null) \
1496 V(Word32, Int32Div, kS390_Div32, \
1497 OperandMode::kAllowRRM | OperandMode::kAllowRRR, null) \
1498 V(Word32, Uint32Div, kS390_DivU32, \
1499 OperandMode::kAllowRRM | OperandMode::kAllowRRR, null) \
1500 V(Word32, Int32Mod, kS390_Mod32, \
1501 OperandMode::kAllowRRM | OperandMode::kAllowRRR, null) \
1502 V(Word32, Uint32Mod, kS390_ModU32, \
1503 OperandMode::kAllowRRM | OperandMode::kAllowRRR, null) \
1504 V(Word32, Word32Ror, kS390_RotRight32, \
1505 OperandMode::kAllowRI | OperandMode::kAllowRRR | OperandMode::kAllowRRI | \
1506 OperandMode::kShift32Imm, \
1507 null) \
1508 V(Word32, Word32And, kS390_And32, And32OperandMode, null) \
1509 V(Word32, Word32Or, kS390_Or32, Or32OperandMode, null) \
1510 V(Word32, Word32Xor, kS390_Xor32, Xor32OperandMode, null) \
1511 V(Word32, Word32Shl, kS390_ShiftLeft32, Shift32OperandMode, null) \
1512 V(Word32, Word32Shr, kS390_ShiftRight32, Shift32OperandMode, null) \
1513 V(Word32, Word32Sar, kS390_ShiftRightArith32, Shift32OperandMode, \
1514 [&]() { return TryMatchSignExtInt16OrInt8FromWord32Sar(this, node); })
1515
1516 #define WORD64_UNARY_OP_LIST(V) \
1517 V(Word64, Word64Popcnt, kS390_Popcnt64, OperandMode::kNone, null) \
1518 V(Word64, Word64Clz, kS390_Cntlz64, OperandMode::kNone, null) \
1519 V(Word64, TruncateInt64ToInt32, kS390_Int64ToInt32, OperandMode::kNone, \
1520 null) \
1521 V(Word64, RoundInt64ToFloat32, kS390_Int64ToFloat32, OperandMode::kNone, \
1522 null) \
1523 V(Word64, RoundInt64ToFloat64, kS390_Int64ToDouble, OperandMode::kNone, \
1524 null) \
1525 V(Word64, RoundUint64ToFloat32, kS390_Uint64ToFloat32, OperandMode::kNone, \
1526 null) \
1527 V(Word64, RoundUint64ToFloat64, kS390_Uint64ToDouble, OperandMode::kNone, \
1528 null) \
1529 V(Word64, BitcastInt64ToFloat64, kS390_BitcastInt64ToDouble, \
1530 OperandMode::kNone, null)
1531
1532 #define WORD64_BIN_OP_LIST(V) \
1533 V(Word64, Int64Add, kS390_Add64, AddOperandMode, null) \
1534 V(Word64, Int64Sub, kS390_Sub64, SubOperandMode, ([&]() { \
1535 return TryMatchNegFromSub<Int64BinopMatcher, kS390_Neg64>(this, node); \
1536 })) \
1537 V(Word64, Int64AddWithOverflow, kS390_Add64, AddOperandMode, \
1538 ([&]() { return TryMatchInt64AddWithOverflow(this, node); })) \
1539 V(Word64, Int64SubWithOverflow, kS390_Sub64, SubOperandMode, \
1540 ([&]() { return TryMatchInt64SubWithOverflow(this, node); })) \
1541 V(Word64, Int64Mul, kS390_Mul64, MulOperandMode, ([&]() { \
1542 return TryMatchShiftFromMul<Int64BinopMatcher, kS390_ShiftLeft64>(this, \
1543 node); \
1544 })) \
1545 V(Word64, Int64Div, kS390_Div64, \
1546 OperandMode::kAllowRRM | OperandMode::kAllowRRR, null) \
1547 V(Word64, Uint64Div, kS390_DivU64, \
1548 OperandMode::kAllowRRM | OperandMode::kAllowRRR, null) \
1549 V(Word64, Int64Mod, kS390_Mod64, \
1550 OperandMode::kAllowRRM | OperandMode::kAllowRRR, null) \
1551 V(Word64, Uint64Mod, kS390_ModU64, \
1552 OperandMode::kAllowRRM | OperandMode::kAllowRRR, null) \
1553 V(Word64, Word64Sar, kS390_ShiftRightArith64, Shift64OperandMode, null) \
1554 V(Word64, Word64Ror, kS390_RotRight64, Shift64OperandMode, null) \
1555 V(Word64, Word64Or, kS390_Or64, Or64OperandMode, null) \
1556 V(Word64, Word64Xor, kS390_Xor64, Xor64OperandMode, null)
1557
1558 #define DECLARE_UNARY_OP(type, name, op, mode, try_extra) \
1559 void InstructionSelector::Visit##name(Node* node) { \
1560 if (std::function<bool()>(try_extra)()) return; \
1561 Visit##type##UnaryOp(this, node, op, mode); \
1562 }
1563
1564 #define DECLARE_BIN_OP(type, name, op, mode, try_extra) \
1565 void InstructionSelector::Visit##name(Node* node) { \
1566 if (std::function<bool()>(try_extra)()) return; \
1567 Visit##type##BinOp(this, node, op, mode); \
1568 }
1569
1570 WORD32_BIN_OP_LIST(DECLARE_BIN_OP);
1571 WORD32_UNARY_OP_LIST(DECLARE_UNARY_OP);
1572 FLOAT_UNARY_OP_LIST(DECLARE_UNARY_OP);
1573 FLOAT_BIN_OP_LIST(DECLARE_BIN_OP);
1485 1574
1486 #if V8_TARGET_ARCH_S390X 1575 #if V8_TARGET_ARCH_S390X
1487 void InstructionSelector::VisitInt64Div(Node* node) { 1576 WORD64_UNARY_OP_LIST(DECLARE_UNARY_OP)
1488 VisitWord64BinOp(this, node, kS390_Div64, 1577 WORD64_BIN_OP_LIST(DECLARE_BIN_OP)
1489 OperandMode::kAllowRRM | OperandMode::kAllowRRR);
1490 }
1491 #endif 1578 #endif
1492 1579
1493 void InstructionSelector::VisitUint32Div(Node* node) { 1580 #undef DECLARE_BIN_OP
1494 VisitBin32op(this, node, kS390_DivU32,
1495 OperandMode::kAllowRRM | OperandMode::kAllowRRR);
1496 }
1497
1498 #if V8_TARGET_ARCH_S390X
1499 void InstructionSelector::VisitUint64Div(Node* node) {
1500 VisitWord64BinOp(this, node, kS390_DivU64,
1501 OperandMode::kAllowRRM | OperandMode::kAllowRRR);
1502 }
1503 #endif
1504
1505 void InstructionSelector::VisitInt32Mod(Node* node) {
1506 VisitBin32op(this, node, kS390_Mod32,
1507 OperandMode::kAllowRRM | OperandMode::kAllowRRR);
1508 }
1509
1510 #if V8_TARGET_ARCH_S390X
1511 void InstructionSelector::VisitInt64Mod(Node* node) {
1512 VisitWord64BinOp(this, node, kS390_Mod64,
1513 OperandMode::kAllowRRM | OperandMode::kAllowRRR);
1514 }
1515 #endif
1516
1517 void InstructionSelector::VisitUint32Mod(Node* node) {
1518 VisitBin32op(this, node, kS390_ModU32,
1519 OperandMode::kAllowRRM | OperandMode::kAllowRRR);
1520 }
1521
1522 #if V8_TARGET_ARCH_S390X
1523 void InstructionSelector::VisitUint64Mod(Node* node) {
1524 VisitWord64BinOp(this, node, kS390_ModU64,
1525 OperandMode::kAllowRRM | OperandMode::kAllowRRR);
1526 }
1527 #endif
1528
1529 // TODO(john.yan): place kAllowRM where available
1530 #define VISIT_FLOAT_UNARY_OP_LIST(V) \
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 1581 #undef DECLARE_UNARY_OP
1585 #undef VISIT_WORD64_UNARY_OP_LIST 1582 #undef WORD64_BIN_OP_LIST
1586 #undef VISIT_FLOAT_UNARY_OP_LIST 1583 #undef WORD64_UNARY_OP_LIST
1587 1584 #undef WORD32_BIN_OP_LIST
1588 void InstructionSelector::VisitRoundInt32ToFloat32(Node* node) { 1585 #undef WORD32_UNARY_OP_LIST
1589 VisitRR(this, kS390_Int32ToFloat32, node); 1586 #undef FLOAT_UNARY_OP_LIST
1590 } 1587 #undef WORD32_UNARY_OP_LIST_32
1591 1588 #undef FLOAT_BIN_OP_LIST
1592 void InstructionSelector::VisitRoundUint32ToFloat32(Node* node) { 1589 #undef FLOAT_BIN_OP_LIST_32
1593 VisitRR(this, kS390_Uint32ToFloat32, node); 1590 #undef null
1594 }
1595
1596 void InstructionSelector::VisitChangeInt32ToFloat64(Node* node) {
1597 VisitRR(this, kS390_Int32ToDouble, node);
1598 }
1599
1600 void InstructionSelector::VisitChangeUint32ToFloat64(Node* node) {
1601 VisitRR(this, kS390_Uint32ToDouble, node);
1602 }
1603 1591
1604 #if V8_TARGET_ARCH_S390X 1592 #if V8_TARGET_ARCH_S390X
1605 void InstructionSelector::VisitTryTruncateFloat32ToInt64(Node* node) { 1593 void InstructionSelector::VisitTryTruncateFloat32ToInt64(Node* node) {
1606 VisitTryTruncateDouble(this, kS390_Float32ToInt64, node); 1594 VisitTryTruncateDouble(this, kS390_Float32ToInt64, node);
1607 } 1595 }
1608 1596
1609 void InstructionSelector::VisitTryTruncateFloat64ToInt64(Node* node) { 1597 void InstructionSelector::VisitTryTruncateFloat64ToInt64(Node* node) {
1610 VisitTryTruncateDouble(this, kS390_DoubleToInt64, node); 1598 VisitTryTruncateDouble(this, kS390_DoubleToInt64, node);
1611 } 1599 }
1612 1600
1613 void InstructionSelector::VisitTryTruncateFloat32ToUint64(Node* node) { 1601 void InstructionSelector::VisitTryTruncateFloat32ToUint64(Node* node) {
1614 VisitTryTruncateDouble(this, kS390_Float32ToUint64, node); 1602 VisitTryTruncateDouble(this, kS390_Float32ToUint64, node);
1615 } 1603 }
1616 1604
1617 void InstructionSelector::VisitTryTruncateFloat64ToUint64(Node* node) { 1605 void InstructionSelector::VisitTryTruncateFloat64ToUint64(Node* node) {
1618 VisitTryTruncateDouble(this, kS390_DoubleToUint64, node); 1606 VisitTryTruncateDouble(this, kS390_DoubleToUint64, node);
1619 } 1607 }
1620 1608
1621 void InstructionSelector::VisitChangeInt32ToInt64(Node* node) {
1622 // TODO(mbrandy): inspect input to see if nop is appropriate.
1623 VisitRR(this, kS390_ExtendSignWord32, node);
1624 }
1625
1626 void InstructionSelector::VisitChangeUint32ToUint64(Node* node) {
1627 S390OperandGenerator g(this);
1628 Node* value = node->InputAt(0);
1629 if (ZeroExtendsWord32ToWord64(value)) {
1630 // These 32-bit operations implicitly zero-extend to 64-bit on x64, so the
1631 // zero-extension is a no-op.
1632 return EmitIdentity(node);
1633 }
1634 VisitRR(this, kS390_Uint32ToUint64, node);
1635 }
1636
1637 void InstructionSelector::VisitChangeFloat64ToUint64(Node* node) {
1638 VisitRR(this, kS390_DoubleToUint64, node);
1639 }
1640 #endif 1609 #endif
1641 1610
1642 void InstructionSelector::VisitBitcastInt32ToFloat32(Node* node) {
1643 VisitRR(this, kS390_BitcastInt32ToFloat32, node);
1644 }
1645
1646 void InstructionSelector::VisitFloat32Add(Node* node) {
1647 return VisitFloat32BinOp(this, node, kS390_AddFloat, OperandMode::kAllowRM);
1648 }
1649
1650 void InstructionSelector::VisitFloat64Add(Node* node) {
1651 // TODO(mbrandy): detect multiply-add
1652 return VisitFloat64BinOp(this, node, kS390_AddDouble, OperandMode::kAllowRM);
1653 }
1654
1655 void InstructionSelector::VisitFloat32Sub(Node* node) {
1656 return VisitFloat32BinOp(this, node, kS390_SubFloat, OperandMode::kAllowRM);
1657 }
1658
1659 void InstructionSelector::VisitFloat64Sub(Node* node) {
1660 // TODO(mbrandy): detect multiply-subtract
1661 return VisitFloat64BinOp(this, node, kS390_SubDouble, OperandMode::kAllowRM);
1662 }
1663
1664 void InstructionSelector::VisitFloat32Mul(Node* node) {
1665 return VisitFloat32BinOp(this, node, kS390_MulFloat, OperandMode::kAllowRM);
1666 }
1667
1668 void InstructionSelector::VisitFloat64Mul(Node* node) {
1669 // TODO(mbrandy): detect negate
1670 return VisitFloat64BinOp(this, node, kS390_MulDouble, OperandMode::kAllowRM);
1671 }
1672
1673 void InstructionSelector::VisitFloat32Div(Node* node) {
1674 return VisitFloat32BinOp(this, node, kS390_DivFloat, OperandMode::kAllowRM);
1675 }
1676
1677 void InstructionSelector::VisitFloat64Div(Node* node) {
1678 return VisitFloat64BinOp(this, node, kS390_DivDouble, OperandMode::kAllowRM);
1679 }
1680
1681 void InstructionSelector::VisitFloat64Mod(Node* node) { 1611 void InstructionSelector::VisitFloat64Mod(Node* node) {
1682 S390OperandGenerator g(this); 1612 S390OperandGenerator g(this);
1683 Emit(kS390_ModDouble, g.DefineAsFixed(node, d1), 1613 Emit(kS390_ModDouble, g.DefineAsFixed(node, d1),
1684 g.UseFixed(node->InputAt(0), d1), g.UseFixed(node->InputAt(1), d2)) 1614 g.UseFixed(node->InputAt(0), d1), g.UseFixed(node->InputAt(1), d2))
1685 ->MarkAsCall(); 1615 ->MarkAsCall();
1686 } 1616 }
1687 1617
1688 void InstructionSelector::VisitFloat32Max(Node* node) {
1689 return VisitFloat32BinOp(this, node, kS390_MaxFloat, OperandMode::kNone);
1690 }
1691
1692 void InstructionSelector::VisitFloat64Max(Node* node) {
1693 return VisitFloat64BinOp(this, node, kS390_MaxDouble, OperandMode::kNone);
1694 }
1695
1696 void InstructionSelector::VisitFloat32Min(Node* node) {
1697 return VisitFloat32BinOp(this, node, kS390_MinFloat, OperandMode::kNone);
1698 }
1699
1700 void InstructionSelector::VisitFloat64Min(Node* node) {
1701 return VisitFloat64BinOp(this, node, kS390_MinDouble, OperandMode::kNone);
1702 }
1703
1704 void InstructionSelector::VisitFloat64Ieee754Unop(Node* node, 1618 void InstructionSelector::VisitFloat64Ieee754Unop(Node* node,
1705 InstructionCode opcode) { 1619 InstructionCode opcode) {
1706 S390OperandGenerator g(this); 1620 S390OperandGenerator g(this);
1707 Emit(opcode, g.DefineAsFixed(node, d1), g.UseFixed(node->InputAt(0), d1)) 1621 Emit(opcode, g.DefineAsFixed(node, d1), g.UseFixed(node->InputAt(0), d1))
1708 ->MarkAsCall(); 1622 ->MarkAsCall();
1709 } 1623 }
1710 1624
1711 void InstructionSelector::VisitFloat64Ieee754Binop(Node* node, 1625 void InstructionSelector::VisitFloat64Ieee754Binop(Node* node,
1712 InstructionCode opcode) { 1626 InstructionCode opcode) {
1713 S390OperandGenerator g(this); 1627 S390OperandGenerator g(this);
1714 Emit(opcode, g.DefineAsFixed(node, d1), g.UseFixed(node->InputAt(0), d1), 1628 Emit(opcode, g.DefineAsFixed(node, d1), g.UseFixed(node->InputAt(0), d1),
1715 g.UseFixed(node->InputAt(1), d2)) 1629 g.UseFixed(node->InputAt(1), d2))
1716 ->MarkAsCall(); 1630 ->MarkAsCall();
1717 } 1631 }
1718 1632
1719 void InstructionSelector::VisitFloat32RoundTiesEven(Node* node) { 1633 void InstructionSelector::VisitFloat32RoundTiesEven(Node* node) {
1720 UNREACHABLE(); 1634 UNREACHABLE();
1721 } 1635 }
1722 1636
1723 void InstructionSelector::VisitFloat64RoundTiesEven(Node* node) { 1637 void InstructionSelector::VisitFloat64RoundTiesEven(Node* node) {
1724 UNREACHABLE(); 1638 UNREACHABLE();
1725 } 1639 }
1726 1640
1727 void InstructionSelector::VisitInt32AddWithOverflow(Node* node) {
1728 OperandModes mode = AddOperandMode;
1729 if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
1730 FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf);
1731 return VisitBin32op(this, node, kS390_Add32, mode, &cont);
1732 }
1733 FlagsContinuation cont;
1734 VisitBin32op(this, node, kS390_Add32, mode, &cont);
1735 }
1736
1737 void InstructionSelector::VisitInt32SubWithOverflow(Node* node) {
1738 OperandModes mode = SubOperandMode;
1739 if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
1740 FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf);
1741 return VisitBin32op(this, node, kS390_Sub32, mode, &cont);
1742 }
1743 FlagsContinuation cont;
1744 VisitBin32op(this, node, kS390_Sub32, mode, &cont);
1745 }
1746
1747 #if V8_TARGET_ARCH_S390X
1748 void InstructionSelector::VisitInt64AddWithOverflow(Node* node) {
1749 if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
1750 FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf);
1751 return VisitWord64BinOp(this, node, kS390_Add64, AddOperandMode, &cont);
1752 }
1753 VisitWord64BinOp(this, node, kS390_Add64, AddOperandMode);
1754 }
1755
1756 void InstructionSelector::VisitInt64SubWithOverflow(Node* node) {
1757 if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
1758 FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf);
1759 return VisitWord64BinOp(this, node, kS390_Sub64, SubOperandMode, &cont);
1760 }
1761 VisitWord64BinOp(this, node, kS390_Sub64, SubOperandMode);
1762 }
1763 #endif
1764
1765 static bool CompareLogical(FlagsContinuation* cont) { 1641 static bool CompareLogical(FlagsContinuation* cont) {
1766 switch (cont->condition()) { 1642 switch (cont->condition()) {
1767 case kUnsignedLessThan: 1643 case kUnsignedLessThan:
1768 case kUnsignedGreaterThanOrEqual: 1644 case kUnsignedGreaterThanOrEqual:
1769 case kUnsignedLessThanOrEqual: 1645 case kUnsignedLessThanOrEqual:
1770 case kUnsignedGreaterThan: 1646 case kUnsignedGreaterThan:
1771 return true; 1647 return true;
1772 default: 1648 default:
1773 return false; 1649 return false;
1774 } 1650 }
(...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after
2098 // unless the 0th projection (the use of the actual value of the 1974 // unless the 0th projection (the use of the actual value of the
2099 // <Operation> is either nullptr, which means there's no use of the 1975 // <Operation> is either nullptr, which means there's no use of the
2100 // actual value, or was already defined, which means it is scheduled 1976 // actual value, or was already defined, which means it is scheduled
2101 // *AFTER* this branch). 1977 // *AFTER* this branch).
2102 Node* const node = value->InputAt(0); 1978 Node* const node = value->InputAt(0);
2103 Node* const result = NodeProperties::FindProjection(node, 0); 1979 Node* const result = NodeProperties::FindProjection(node, 0);
2104 if (result == nullptr || selector->IsDefined(result)) { 1980 if (result == nullptr || selector->IsDefined(result)) {
2105 switch (node->opcode()) { 1981 switch (node->opcode()) {
2106 case IrOpcode::kInt32AddWithOverflow: 1982 case IrOpcode::kInt32AddWithOverflow:
2107 cont->OverwriteAndNegateIfEqual(kOverflow); 1983 cont->OverwriteAndNegateIfEqual(kOverflow);
2108 return VisitBin32op(selector, node, kS390_Add32, AddOperandMode, 1984 return VisitWord32BinOp(selector, node, kS390_Add32,
2109 cont); 1985 AddOperandMode, cont);
2110 case IrOpcode::kInt32SubWithOverflow: 1986 case IrOpcode::kInt32SubWithOverflow:
2111 cont->OverwriteAndNegateIfEqual(kOverflow); 1987 cont->OverwriteAndNegateIfEqual(kOverflow);
2112 return VisitBin32op(selector, node, kS390_Sub32, SubOperandMode, 1988 return VisitWord32BinOp(selector, node, kS390_Sub32,
2113 cont); 1989 SubOperandMode, cont);
2114 case IrOpcode::kInt32MulWithOverflow: 1990 case IrOpcode::kInt32MulWithOverflow:
2115 cont->OverwriteAndNegateIfEqual(kNotEqual); 1991 cont->OverwriteAndNegateIfEqual(kNotEqual);
2116 return VisitBin32op( 1992 return VisitWord32BinOp(
2117 selector, node, kS390_Mul32WithOverflow, 1993 selector, node, kS390_Mul32WithOverflow,
2118 OperandMode::kInt32Imm | OperandMode::kAllowDistinctOps, 1994 OperandMode::kInt32Imm | OperandMode::kAllowDistinctOps,
2119 cont); 1995 cont);
2120 #if V8_TARGET_ARCH_S390X 1996 #if V8_TARGET_ARCH_S390X
2121 case IrOpcode::kInt64AddWithOverflow: 1997 case IrOpcode::kInt64AddWithOverflow:
2122 cont->OverwriteAndNegateIfEqual(kOverflow); 1998 cont->OverwriteAndNegateIfEqual(kOverflow);
2123 return VisitWord64BinOp(selector, node, kS390_Add64, 1999 return VisitWord64BinOp(selector, node, kS390_Add64,
2124 AddOperandMode, cont); 2000 AddOperandMode, cont);
2125 case IrOpcode::kInt64SubWithOverflow: 2001 case IrOpcode::kInt64SubWithOverflow:
2126 cont->OverwriteAndNegateIfEqual(kOverflow); 2002 cont->OverwriteAndNegateIfEqual(kOverflow);
(...skipping 22 matching lines...) Expand all
2149 default: 2025 default:
2150 break; 2026 break;
2151 } 2027 }
2152 break; 2028 break;
2153 } 2029 }
2154 case IrOpcode::kInt32Add: 2030 case IrOpcode::kInt32Add:
2155 // can't handle overflow case. 2031 // can't handle overflow case.
2156 break; 2032 break;
2157 case IrOpcode::kWord32Or: 2033 case IrOpcode::kWord32Or:
2158 if (fc == kNotEqual || fc == kEqual) 2034 if (fc == kNotEqual || fc == kEqual)
2159 return VisitBin32op(selector, value, kS390_Or32, Or32OperandMode, 2035 return VisitWord32BinOp(selector, value, kS390_Or32, Or32OperandMode,
2160 cont); 2036 cont);
2161 break; 2037 break;
2162 case IrOpcode::kWord32Xor: 2038 case IrOpcode::kWord32Xor:
2163 if (fc == kNotEqual || fc == kEqual) 2039 if (fc == kNotEqual || fc == kEqual)
2164 return VisitBin32op(selector, value, kS390_Xor32, Xor32OperandMode, 2040 return VisitWord32BinOp(selector, value, kS390_Xor32,
2165 cont); 2041 Xor32OperandMode, cont);
2166 break; 2042 break;
2167 case IrOpcode::kWord32Sar: 2043 case IrOpcode::kWord32Sar:
2168 case IrOpcode::kWord32Shl: 2044 case IrOpcode::kWord32Shl:
2169 case IrOpcode::kWord32Shr: 2045 case IrOpcode::kWord32Shr:
2170 case IrOpcode::kWord32Ror: 2046 case IrOpcode::kWord32Ror:
2171 // doesn't generate cc, so ignore. 2047 // doesn't generate cc, so ignore.
2172 break; 2048 break;
2173 #if V8_TARGET_ARCH_S390X 2049 #if V8_TARGET_ARCH_S390X
2174 case IrOpcode::kInt64Sub: 2050 case IrOpcode::kInt64Sub:
2175 if (fc == kNotEqual || fc == kEqual) 2051 if (fc == kNotEqual || fc == kEqual)
(...skipping 398 matching lines...) Expand 10 before | Expand all | Expand 10 after
2574 // static 2450 // static
2575 MachineOperatorBuilder::AlignmentRequirements 2451 MachineOperatorBuilder::AlignmentRequirements
2576 InstructionSelector::AlignmentRequirements() { 2452 InstructionSelector::AlignmentRequirements() {
2577 return MachineOperatorBuilder::AlignmentRequirements:: 2453 return MachineOperatorBuilder::AlignmentRequirements::
2578 FullUnalignedAccessSupport(); 2454 FullUnalignedAccessSupport();
2579 } 2455 }
2580 2456
2581 } // namespace compiler 2457 } // namespace compiler
2582 } // namespace internal 2458 } // namespace internal
2583 } // namespace v8 2459 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/s390/code-generator-s390.cc ('k') | src/s390/macro-assembler-s390.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698