| OLD | NEW |
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/base/adapters.h" | 5 #include "src/base/adapters.h" |
| 6 #include "src/compiler/instruction-selector-impl.h" | 6 #include "src/compiler/instruction-selector-impl.h" |
| 7 #include "src/compiler/node-matchers.h" | 7 #include "src/compiler/node-matchers.h" |
| 8 #include "src/compiler/node-properties.h" | 8 #include "src/compiler/node-properties.h" |
| 9 #include "src/s390/frames-s390.h" | 9 #include "src/s390/frames-s390.h" |
| 10 | 10 |
| (...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |