| 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/compiler/effect-control-linearizer.h" | 5 #include "src/compiler/effect-control-linearizer.h" |
| 6 | 6 |
| 7 #include "src/code-factory.h" | 7 #include "src/code-factory.h" |
| 8 #include "src/compiler/access-builder.h" | 8 #include "src/compiler/access-builder.h" |
| 9 #include "src/compiler/js-graph.h" | 9 #include "src/compiler/js-graph.h" |
| 10 #include "src/compiler/linkage.h" | 10 #include "src/compiler/linkage.h" |
| (...skipping 762 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 773 break; | 773 break; |
| 774 case IrOpcode::kFloat64RoundUp: | 774 case IrOpcode::kFloat64RoundUp: |
| 775 state = LowerFloat64RoundUp(node, *effect, *control); | 775 state = LowerFloat64RoundUp(node, *effect, *control); |
| 776 break; | 776 break; |
| 777 case IrOpcode::kFloat64RoundDown: | 777 case IrOpcode::kFloat64RoundDown: |
| 778 state = LowerFloat64RoundDown(node, *effect, *control); | 778 state = LowerFloat64RoundDown(node, *effect, *control); |
| 779 break; | 779 break; |
| 780 case IrOpcode::kFloat64RoundTruncate: | 780 case IrOpcode::kFloat64RoundTruncate: |
| 781 state = LowerFloat64RoundTruncate(node, *effect, *control); | 781 state = LowerFloat64RoundTruncate(node, *effect, *control); |
| 782 break; | 782 break; |
| 783 case IrOpcode::kFloat64RoundTiesEven: |
| 784 state = LowerFloat64RoundTiesEven(node, *effect, *control); |
| 785 break; |
| 783 default: | 786 default: |
| 784 return false; | 787 return false; |
| 785 } | 788 } |
| 786 NodeProperties::ReplaceUses(node, state.value, state.effect, state.control); | 789 NodeProperties::ReplaceUses(node, state.value, state.effect, state.control); |
| 787 *effect = state.effect; | 790 *effect = state.effect; |
| 788 *control = state.control; | 791 *control = state.control; |
| 789 return true; | 792 return true; |
| 790 } | 793 } |
| 791 | 794 |
| 792 EffectControlLinearizer::ValueEffectControl | 795 EffectControlLinearizer::ValueEffectControl |
| (...skipping 2575 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3368 } | 3371 } |
| 3369 | 3372 |
| 3370 Node* merge0 = graph()->NewNode(common()->Merge(2), if_true0, if_false0); | 3373 Node* merge0 = graph()->NewNode(common()->Merge(2), if_true0, if_false0); |
| 3371 Node* value = | 3374 Node* value = |
| 3372 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2), | 3375 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2), |
| 3373 vtrue0, vfalse0, merge0); | 3376 vtrue0, vfalse0, merge0); |
| 3374 return ValueEffectControl(value, effect, merge0); | 3377 return ValueEffectControl(value, effect, merge0); |
| 3375 } | 3378 } |
| 3376 | 3379 |
| 3377 EffectControlLinearizer::ValueEffectControl | 3380 EffectControlLinearizer::ValueEffectControl |
| 3381 EffectControlLinearizer::BuildFloat64RoundDown(Node* value, Node* effect, |
| 3382 Node* control) { |
| 3383 if (machine()->Float64RoundDown().IsSupported()) { |
| 3384 value = graph()->NewNode(machine()->Float64RoundDown().op(), value); |
| 3385 } else { |
| 3386 Node* const one = jsgraph()->Float64Constant(1.0); |
| 3387 Node* const zero = jsgraph()->Float64Constant(0.0); |
| 3388 Node* const minus_one = jsgraph()->Float64Constant(-1.0); |
| 3389 Node* const minus_zero = jsgraph()->Float64Constant(-0.0); |
| 3390 Node* const two_52 = jsgraph()->Float64Constant(4503599627370496.0E0); |
| 3391 Node* const minus_two_52 = |
| 3392 jsgraph()->Float64Constant(-4503599627370496.0E0); |
| 3393 Node* const input = value; |
| 3394 |
| 3395 // General case for floor. |
| 3396 // |
| 3397 // if 0.0 < input then |
| 3398 // if 2^52 <= input then |
| 3399 // input |
| 3400 // else |
| 3401 // let temp1 = (2^52 + input) - 2^52 in |
| 3402 // if input < temp1 then |
| 3403 // temp1 - 1 |
| 3404 // else |
| 3405 // temp1 |
| 3406 // else |
| 3407 // if input == 0 then |
| 3408 // input |
| 3409 // else |
| 3410 // if input <= -2^52 then |
| 3411 // input |
| 3412 // else |
| 3413 // let temp1 = -0 - input in |
| 3414 // let temp2 = (2^52 + temp1) - 2^52 in |
| 3415 // if temp2 < temp1 then |
| 3416 // -1 - temp2 |
| 3417 // else |
| 3418 // -0 - temp2 |
| 3419 // |
| 3420 // Note: We do not use the Diamond helper class here, because it really |
| 3421 // hurts |
| 3422 // readability with nested diamonds. |
| 3423 |
| 3424 Node* check0 = graph()->NewNode(machine()->Float64LessThan(), zero, input); |
| 3425 Node* branch0 = |
| 3426 graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control); |
| 3427 |
| 3428 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0); |
| 3429 Node* vtrue0; |
| 3430 { |
| 3431 Node* check1 = |
| 3432 graph()->NewNode(machine()->Float64LessThanOrEqual(), two_52, input); |
| 3433 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_true0); |
| 3434 |
| 3435 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); |
| 3436 Node* vtrue1 = input; |
| 3437 |
| 3438 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); |
| 3439 Node* vfalse1; |
| 3440 { |
| 3441 Node* temp1 = graph()->NewNode( |
| 3442 machine()->Float64Sub(), |
| 3443 graph()->NewNode(machine()->Float64Add(), two_52, input), two_52); |
| 3444 vfalse1 = graph()->NewNode( |
| 3445 common()->Select(MachineRepresentation::kFloat64), |
| 3446 graph()->NewNode(machine()->Float64LessThan(), input, temp1), |
| 3447 graph()->NewNode(machine()->Float64Sub(), temp1, one), temp1); |
| 3448 } |
| 3449 |
| 3450 if_true0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1); |
| 3451 vtrue0 = |
| 3452 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2), |
| 3453 vtrue1, vfalse1, if_true0); |
| 3454 } |
| 3455 |
| 3456 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0); |
| 3457 Node* vfalse0; |
| 3458 { |
| 3459 Node* check1 = graph()->NewNode(machine()->Float64Equal(), input, zero); |
| 3460 Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kFalse), |
| 3461 check1, if_false0); |
| 3462 |
| 3463 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); |
| 3464 Node* vtrue1 = input; |
| 3465 |
| 3466 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); |
| 3467 Node* vfalse1; |
| 3468 { |
| 3469 Node* check2 = graph()->NewNode(machine()->Float64LessThanOrEqual(), |
| 3470 input, minus_two_52); |
| 3471 Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kFalse), |
| 3472 check2, if_false1); |
| 3473 |
| 3474 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2); |
| 3475 Node* vtrue2 = input; |
| 3476 |
| 3477 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2); |
| 3478 Node* vfalse2; |
| 3479 { |
| 3480 Node* temp1 = |
| 3481 graph()->NewNode(machine()->Float64Sub(), minus_zero, input); |
| 3482 Node* temp2 = graph()->NewNode( |
| 3483 machine()->Float64Sub(), |
| 3484 graph()->NewNode(machine()->Float64Add(), two_52, temp1), two_52); |
| 3485 vfalse2 = graph()->NewNode( |
| 3486 common()->Select(MachineRepresentation::kFloat64), |
| 3487 graph()->NewNode(machine()->Float64LessThan(), temp2, temp1), |
| 3488 graph()->NewNode(machine()->Float64Sub(), minus_one, temp2), |
| 3489 graph()->NewNode(machine()->Float64Sub(), minus_zero, temp2)); |
| 3490 } |
| 3491 |
| 3492 if_false1 = graph()->NewNode(common()->Merge(2), if_true2, if_false2); |
| 3493 vfalse1 = |
| 3494 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2), |
| 3495 vtrue2, vfalse2, if_false1); |
| 3496 } |
| 3497 |
| 3498 if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1); |
| 3499 vfalse0 = |
| 3500 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2), |
| 3501 vtrue1, vfalse1, if_false0); |
| 3502 } |
| 3503 |
| 3504 control = graph()->NewNode(common()->Merge(2), if_true0, if_false0); |
| 3505 value = graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2), |
| 3506 vtrue0, vfalse0, control); |
| 3507 } |
| 3508 return ValueEffectControl(value, effect, control); |
| 3509 } |
| 3510 |
| 3511 EffectControlLinearizer::ValueEffectControl |
| 3378 EffectControlLinearizer::LowerFloat64RoundDown(Node* node, Node* effect, | 3512 EffectControlLinearizer::LowerFloat64RoundDown(Node* node, Node* effect, |
| 3379 Node* control) { | 3513 Node* control) { |
| 3380 // Nothing to be done if a fast hardware instruction is available. | 3514 // Nothing to be done if a fast hardware instruction is available. |
| 3381 if (machine()->Float64RoundDown().IsSupported()) { | 3515 if (machine()->Float64RoundDown().IsSupported()) { |
| 3382 return ValueEffectControl(node, effect, control); | 3516 return ValueEffectControl(node, effect, control); |
| 3383 } | 3517 } |
| 3384 | 3518 |
| 3519 Node* const input = node->InputAt(0); |
| 3520 return BuildFloat64RoundDown(input, effect, control); |
| 3521 } |
| 3522 |
| 3523 EffectControlLinearizer::ValueEffectControl |
| 3524 EffectControlLinearizer::LowerFloat64RoundTiesEven(Node* node, Node* effect, |
| 3525 Node* control) { |
| 3526 // Nothing to be done if a fast hardware instruction is available. |
| 3527 if (machine()->Float64RoundTiesEven().IsSupported()) { |
| 3528 return ValueEffectControl(node, effect, control); |
| 3529 } |
| 3530 |
| 3385 Node* const one = jsgraph()->Float64Constant(1.0); | 3531 Node* const one = jsgraph()->Float64Constant(1.0); |
| 3532 Node* const two = jsgraph()->Float64Constant(2.0); |
| 3533 Node* const half = jsgraph()->Float64Constant(0.5); |
| 3386 Node* const zero = jsgraph()->Float64Constant(0.0); | 3534 Node* const zero = jsgraph()->Float64Constant(0.0); |
| 3387 Node* const minus_one = jsgraph()->Float64Constant(-1.0); | |
| 3388 Node* const minus_zero = jsgraph()->Float64Constant(-0.0); | |
| 3389 Node* const two_52 = jsgraph()->Float64Constant(4503599627370496.0E0); | |
| 3390 Node* const minus_two_52 = jsgraph()->Float64Constant(-4503599627370496.0E0); | |
| 3391 Node* const input = node->InputAt(0); | 3535 Node* const input = node->InputAt(0); |
| 3392 | 3536 |
| 3393 // General case for floor. | 3537 // Generate case for round ties to even: |
| 3394 // | 3538 // |
| 3395 // if 0.0 < input then | 3539 // let value = floor(input) in |
| 3396 // if 2^52 <= input then | 3540 // let temp1 = input - value in |
| 3397 // input | 3541 // if temp1 < 0.5 then |
| 3542 // value |
| 3543 // else if 0.5 < temp1 then |
| 3544 // value + 1.0 |
| 3545 // else |
| 3546 // let temp2 = value % 2.0 in |
| 3547 // if temp2 == 0.0 then |
| 3548 // value |
| 3398 // else | 3549 // else |
| 3399 // let temp1 = (2^52 + input) - 2^52 in | 3550 // value + 1.0 |
| 3400 // if input < temp1 then | |
| 3401 // temp1 - 1 | |
| 3402 // else | |
| 3403 // temp1 | |
| 3404 // else | |
| 3405 // if input == 0 then | |
| 3406 // input | |
| 3407 // else | |
| 3408 // if input <= -2^52 then | |
| 3409 // input | |
| 3410 // else | |
| 3411 // let temp1 = -0 - input in | |
| 3412 // let temp2 = (2^52 + temp1) - 2^52 in | |
| 3413 // if temp2 < temp1 then | |
| 3414 // -1 - temp2 | |
| 3415 // else | |
| 3416 // -0 - temp2 | |
| 3417 // | 3551 // |
| 3418 // Note: We do not use the Diamond helper class here, because it really hurts | 3552 // Note: We do not use the Diamond helper class here, because it really hurts |
| 3419 // readability with nested diamonds. | 3553 // readability with nested diamonds. |
| 3420 | 3554 |
| 3421 Node* check0 = graph()->NewNode(machine()->Float64LessThan(), zero, input); | 3555 ValueEffectControl continuation = |
| 3422 Node* branch0 = | 3556 BuildFloat64RoundDown(input, effect, control); |
| 3423 graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control); | 3557 Node* value = continuation.value; |
| 3558 effect = continuation.effect; |
| 3559 control = continuation.control; |
| 3560 |
| 3561 Node* temp1 = graph()->NewNode(machine()->Float64Sub(), input, value); |
| 3562 |
| 3563 Node* check0 = graph()->NewNode(machine()->Float64LessThan(), temp1, half); |
| 3564 Node* branch0 = graph()->NewNode(common()->Branch(), check0, control); |
| 3424 | 3565 |
| 3425 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0); | 3566 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0); |
| 3426 Node* vtrue0; | 3567 Node* vtrue0 = value; |
| 3568 |
| 3569 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0); |
| 3570 Node* vfalse0; |
| 3427 { | 3571 { |
| 3428 Node* check1 = | 3572 Node* check1 = graph()->NewNode(machine()->Float64LessThan(), half, temp1); |
| 3429 graph()->NewNode(machine()->Float64LessThanOrEqual(), two_52, input); | 3573 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0); |
| 3430 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_true0); | |
| 3431 | 3574 |
| 3432 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); | 3575 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); |
| 3433 Node* vtrue1 = input; | 3576 Node* vtrue1 = graph()->NewNode(machine()->Float64Add(), value, one); |
| 3434 | 3577 |
| 3435 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); | 3578 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); |
| 3436 Node* vfalse1; | 3579 Node* vfalse1; |
| 3437 { | 3580 { |
| 3438 Node* temp1 = graph()->NewNode( | 3581 Node* temp2 = graph()->NewNode(machine()->Float64Mod(), value, two); |
| 3439 machine()->Float64Sub(), | |
| 3440 graph()->NewNode(machine()->Float64Add(), two_52, input), two_52); | |
| 3441 vfalse1 = graph()->NewNode( | |
| 3442 common()->Select(MachineRepresentation::kFloat64), | |
| 3443 graph()->NewNode(machine()->Float64LessThan(), input, temp1), | |
| 3444 graph()->NewNode(machine()->Float64Sub(), temp1, one), temp1); | |
| 3445 } | |
| 3446 | 3582 |
| 3447 if_true0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1); | 3583 Node* check2 = graph()->NewNode(machine()->Float64Equal(), temp2, zero); |
| 3448 vtrue0 = graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2), | 3584 Node* branch2 = graph()->NewNode(common()->Branch(), check2, if_false1); |
| 3449 vtrue1, vfalse1, if_true0); | |
| 3450 } | |
| 3451 | |
| 3452 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0); | |
| 3453 Node* vfalse0; | |
| 3454 { | |
| 3455 Node* check1 = graph()->NewNode(machine()->Float64Equal(), input, zero); | |
| 3456 Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kFalse), | |
| 3457 check1, if_false0); | |
| 3458 | |
| 3459 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); | |
| 3460 Node* vtrue1 = input; | |
| 3461 | |
| 3462 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); | |
| 3463 Node* vfalse1; | |
| 3464 { | |
| 3465 Node* check2 = graph()->NewNode(machine()->Float64LessThanOrEqual(), | |
| 3466 input, minus_two_52); | |
| 3467 Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kFalse), | |
| 3468 check2, if_false1); | |
| 3469 | 3585 |
| 3470 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2); | 3586 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2); |
| 3471 Node* vtrue2 = input; | 3587 Node* vtrue2 = value; |
| 3472 | 3588 |
| 3473 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2); | 3589 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2); |
| 3474 Node* vfalse2; | 3590 Node* vfalse2 = graph()->NewNode(machine()->Float64Add(), value, one); |
| 3475 { | |
| 3476 Node* temp1 = | |
| 3477 graph()->NewNode(machine()->Float64Sub(), minus_zero, input); | |
| 3478 Node* temp2 = graph()->NewNode( | |
| 3479 machine()->Float64Sub(), | |
| 3480 graph()->NewNode(machine()->Float64Add(), two_52, temp1), two_52); | |
| 3481 vfalse2 = graph()->NewNode( | |
| 3482 common()->Select(MachineRepresentation::kFloat64), | |
| 3483 graph()->NewNode(machine()->Float64LessThan(), temp2, temp1), | |
| 3484 graph()->NewNode(machine()->Float64Sub(), minus_one, temp2), | |
| 3485 graph()->NewNode(machine()->Float64Sub(), minus_zero, temp2)); | |
| 3486 } | |
| 3487 | 3591 |
| 3488 if_false1 = graph()->NewNode(common()->Merge(2), if_true2, if_false2); | 3592 if_false1 = graph()->NewNode(common()->Merge(2), if_true2, if_false2); |
| 3489 vfalse1 = | 3593 vfalse1 = |
| 3490 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2), | 3594 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2), |
| 3491 vtrue2, vfalse2, if_false1); | 3595 vtrue2, vfalse2, if_false1); |
| 3492 } | 3596 } |
| 3493 | 3597 |
| 3494 if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1); | 3598 if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1); |
| 3495 vfalse0 = | 3599 vfalse0 = |
| 3496 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2), | 3600 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2), |
| 3497 vtrue1, vfalse1, if_false0); | 3601 vtrue1, vfalse1, if_false0); |
| 3498 } | 3602 } |
| 3499 | 3603 |
| 3500 Node* merge0 = graph()->NewNode(common()->Merge(2), if_true0, if_false0); | 3604 control = graph()->NewNode(common()->Merge(2), if_true0, if_false0); |
| 3501 Node* value = | 3605 value = graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2), |
| 3502 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2), | 3606 vtrue0, vfalse0, control); |
| 3503 vtrue0, vfalse0, merge0); | 3607 |
| 3504 return ValueEffectControl(value, effect, merge0); | 3608 return ValueEffectControl(value, effect, control); |
| 3505 } | 3609 } |
| 3506 | 3610 |
| 3507 EffectControlLinearizer::ValueEffectControl | 3611 EffectControlLinearizer::ValueEffectControl |
| 3508 EffectControlLinearizer::LowerFloat64RoundTruncate(Node* node, Node* effect, | 3612 EffectControlLinearizer::LowerFloat64RoundTruncate(Node* node, Node* effect, |
| 3509 Node* control) { | 3613 Node* control) { |
| 3510 // Nothing to be done if a fast hardware instruction is available. | 3614 // Nothing to be done if a fast hardware instruction is available. |
| 3511 if (machine()->Float64RoundTruncate().IsSupported()) { | 3615 if (machine()->Float64RoundTruncate().IsSupported()) { |
| 3512 return ValueEffectControl(node, effect, control); | 3616 return ValueEffectControl(node, effect, control); |
| 3513 } | 3617 } |
| 3514 | 3618 |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3647 isolate(), graph()->zone(), callable.descriptor(), 0, flags, | 3751 isolate(), graph()->zone(), callable.descriptor(), 0, flags, |
| 3648 Operator::kEliminatable); | 3752 Operator::kEliminatable); |
| 3649 to_number_operator_.set(common()->Call(desc)); | 3753 to_number_operator_.set(common()->Call(desc)); |
| 3650 } | 3754 } |
| 3651 return to_number_operator_.get(); | 3755 return to_number_operator_.get(); |
| 3652 } | 3756 } |
| 3653 | 3757 |
| 3654 } // namespace compiler | 3758 } // namespace compiler |
| 3655 } // namespace internal | 3759 } // namespace internal |
| 3656 } // namespace v8 | 3760 } // namespace v8 |
| OLD | NEW |