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 |