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