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

Side by Side Diff: src/a64/lithium-codegen-a64.cc

Issue 164183002: A64: Implement division in Lithium for smis (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/a64/lithium-codegen-a64.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 1044 matching lines...) Expand 10 before | Expand all | Expand 10 after
1055 1055
1056 void LCodeGen::DeoptimizeIfZero(Register rt, LEnvironment* environment) { 1056 void LCodeGen::DeoptimizeIfZero(Register rt, LEnvironment* environment) {
1057 Label dont_deopt; 1057 Label dont_deopt;
1058 Deoptimizer::BailoutType bailout_type = DeoptimizeHeader(environment, NULL); 1058 Deoptimizer::BailoutType bailout_type = DeoptimizeHeader(environment, NULL);
1059 __ Cbnz(rt, &dont_deopt); 1059 __ Cbnz(rt, &dont_deopt);
1060 Deoptimize(environment, bailout_type); 1060 Deoptimize(environment, bailout_type);
1061 __ Bind(&dont_deopt); 1061 __ Bind(&dont_deopt);
1062 } 1062 }
1063 1063
1064 1064
1065 void LCodeGen::DeoptimizeIfNotZero(Register rt, LEnvironment* environment) {
1066 Label dont_deopt;
1067 Deoptimizer::BailoutType bailout_type = DeoptimizeHeader(environment, NULL);
1068 __ Cbz(rt, &dont_deopt);
1069 Deoptimize(environment, bailout_type);
1070 __ Bind(&dont_deopt);
1071 }
1072
1073
1065 void LCodeGen::DeoptimizeIfNegative(Register rt, LEnvironment* environment) { 1074 void LCodeGen::DeoptimizeIfNegative(Register rt, LEnvironment* environment) {
1066 Label dont_deopt; 1075 Label dont_deopt;
1067 Deoptimizer::BailoutType bailout_type = DeoptimizeHeader(environment, NULL); 1076 Deoptimizer::BailoutType bailout_type = DeoptimizeHeader(environment, NULL);
1068 __ Tbz(rt, rt.Is64Bits() ? kXSignBit : kWSignBit, &dont_deopt); 1077 __ Tbz(rt, rt.Is64Bits() ? kXSignBit : kWSignBit, &dont_deopt);
1069 Deoptimize(environment, bailout_type); 1078 Deoptimize(environment, bailout_type);
1070 __ Bind(&dont_deopt); 1079 __ Bind(&dont_deopt);
1071 } 1080 }
1072 1081
1073 1082
1074 void LCodeGen::DeoptimizeIfSmi(Register rt, 1083 void LCodeGen::DeoptimizeIfSmi(Register rt,
(...skipping 1499 matching lines...) Expand 10 before | Expand all | Expand 10 after
2574 if (info()->IsStub() && (type == Deoptimizer::EAGER)) { 2583 if (info()->IsStub() && (type == Deoptimizer::EAGER)) {
2575 type = Deoptimizer::LAZY; 2584 type = Deoptimizer::LAZY;
2576 } 2585 }
2577 2586
2578 Comment(";;; deoptimize: %s", instr->hydrogen()->reason()); 2587 Comment(";;; deoptimize: %s", instr->hydrogen()->reason());
2579 DeoptimizeHeader(instr->environment(), &type); 2588 DeoptimizeHeader(instr->environment(), &type);
2580 Deoptimize(instr->environment(), type); 2589 Deoptimize(instr->environment(), type);
2581 } 2590 }
2582 2591
2583 2592
2593 void LCodeGen::DoDivConstI(LDivConstI* instr) {
2594 ASSERT(instr->hydrogen()->RightIsPowerOf2());
2595
2596 HDiv* hinstr = instr->hydrogen();
2597 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
2598 bool bailout_on_minus_zero = hinstr->CheckFlag(HValue::kBailoutOnMinusZero);
2599 bool all_uses_truncating_to_int32 =
2600 hinstr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32);
2601 bool is_smi = hinstr->representation().IsSmi();
2602
2603 Register dividend = is_smi ?
2604 ToRegister(instr->left()) : ToRegister32(instr->left());
2605 Register result = is_smi ?
2606 ToRegister(instr->result()) : ToRegister32(instr->result());
2607 int32_t divisor = ToInteger32(LConstantOperand::cast(instr->right()));
2608 int32_t power;
2609 int64_t power_mask;
2610 Label done;
2611
2612 ASSERT(divisor != 0);
2613 if (divisor > 0) {
2614 power = WhichPowerOf2(divisor);
2615 power_mask = divisor - 1;
2616 } else {
2617 // Check for (0 / -x) as that will produce negative zero.
2618 if (bailout_on_minus_zero) {
2619 if (all_uses_truncating_to_int32) {
2620 // If all uses truncate, and the dividend is zero, the truncated
2621 // result is zero.
2622 __ Mov(result, 0);
2623 __ Cbz(dividend, &done);
2624 } else {
2625 DeoptimizeIfZero(dividend, instr->environment());
2626 }
2627 }
2628 // Check for (kMinInt / -1).
2629 if ((divisor == -1) && can_overflow && !all_uses_truncating_to_int32) {
2630 // Check for kMinInt (or the smi equivalent) by subtracting one and
2631 // checking for overflow.
2632 __ Cmp(dividend, 1);
2633 DeoptimizeIf(vs, instr->environment());
2634 }
2635 power = WhichPowerOf2(-divisor);
2636 power_mask = -divisor - 1;
2637 }
2638
2639 if (power_mask != 0) {
2640 if (all_uses_truncating_to_int32) {
2641 __ Cmp(dividend, 0);
2642 __ Cneg(result, dividend, lt);
2643 __ Lsr(result, result, power);
2644 if (divisor > 0) __ Cneg(result, result, lt);
2645 if (divisor < 0) __ Cneg(result, result, gt);
2646 if (is_smi) {
2647 // Clear the bits shifted into the smi tag.
2648 __ Bic(result, result, kSmiShiftMask);
2649 }
2650 return;
2651 } else {
2652 if (is_smi) power_mask <<= kSmiShift;
2653
2654 // Deoptimize if remainder is not 0. If the least-significant
2655 // power bits aren't 0, it's not a multiple of 2^power, and
2656 // therefore, there will be a remainder.
2657 __ Tst(dividend, power_mask);
2658 DeoptimizeIf(ne, instr->environment());
2659 __ Asr(result, dividend, power);
2660 if (divisor < 0) __ Neg(result, result);
2661
2662 // If there's no remainder, there will be no set bits in the smi tag area
2663 // after shifting, so the result is a valid smi.
2664 }
2665 } else {
2666 ASSERT((divisor == 1) || (divisor == -1));
2667 if (divisor < 0) {
2668 __ Neg(result, dividend);
2669 } else {
2670 __ Mov(result, dividend);
2671 }
2672 }
2673 __ Bind(&done);
2674 }
2675
2676
2584 void LCodeGen::DoDivI(LDivI* instr) { 2677 void LCodeGen::DoDivI(LDivI* instr) {
2585 Register dividend = ToRegister32(instr->left()); 2678 HDiv* hinstr = instr->hydrogen();
2679 bool can_overflow = hinstr->CheckFlag(HValue::kCanOverflow);
2680 bool bailout_on_minus_zero = hinstr->CheckFlag(HValue::kBailoutOnMinusZero);
2681 bool can_be_div_by_zero = hinstr->CheckFlag(HValue::kCanBeDivByZero);
2682 bool all_uses_truncating_to_int32 =
2683 hinstr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32);
2684 bool is_smi = hinstr->representation().IsSmi();
2685
2586 Register result = ToRegister32(instr->result()); 2686 Register result = ToRegister32(instr->result());
2687 Register dividend, divisor;
2587 2688
2588 bool has_power_of_2_divisor = instr->hydrogen()->RightIsPowerOf2(); 2689 if (is_smi) {
2589 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); 2690 dividend = ToRegister32(instr->temp2());
2590 bool bailout_on_minus_zero = 2691 divisor = ToRegister32(instr->temp3());
2591 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero); 2692 __ SmiUntag(dividend, ToRegister(instr->left()));
2592 bool can_be_div_by_zero = 2693 __ SmiUntag(divisor, ToRegister(instr->right()));
2593 instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero); 2694 } else {
2594 bool all_uses_truncating_to_int32 = 2695 // Additional temps are not required for the int32 case.
2595 instr->hydrogen()->CheckFlag(HInstruction::kAllUsesTruncatingToInt32); 2696 ASSERT((instr->temp2() == NULL) && (instr->temp3() == NULL));
2697 dividend = ToRegister32(instr->left());
2698 divisor = ToRegister32(instr->right());
2699 }
2596 2700
2597 if (has_power_of_2_divisor) { 2701 // Issue the division first, and then check for any deopt cases whilst the
2598 ASSERT(instr->temp() == NULL); 2702 // result is computed.
2599 int32_t divisor = ToInteger32(LConstantOperand::cast(instr->right())); 2703 __ Sdiv(result, dividend, divisor);
2600 int32_t power;
2601 int32_t power_mask;
2602 Label deopt, done;
2603 2704
2604 ASSERT(divisor != 0); 2705 if (all_uses_truncating_to_int32) {
2605 if (divisor > 0) { 2706 // Equivalent to integer division, so no special handling required.
2606 power = WhichPowerOf2(divisor); 2707 // Sdiv gives the correct answer for truncated infinite or minus zero
2607 power_mask = divisor - 1; 2708 // results.
2608 } else { 2709 ASSERT(instr->temp1() == NULL);
2609 // Check for (0 / -x) as that will produce negative zero. 2710 } else {
2610 if (bailout_on_minus_zero) { 2711 // Check for x / 0.
2611 if (all_uses_truncating_to_int32) { 2712 if (can_be_div_by_zero) {
2612 // If all uses truncate, and the dividend is zero, the truncated 2713 // A non-truncated zero divisor has a floating point result, so deopt.
2613 // result is zero. 2714 DeoptimizeIfZero(divisor, instr->environment());
2614 __ Mov(result, 0);
2615 __ Cbz(dividend, &done);
2616 } else {
2617 __ Cbz(dividend, &deopt);
2618 }
2619 }
2620 // Check for (kMinInt / -1).
2621 if ((divisor == -1) && can_overflow && !all_uses_truncating_to_int32) {
2622 // Check for kMinInt by subtracting one and checking for overflow.
2623 __ Cmp(dividend, 1);
2624 __ B(vs, &deopt);
2625 }
2626 power = WhichPowerOf2(-divisor);
2627 power_mask = -divisor - 1;
2628 } 2715 }
2629 2716
2630 if (power_mask != 0) { 2717 // Check for (0 / -x) as that will produce negative zero.
2631 if (all_uses_truncating_to_int32) { 2718 if (bailout_on_minus_zero) {
2632 __ Cmp(dividend, 0); 2719 __ Cmp(divisor, 0);
2633 __ Cneg(result, dividend, lt); 2720
2634 __ Asr(result, result, power); 2721 // If the divisor < 0 (mi), compare the dividend, and deopt if it is
2635 if (divisor > 0) __ Cneg(result, result, lt); 2722 // zero, ie. zero dividend with negative divisor deopts.
2636 if (divisor < 0) __ Cneg(result, result, gt); 2723 // If the divisor >= 0 (pl, the opposite of mi) set the flags to
2637 return; // Don't fall through to negation below. 2724 // condition ne, so we don't deopt, ie. positive divisor doesn't deopt.
2638 } else { 2725 __ Ccmp(dividend, 0, NoFlag, mi);
2639 // Deoptimize if remainder is not 0. If the least-significant 2726 DeoptimizeIf(eq, instr->environment());
2640 // power bits aren't 0, it's not a multiple of 2^power, and
2641 // therefore, there will be a remainder.
2642 __ TestAndBranchIfAnySet(dividend, power_mask, &deopt);
2643 __ Asr(result, dividend, power);
2644 if (divisor < 0) __ Neg(result, result);
2645 }
2646 } else {
2647 ASSERT((divisor == 1) || (divisor == -1));
2648 if (divisor < 0) {
2649 __ Neg(result, dividend);
2650 } else {
2651 __ Mov(result, dividend);
2652 }
2653 } 2727 }
2654 __ B(&done);
2655 __ Bind(&deopt);
2656 Deoptimize(instr->environment());
2657 __ Bind(&done);
2658 } else {
2659 Register divisor = ToRegister32(instr->right());
2660 2728
2661 // Issue the division first, and then check for any deopt cases whilst the 2729 // Check for (kMinInt / -1).
2662 // result is computed. 2730 if (can_overflow) {
2663 __ Sdiv(result, dividend, divisor); 2731 // Test dividend for kMinInt by subtracting one (cmp) and checking for
2732 // overflow.
2733 __ Cmp(dividend, 1);
2734 // If overflow is set, ie. dividend = kMinInt, compare the divisor with
2735 // -1. If overflow is clear, set the flags for condition ne, as the
2736 // dividend isn't -1, and thus we shouldn't deopt.
2737 __ Ccmp(divisor, -1, NoFlag, vs);
2738 DeoptimizeIf(eq, instr->environment());
2739 }
2664 2740
2665 if (!all_uses_truncating_to_int32) { 2741 // Compute remainder and deopt if it's not zero.
2666 Label deopt; 2742 Register remainder = ToRegister32(instr->temp1());
2667 // Check for x / 0. 2743 __ Msub(remainder, result, divisor, dividend);
2668 if (can_be_div_by_zero) { 2744 DeoptimizeIfNotZero(remainder, instr->environment());
2669 __ Cbz(divisor, &deopt); 2745 }
2670 }
2671 2746
2672 // Check for (0 / -x) as that will produce negative zero. 2747 if (is_smi) {
2673 if (bailout_on_minus_zero) { 2748 __ SmiTag(result.X());
2674 __ Cmp(divisor, 0);
2675
2676 // If the divisor < 0 (mi), compare the dividend, and deopt if it is
2677 // zero, ie. zero dividend with negative divisor deopts.
2678 // If the divisor >= 0 (pl, the opposite of mi) set the flags to
2679 // condition ne, so we don't deopt, ie. positive divisor doesn't deopt.
2680 __ Ccmp(dividend, 0, NoFlag, mi);
2681 __ B(eq, &deopt);
2682 }
2683
2684 // Check for (kMinInt / -1).
2685 if (can_overflow) {
2686 // Test dividend for kMinInt by subtracting one (cmp) and checking for
2687 // overflow.
2688 __ Cmp(dividend, 1);
2689 // If overflow is set, ie. dividend = kMinInt, compare the divisor with
2690 // -1. If overflow is clear, set the flags for condition ne, as the
2691 // dividend isn't -1, and thus we shouldn't deopt.
2692 __ Ccmp(divisor, -1, NoFlag, vs);
2693 __ B(eq, &deopt);
2694 }
2695
2696 // Compute remainder and deopt if it's not zero.
2697 Register remainder = ToRegister32(instr->temp());
2698 __ Msub(remainder, result, divisor, dividend);
2699 __ Cbnz(remainder, &deopt);
2700
2701 Label div_ok;
2702 __ B(&div_ok);
2703 __ Bind(&deopt);
2704 Deoptimize(instr->environment());
2705 __ Bind(&div_ok);
2706 } else {
2707 ASSERT(instr->temp() == NULL);
2708 }
2709 } 2749 }
2710 } 2750 }
2711 2751
2712 2752
2713 void LCodeGen::DoDoubleToIntOrSmi(LDoubleToIntOrSmi* instr) { 2753 void LCodeGen::DoDoubleToIntOrSmi(LDoubleToIntOrSmi* instr) {
2714 DoubleRegister input = ToDoubleRegister(instr->value()); 2754 DoubleRegister input = ToDoubleRegister(instr->value());
2715 Register result = ToRegister32(instr->result()); 2755 Register result = ToRegister32(instr->result());
2716 Label done, deopt; 2756 Label done, deopt;
2717 2757
2718 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 2758 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
(...skipping 2998 matching lines...) Expand 10 before | Expand all | Expand 10 after
5717 __ Bind(&out_of_object); 5757 __ Bind(&out_of_object);
5718 __ Ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); 5758 __ Ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset));
5719 // Index is equal to negated out of object property index plus 1. 5759 // Index is equal to negated out of object property index plus 1.
5720 __ Sub(result, result, Operand::UntagSmiAndScale(index, kPointerSizeLog2)); 5760 __ Sub(result, result, Operand::UntagSmiAndScale(index, kPointerSizeLog2));
5721 __ Ldr(result, FieldMemOperand(result, 5761 __ Ldr(result, FieldMemOperand(result,
5722 FixedArray::kHeaderSize - kPointerSize)); 5762 FixedArray::kHeaderSize - kPointerSize));
5723 __ Bind(&done); 5763 __ Bind(&done);
5724 } 5764 }
5725 5765
5726 } } // namespace v8::internal 5766 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/a64/lithium-codegen-a64.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698