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

Unified Diff: src/x64/lithium-codegen-x64.cc

Issue 10382033: x86/x64 port of Math.floor(x/y) to use integer division for specific divisor (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 8 years, 7 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
Index: src/x64/lithium-codegen-x64.cc
===================================================================
--- src/x64/lithium-codegen-x64.cc (revision 11554)
+++ src/x64/lithium-codegen-x64.cc (working copy)
@@ -882,6 +882,86 @@
}
+void LCodeGen::DoMathFloorOfDiv(LMathFloorOfDiv* instr) {
+ ASSERT(instr->InputAt(1)->IsConstantOperand());
+
+ const Register dividend = ToRegister(instr->InputAt(0));
+ int32_t divisor = ToInteger32(LConstantOperand::cast(instr->InputAt(1)));
+ const Register result = ToRegister(instr->result());
+
+ switch (divisor) {
+ case 0:
+ DeoptimizeIf(no_condition, instr->environment());
+ return;
+
+ case 1:
+ if (!result.is(dividend)) {
+ __ movl(result, dividend);
+ }
+ return;
+
+ case -1:
+ if (!result.is(dividend)) {
+ __ movl(result, dividend);
+ }
+ __ negl(result);
+ // FIXME: set & check HValue::kBailoutOnMinusZero
Yang 2012/06/19 15:41:38 Any changes here?
+ DeoptimizeIf(zero, instr->environment());
+ if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
+ DeoptimizeIf(overflow, instr->environment());
+ }
+ return;
+ }
+
+ uint32_t divisor_abs = abs(divisor);
+ if (IsPowerOf2(divisor_abs)) {
+ int32_t power = WhichPowerOf2(divisor_abs);
+ if (divisor < 0) {
+ __ movsxlq(result, dividend);
+ __ neg(result);
+ // FIXME: set & check HValue::kBailoutOnMinusZero
Yang 2012/06/19 15:41:38 Ditto.
+ DeoptimizeIf(zero, instr->environment());
+ __ sar(result, Immediate(power));
+ } else {
+ if (!result.is(dividend)) {
+ __ movl(result, dividend);
+ }
+ __ sarl(result, Immediate(power));
+ }
+ } else {
+ Register reg1 = ToRegister(instr->TempAt(0));
+ Register reg2 = ToRegister(instr->result());
+
+ // b: 2^b < divisor_abs < 2^(b+1)
+ unsigned b = 31 - CompilerIntrinsics::CountLeadingZeros(divisor_abs);
+ unsigned shift = 32 + b; // precision +1bit (effectively)
+ double multiplier_f = static_cast<double>((uint64_t)1 << shift)
Yang 2012/06/19 15:41:38 Use static_cast please.
+ / divisor_abs;
+ int64_t multiplier;
+ if (multiplier_f - floor(multiplier_f) < 0.5) {
+ multiplier = floor(multiplier_f);
+ } else {
+ multiplier = floor(multiplier_f) + 1;
+ }
+ // multiplier is a uint32
+ ASSERT(multiplier > 0 && multiplier < ((int64_t)1<<32));
Yang 2012/06/19 15:41:38 Use static_cast please.
+ // the multiply is int64, so sign-extend to r64
+ __ movsxlq(reg1, dividend);
+ if (divisor < 0) {
+ __ neg(reg1);
+ // FIXME: set & check HValue::kBailoutOnMinusZero
Yang 2012/06/19 15:41:38 Ditto.
+ DeoptimizeIf(zero, instr->environment());
+ }
+ __ movq(reg2, multiplier, RelocInfo::NONE);
+ // result just fit in r64: because it's int32 * uint32
+ __ imul(reg2, reg1);
+
+ __ addq(reg2, Immediate(1<<30)); // effectively +1/2d
+ __ sar(reg2, Immediate(shift));
+ }
+}
+
+
void LCodeGen::DoDivI(LDivI* instr) {
LOperand* right = instr->InputAt(1);
ASSERT(ToRegister(instr->result()).is(rax));

Powered by Google App Engine
This is Rietveld 408576698