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

Unified 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/a64/lithium-codegen-a64.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/a64/lithium-codegen-a64.cc
diff --git a/src/a64/lithium-codegen-a64.cc b/src/a64/lithium-codegen-a64.cc
index 40ef5c6f124501e42e5c4c05735718a84eaa2627..66edbcce6787665085006b5f45b696b9b2dbbf01 100644
--- a/src/a64/lithium-codegen-a64.cc
+++ b/src/a64/lithium-codegen-a64.cc
@@ -1062,6 +1062,15 @@ void LCodeGen::DeoptimizeIfZero(Register rt, LEnvironment* environment) {
}
+void LCodeGen::DeoptimizeIfNotZero(Register rt, LEnvironment* environment) {
+ Label dont_deopt;
+ Deoptimizer::BailoutType bailout_type = DeoptimizeHeader(environment, NULL);
+ __ Cbz(rt, &dont_deopt);
+ Deoptimize(environment, bailout_type);
+ __ Bind(&dont_deopt);
+}
+
+
void LCodeGen::DeoptimizeIfNegative(Register rt, LEnvironment* environment) {
Label dont_deopt;
Deoptimizer::BailoutType bailout_type = DeoptimizeHeader(environment, NULL);
@@ -2581,131 +2590,162 @@ void LCodeGen::DoDeoptimize(LDeoptimize* instr) {
}
-void LCodeGen::DoDivI(LDivI* instr) {
- Register dividend = ToRegister32(instr->left());
- Register result = ToRegister32(instr->result());
+void LCodeGen::DoDivConstI(LDivConstI* instr) {
+ ASSERT(instr->hydrogen()->RightIsPowerOf2());
- bool has_power_of_2_divisor = instr->hydrogen()->RightIsPowerOf2();
+ HDiv* hinstr = instr->hydrogen();
bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
- bool bailout_on_minus_zero =
- instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero);
- bool can_be_div_by_zero =
- instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero);
+ bool bailout_on_minus_zero = hinstr->CheckFlag(HValue::kBailoutOnMinusZero);
bool all_uses_truncating_to_int32 =
- instr->hydrogen()->CheckFlag(HInstruction::kAllUsesTruncatingToInt32);
+ hinstr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32);
+ bool is_smi = hinstr->representation().IsSmi();
+
+ Register dividend = is_smi ?
+ ToRegister(instr->left()) : ToRegister32(instr->left());
+ Register result = is_smi ?
+ ToRegister(instr->result()) : ToRegister32(instr->result());
+ int32_t divisor = ToInteger32(LConstantOperand::cast(instr->right()));
+ int32_t power;
+ int64_t power_mask;
+ Label done;
- if (has_power_of_2_divisor) {
- ASSERT(instr->temp() == NULL);
- int32_t divisor = ToInteger32(LConstantOperand::cast(instr->right()));
- int32_t power;
- int32_t power_mask;
- Label deopt, done;
-
- ASSERT(divisor != 0);
- if (divisor > 0) {
- power = WhichPowerOf2(divisor);
- power_mask = divisor - 1;
- } else {
- // Check for (0 / -x) as that will produce negative zero.
- if (bailout_on_minus_zero) {
- if (all_uses_truncating_to_int32) {
- // If all uses truncate, and the dividend is zero, the truncated
- // result is zero.
- __ Mov(result, 0);
- __ Cbz(dividend, &done);
- } else {
- __ Cbz(dividend, &deopt);
- }
- }
- // Check for (kMinInt / -1).
- if ((divisor == -1) && can_overflow && !all_uses_truncating_to_int32) {
- // Check for kMinInt by subtracting one and checking for overflow.
- __ Cmp(dividend, 1);
- __ B(vs, &deopt);
+ ASSERT(divisor != 0);
+ if (divisor > 0) {
+ power = WhichPowerOf2(divisor);
+ power_mask = divisor - 1;
+ } else {
+ // Check for (0 / -x) as that will produce negative zero.
+ if (bailout_on_minus_zero) {
+ if (all_uses_truncating_to_int32) {
+ // If all uses truncate, and the dividend is zero, the truncated
+ // result is zero.
+ __ Mov(result, 0);
+ __ Cbz(dividend, &done);
+ } else {
+ DeoptimizeIfZero(dividend, instr->environment());
}
- power = WhichPowerOf2(-divisor);
- power_mask = -divisor - 1;
}
+ // Check for (kMinInt / -1).
+ if ((divisor == -1) && can_overflow && !all_uses_truncating_to_int32) {
+ // Check for kMinInt (or the smi equivalent) by subtracting one and
+ // checking for overflow.
+ __ Cmp(dividend, 1);
+ DeoptimizeIf(vs, instr->environment());
+ }
+ power = WhichPowerOf2(-divisor);
+ power_mask = -divisor - 1;
+ }
- if (power_mask != 0) {
- if (all_uses_truncating_to_int32) {
- __ Cmp(dividend, 0);
- __ Cneg(result, dividend, lt);
- __ Asr(result, result, power);
- if (divisor > 0) __ Cneg(result, result, lt);
- if (divisor < 0) __ Cneg(result, result, gt);
- return; // Don't fall through to negation below.
- } else {
- // Deoptimize if remainder is not 0. If the least-significant
- // power bits aren't 0, it's not a multiple of 2^power, and
- // therefore, there will be a remainder.
- __ TestAndBranchIfAnySet(dividend, power_mask, &deopt);
- __ Asr(result, dividend, power);
- if (divisor < 0) __ Neg(result, result);
+ if (power_mask != 0) {
+ if (all_uses_truncating_to_int32) {
+ __ Cmp(dividend, 0);
+ __ Cneg(result, dividend, lt);
+ __ Lsr(result, result, power);
+ if (divisor > 0) __ Cneg(result, result, lt);
+ if (divisor < 0) __ Cneg(result, result, gt);
+ if (is_smi) {
+ // Clear the bits shifted into the smi tag.
+ __ Bic(result, result, kSmiShiftMask);
}
+ return;
} else {
- ASSERT((divisor == 1) || (divisor == -1));
- if (divisor < 0) {
- __ Neg(result, dividend);
- } else {
- __ Mov(result, dividend);
- }
+ if (is_smi) power_mask <<= kSmiShift;
+
+ // Deoptimize if remainder is not 0. If the least-significant
+ // power bits aren't 0, it's not a multiple of 2^power, and
+ // therefore, there will be a remainder.
+ __ Tst(dividend, power_mask);
+ DeoptimizeIf(ne, instr->environment());
+ __ Asr(result, dividend, power);
+ if (divisor < 0) __ Neg(result, result);
+
+ // If there's no remainder, there will be no set bits in the smi tag area
+ // after shifting, so the result is a valid smi.
}
- __ B(&done);
- __ Bind(&deopt);
- Deoptimize(instr->environment());
- __ Bind(&done);
} else {
- Register divisor = ToRegister32(instr->right());
+ ASSERT((divisor == 1) || (divisor == -1));
+ if (divisor < 0) {
+ __ Neg(result, dividend);
+ } else {
+ __ Mov(result, dividend);
+ }
+ }
+ __ Bind(&done);
+}
- // Issue the division first, and then check for any deopt cases whilst the
- // result is computed.
- __ Sdiv(result, dividend, divisor);
- if (!all_uses_truncating_to_int32) {
- Label deopt;
- // Check for x / 0.
- if (can_be_div_by_zero) {
- __ Cbz(divisor, &deopt);
- }
+void LCodeGen::DoDivI(LDivI* instr) {
+ HDiv* hinstr = instr->hydrogen();
+ bool can_overflow = hinstr->CheckFlag(HValue::kCanOverflow);
+ bool bailout_on_minus_zero = hinstr->CheckFlag(HValue::kBailoutOnMinusZero);
+ bool can_be_div_by_zero = hinstr->CheckFlag(HValue::kCanBeDivByZero);
+ bool all_uses_truncating_to_int32 =
+ hinstr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32);
+ bool is_smi = hinstr->representation().IsSmi();
- // Check for (0 / -x) as that will produce negative zero.
- if (bailout_on_minus_zero) {
- __ Cmp(divisor, 0);
+ Register result = ToRegister32(instr->result());
+ Register dividend, divisor;
- // If the divisor < 0 (mi), compare the dividend, and deopt if it is
- // zero, ie. zero dividend with negative divisor deopts.
- // If the divisor >= 0 (pl, the opposite of mi) set the flags to
- // condition ne, so we don't deopt, ie. positive divisor doesn't deopt.
- __ Ccmp(dividend, 0, NoFlag, mi);
- __ B(eq, &deopt);
- }
+ if (is_smi) {
+ dividend = ToRegister32(instr->temp2());
+ divisor = ToRegister32(instr->temp3());
+ __ SmiUntag(dividend, ToRegister(instr->left()));
+ __ SmiUntag(divisor, ToRegister(instr->right()));
+ } else {
+ // Additional temps are not required for the int32 case.
+ ASSERT((instr->temp2() == NULL) && (instr->temp3() == NULL));
+ dividend = ToRegister32(instr->left());
+ divisor = ToRegister32(instr->right());
+ }
- // Check for (kMinInt / -1).
- if (can_overflow) {
- // Test dividend for kMinInt by subtracting one (cmp) and checking for
- // overflow.
- __ Cmp(dividend, 1);
- // If overflow is set, ie. dividend = kMinInt, compare the divisor with
- // -1. If overflow is clear, set the flags for condition ne, as the
- // dividend isn't -1, and thus we shouldn't deopt.
- __ Ccmp(divisor, -1, NoFlag, vs);
- __ B(eq, &deopt);
- }
+ // Issue the division first, and then check for any deopt cases whilst the
+ // result is computed.
+ __ Sdiv(result, dividend, divisor);
- // Compute remainder and deopt if it's not zero.
- Register remainder = ToRegister32(instr->temp());
- __ Msub(remainder, result, divisor, dividend);
- __ Cbnz(remainder, &deopt);
+ if (all_uses_truncating_to_int32) {
+ // Equivalent to integer division, so no special handling required.
+ // Sdiv gives the correct answer for truncated infinite or minus zero
+ // results.
+ ASSERT(instr->temp1() == NULL);
+ } else {
+ // Check for x / 0.
+ if (can_be_div_by_zero) {
+ // A non-truncated zero divisor has a floating point result, so deopt.
+ DeoptimizeIfZero(divisor, instr->environment());
+ }
- Label div_ok;
- __ B(&div_ok);
- __ Bind(&deopt);
- Deoptimize(instr->environment());
- __ Bind(&div_ok);
- } else {
- ASSERT(instr->temp() == NULL);
+ // Check for (0 / -x) as that will produce negative zero.
+ if (bailout_on_minus_zero) {
+ __ Cmp(divisor, 0);
+
+ // If the divisor < 0 (mi), compare the dividend, and deopt if it is
+ // zero, ie. zero dividend with negative divisor deopts.
+ // If the divisor >= 0 (pl, the opposite of mi) set the flags to
+ // condition ne, so we don't deopt, ie. positive divisor doesn't deopt.
+ __ Ccmp(dividend, 0, NoFlag, mi);
+ DeoptimizeIf(eq, instr->environment());
+ }
+
+ // Check for (kMinInt / -1).
+ if (can_overflow) {
+ // Test dividend for kMinInt by subtracting one (cmp) and checking for
+ // overflow.
+ __ Cmp(dividend, 1);
+ // If overflow is set, ie. dividend = kMinInt, compare the divisor with
+ // -1. If overflow is clear, set the flags for condition ne, as the
+ // dividend isn't -1, and thus we shouldn't deopt.
+ __ Ccmp(divisor, -1, NoFlag, vs);
+ DeoptimizeIf(eq, instr->environment());
}
+
+ // Compute remainder and deopt if it's not zero.
+ Register remainder = ToRegister32(instr->temp1());
+ __ Msub(remainder, result, divisor, dividend);
+ DeoptimizeIfNotZero(remainder, instr->environment());
+ }
+
+ if (is_smi) {
+ __ SmiTag(result.X());
}
}
« 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