Revision: 8459
Author: sgje...@chromium.org
Date: Wed Jun 29 03:51:06 2011
Log: ARM: Improve register allocation and constraints (try 2).
Gives ~20% boost for Crypto benchmark on A9.
BUG=none
TEST=added to mjsunit/div-mod.js
Review URL: http://codereview.chromium.org//7276034
Patch from Martyn Capewell <m.m.capew...@googlemail.com>.
http://code.google.com/p/v8/source/detail?r=8459
Modified:
/branches/bleeding_edge/src/arm/assembler-arm.h
/branches/bleeding_edge/src/arm/code-stubs-arm.cc
/branches/bleeding_edge/src/arm/lithium-arm.cc
/branches/bleeding_edge/src/arm/lithium-codegen-arm.cc
/branches/bleeding_edge/src/arm/lithium-codegen-arm.h
/branches/bleeding_edge/src/arm/macro-assembler-arm.cc
/branches/bleeding_edge/src/arm/macro-assembler-arm.h
/branches/bleeding_edge/test/mjsunit/div-mod.js
=======================================
--- /branches/bleeding_edge/src/arm/assembler-arm.h Thu Jun 23 05:03:16 2011
+++ /branches/bleeding_edge/src/arm/assembler-arm.h Wed Jun 29 03:51:06 2011
@@ -167,13 +167,14 @@
// Double word VFP register.
struct DwVfpRegister {
- // d0 has been excluded from allocation. This is following ia32
- // where xmm0 is excluded. This should be revisited.
- // Currently d0 is used as a scratch register.
- // d1 has also been excluded from allocation to be used as a scratch
- // register as well.
static const int kNumRegisters = 16;
- static const int kNumAllocatableRegisters = 15;
+ // A few double registers are reserved: one as a scratch register and
one to
+ // hold 0.0, that does not fit in the immediate field of vmov
instructions.
+ // d14: 0.0
+ // d15: scratch register.
+ static const int kNumReservedRegisters = 2;
+ static const int kNumAllocatableRegisters = kNumRegisters -
+ kNumReservedRegisters;
static int ToAllocationIndex(DwVfpRegister reg) {
ASSERT(reg.code() != 0);
@@ -188,6 +189,7 @@
static const char* AllocationIndexToString(int index) {
ASSERT(index >= 0 && index < kNumAllocatableRegisters);
const char* const names[] = {
+ "d0",
"d1",
"d2",
"d3",
@@ -200,9 +202,7 @@
"d10",
"d11",
"d12",
- "d13",
- "d14",
- "d15"
+ "d13"
};
return names[index];
}
@@ -306,6 +306,7 @@
// Aliases for double registers.
const DwVfpRegister kFirstCalleeSavedDoubleReg = d8;
const DwVfpRegister kLastCalleeSavedDoubleReg = d15;
+const DwVfpRegister kDoubleRegZero = d14;
// Coprocessor register
=======================================
--- /branches/bleeding_edge/src/arm/code-stubs-arm.cc Tue Jun 28 08:22:08
2011
+++ /branches/bleeding_edge/src/arm/code-stubs-arm.cc Wed Jun 29 03:51:06
2011
@@ -3540,6 +3540,8 @@
CpuFeatures::Scope scope(VFP3);
// Save callee-saved vfp registers.
__ vstm(db_w, sp, kFirstCalleeSavedDoubleReg,
kLastCalleeSavedDoubleReg);
+ // Set up the reserved register for 0.0.
+ __ vmov(kDoubleRegZero, 0.0);
}
// Get address of argv, see stm above.
=======================================
--- /branches/bleeding_edge/src/arm/lithium-arm.cc Tue Jun 28 07:21:55 2011
+++ /branches/bleeding_edge/src/arm/lithium-arm.cc Wed Jun 29 03:51:06 2011
@@ -822,7 +822,7 @@
LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand());
- return DefineSameAsFirst(new LBitI(op, left, right));
+ return DefineAsRegister(new LBitI(op, left, right));
} else {
ASSERT(instr->representation().IsTagged());
ASSERT(instr->left()->representation().IsTagged());
@@ -861,7 +861,7 @@
right = chunk_->DefineConstantOperand(constant);
constant_value = constant->Integer32Value() & 0x1f;
} else {
- right = UseRegister(right_value);
+ right = UseRegisterAtStart(right_value);
}
// Shift operations can only deoptimize if we do a logical shift
@@ -878,7 +878,7 @@
}
LInstruction* result =
- DefineSameAsFirst(new LShiftI(op, left, right, does_deopt));
+ DefineAsRegister(new LShiftI(op, left, right, does_deopt));
return does_deopt ? AssignEnvironment(result) : result;
}
@@ -892,7 +892,7 @@
LOperand* left = UseRegisterAtStart(instr->left());
LOperand* right = UseRegisterAtStart(instr->right());
LArithmeticD* result = new LArithmeticD(op, left, right);
- return DefineSameAsFirst(result);
+ return DefineAsRegister(result);
}
@@ -1233,15 +1233,15 @@
LUnaryMathOperation* result = new LUnaryMathOperation(input, temp);
switch (op) {
case kMathAbs:
- return
AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result)));
+ return
AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
case kMathFloor:
return
AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
case kMathSqrt:
- return DefineSameAsFirst(result);
+ return DefineAsRegister(result);
case kMathRound:
return AssignEnvironment(DefineAsRegister(result));
case kMathPowHalf:
- return DefineSameAsFirst(result);
+ return DefineAsRegister(result);
default:
UNREACHABLE();
return NULL;
@@ -1319,7 +1319,7 @@
LInstruction* LChunkBuilder::DoBitNot(HBitNot* instr) {
ASSERT(instr->value()->representation().IsInteger32());
ASSERT(instr->representation().IsInteger32());
- return DefineSameAsFirst(new
LBitNotI(UseRegisterAtStart(instr->value())));
+ return DefineAsRegister(new
LBitNotI(UseRegisterAtStart(instr->value())));
}
@@ -1364,15 +1364,20 @@
mod = new LModI(value, UseOrConstant(instr->right()));
} else {
LOperand* dividend = UseRegister(instr->left());
- LOperand* divisor = UseRegisterAtStart(instr->right());
+ LOperand* divisor = UseRegister(instr->right());
mod = new LModI(dividend,
divisor,
TempRegister(),
- FixedTemp(d1),
- FixedTemp(d2));
+ FixedTemp(d10),
+ FixedTemp(d11));
}
- return AssignEnvironment(DefineSameAsFirst(mod));
+ if (instr->CheckFlag(HValue::kBailoutOnMinusZero) ||
+ instr->CheckFlag(HValue::kCanBeDivByZero)) {
+ return AssignEnvironment(DefineAsRegister(mod));
+ } else {
+ return DefineAsRegister(mod);
+ }
} else if (instr->representation().IsTagged()) {
return DoArithmeticT(Token::MOD, instr);
} else {
@@ -1392,15 +1397,18 @@
if (instr->representation().IsInteger32()) {
ASSERT(instr->left()->representation().IsInteger32());
ASSERT(instr->right()->representation().IsInteger32());
- LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
+ LOperand* left;
LOperand* right = UseOrConstant(instr->MostConstantOperand());
LOperand* temp = NULL;
if (instr->CheckFlag(HValue::kBailoutOnMinusZero) &&
(instr->CheckFlag(HValue::kCanOverflow) ||
!right->IsConstantOperand())) {
+ left = UseRegister(instr->LeastConstantOperand());
temp = TempRegister();
- }
- return AssignEnvironment(DefineSameAsFirst(new LMulI(left, right,
temp)));
+ } else {
+ left = UseRegisterAtStart(instr->LeastConstantOperand());
+ }
+ return AssignEnvironment(DefineAsRegister(new LMulI(left, right,
temp)));
} else if (instr->representation().IsDouble()) {
return DoArithmeticD(Token::MUL, instr);
@@ -1418,7 +1426,7 @@
LOperand* left = UseRegisterAtStart(instr->left());
LOperand* right = UseOrConstantAtStart(instr->right());
LSubI* sub = new LSubI(left, right);
- LInstruction* result = DefineSameAsFirst(sub);
+ LInstruction* result = DefineAsRegister(sub);
if (instr->CheckFlag(HValue::kCanOverflow)) {
result = AssignEnvironment(result);
}
@@ -1438,7 +1446,7 @@
LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand());
LAddI* add = new LAddI(left, right);
- LInstruction* result = DefineSameAsFirst(add);
+ LInstruction* result = DefineAsRegister(add);
if (instr->CheckFlag(HValue::kCanOverflow)) {
result = AssignEnvironment(result);
}
@@ -1604,7 +1612,7 @@
LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) {
LOperand* object = UseRegister(instr->value());
LValueOf* result = new LValueOf(object, TempRegister());
- return AssignEnvironment(DefineSameAsFirst(result));
+ return AssignEnvironment(DefineAsRegister(result));
}
@@ -1659,7 +1667,7 @@
LOperand* temp1 = TempRegister();
LOperand* temp2 = instr->CanTruncateToInt32() ? TempRegister()
: NULL;
- LOperand* temp3 = instr->CanTruncateToInt32() ? FixedTemp(d3)
+ LOperand* temp3 = instr->CanTruncateToInt32() ? FixedTemp(d11)
: NULL;
res = DefineSameAsFirst(new LTaggedToI(value, temp1, temp2,
temp3));
res = AssignEnvironment(res);
@@ -1753,14 +1761,14 @@
Representation input_rep = value->representation();
LOperand* reg = UseRegister(value);
if (input_rep.IsDouble()) {
- return DefineAsRegister(new LClampDToUint8(reg, FixedTemp(d1)));
+ return DefineAsRegister(new LClampDToUint8(reg, FixedTemp(d11)));
} else if (input_rep.IsInteger32()) {
return DefineAsRegister(new LClampIToUint8(reg));
} else {
ASSERT(input_rep.IsTagged());
// Register allocator doesn't (yet) support allocation of double
// temps. Reserve d1 explicitly.
- LClampTToUint8* result = new LClampTToUint8(reg, FixedTemp(d1));
+ LClampTToUint8* result = new LClampTToUint8(reg, FixedTemp(d11));
return AssignEnvironment(DefineAsRegister(result));
}
}
@@ -1784,7 +1792,7 @@
ASSERT(input_rep.IsTagged());
LOperand* temp1 = TempRegister();
LOperand* temp2 = TempRegister();
- LOperand* temp3 = FixedTemp(d3);
+ LOperand* temp3 = FixedTemp(d11);
LTaggedToI* res = new LTaggedToI(reg, temp1, temp2, temp3);
return AssignEnvironment(DefineSameAsFirst(res));
}
@@ -1922,7 +1930,7 @@
LOperand* obj = UseRegisterAtStart(instr->object());
LOperand* key = UseRegisterAtStart(instr->key());
LLoadKeyedFastElement* result = new LLoadKeyedFastElement(obj, key);
- return AssignEnvironment(DefineSameAsFirst(result));
+ return AssignEnvironment(DefineAsRegister(result));
}
=======================================
--- /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Tue Jun 28
07:21:55 2011
+++ /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Wed Jun 29
03:51:06 2011
@@ -873,6 +873,7 @@
void LCodeGen::DoModI(LModI* instr) {
if (instr->hydrogen()->HasPowerOf2Divisor()) {
Register dividend = ToRegister(instr->InputAt(0));
+ Register result = ToRegister(instr->result());
int32_t divisor =
HConstant::cast(instr->hydrogen()->right())->Integer32Value();
@@ -882,17 +883,15 @@
Label positive_dividend, done;
__ cmp(dividend, Operand(0));
__ b(pl, &positive_dividend);
- __ rsb(dividend, dividend, Operand(0));
- __ and_(dividend, dividend, Operand(divisor - 1));
- __ rsb(dividend, dividend, Operand(0), SetCC);
+ __ rsb(result, dividend, Operand(0));
+ __ and_(result, result, Operand(divisor - 1), SetCC);
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
- __ b(ne, &done);
- DeoptimizeIf(al, instr->environment());
- } else {
- __ b(&done);
- }
+ DeoptimizeIf(eq, instr->environment());
+ }
+ __ rsb(result, result, Operand(0));
+ __ b(&done);
__ bind(&positive_dividend);
- __ and_(dividend, dividend, Operand(divisor - 1));
+ __ and_(result, dividend, Operand(divisor - 1));
__ bind(&done);
return;
}
@@ -908,8 +907,6 @@
DwVfpRegister divisor = ToDoubleRegister(instr->TempAt(2));
DwVfpRegister quotient = double_scratch0();
- ASSERT(result.is(left));
-
ASSERT(!dividend.is(divisor));
ASSERT(!dividend.is(quotient));
ASSERT(!divisor.is(quotient));
@@ -924,6 +921,8 @@
__ cmp(right, Operand(0));
DeoptimizeIf(eq, instr->environment());
}
+
+ __ Move(result, left);
// (0 % x) must yield 0 (if x is finite, which is the case here).
__ cmp(left, Operand(0));
@@ -1120,9 +1119,9 @@
void LCodeGen::DoMulI(LMulI* instr) {
- ASSERT(instr->result()->Equals(instr->InputAt(0)));
Register scratch = scratch0();
Register result = ToRegister(instr->result());
+ // Note that result may alias left.
Register left = ToRegister(instr->InputAt(0));
LOperand* right_op = instr->InputAt(1);
@@ -1155,7 +1154,7 @@
__ mov(result, Operand(0));
break;
case 1:
- // Nothing to do.
+ __ Move(result, left);
break;
default:
// Multiplying by powers of two and powers of two plus or minus
@@ -1217,30 +1216,29 @@
void LCodeGen::DoBitI(LBitI* instr) {
- LOperand* left = instr->InputAt(0);
- LOperand* right = instr->InputAt(1);
- ASSERT(left->Equals(instr->result()));
- ASSERT(left->IsRegister());
- Register result = ToRegister(left);
- Operand right_operand(no_reg);
-
- if (right->IsStackSlot() || right->IsArgument()) {
- Register right_reg = EmitLoadRegister(right, ip);
- right_operand = Operand(right_reg);
+ LOperand* left_op = instr->InputAt(0);
+ LOperand* right_op = instr->InputAt(1);
+ ASSERT(left_op->IsRegister());
+ Register left = ToRegister(left_op);
+ Register result = ToRegister(instr->result());
+ Operand right(no_reg);
+
+ if (right_op->IsStackSlot() || right_op->IsArgument()) {
+ right = Operand(EmitLoadRegister(right_op, ip));
} else {
- ASSERT(right->IsRegister() || right->IsConstantOperand());
- right_operand = ToOperand(right);
+ ASSERT(right_op->IsRegister() || right_op->IsConstantOperand());
+ right = ToOperand(right_op);
}
switch (instr->op()) {
case Token::BIT_AND:
- __ and_(result, ToRegister(left), right_operand);
+ __ and_(result, left, right);
break;
case Token::BIT_OR:
- __ orr(result, ToRegister(left), right_operand);
+ __ orr(result, left, right);
break;
case Token::BIT_XOR:
- __ eor(result, ToRegister(left), right_operand);
+ __ eor(result, left, right);
break;
default:
UNREACHABLE();
@@ -1250,54 +1248,62 @@
void LCodeGen::DoShiftI(LShiftI* instr) {
+ // Both 'left' and 'right' are "used at start" (see LCodeGen::DoShift),
so
+ // result may alias either of them.
+ LOperand* right_op = instr->InputAt(1);
+ Register left = ToRegister(instr->InputAt(0));
+ Register result = ToRegister(instr->result());
Register scratch = scratch0();
- LOperand* left = instr->InputAt(0);
- LOperand* right = instr->InputAt(1);
- ASSERT(left->Equals(instr->result()));
- ASSERT(left->IsRegister());
- Register result = ToRegister(left);
- if (right->IsRegister()) {
- // Mask the right operand.
- __ and_(scratch, ToRegister(right), Operand(0x1F));
+ if (right_op->IsRegister()) {
+ // Mask the right_op operand.
+ __ and_(scratch, ToRegister(right_op), Operand(0x1F));
switch (instr->op()) {
case Token::SAR:
- __ mov(result, Operand(result, ASR, scratch));
+ __ mov(result, Operand(left, ASR, scratch));
break;
case Token::SHR:
if (instr->can_deopt()) {
- __ mov(result, Operand(result, LSR, scratch), SetCC);
+ __ mov(result, Operand(left, LSR, scratch), SetCC);
DeoptimizeIf(mi, instr->environment());
} else {
- __ mov(result, Operand(result, LSR, scratch));
+ __ mov(result, Operand(left, LSR, scratch));
}
break;
case Token::SHL:
- __ mov(result, Operand(result, LSL, scratch));
+ __ mov(result, Operand(left, LSL, scratch));
break;
default:
UNREACHABLE();
break;
}
} else {
- int value = ToInteger32(LConstantOperand::cast(right));
+ // Mask the right_op operand.
+ int value = ToInteger32(LConstantOperand::cast(right_op));
uint8_t shift_count = static_cast<uint8_t>(value & 0x1F);
switch (instr->op()) {
case Token::SAR:
if (shift_count != 0) {
- __ mov(result, Operand(result, ASR, shift_count));
+ __ mov(result, Operand(left, ASR, shift_count));
+ } else {
+ __ Move(result, left);
}
break;
case Token::SHR:
- if (shift_count == 0 && instr->can_deopt()) {
- __ tst(result, Operand(0x80000000));
- DeoptimizeIf(ne, instr->environment());
+ if (shift_count != 0) {
+ __ mov(result, Operand(left, LSR, shift_count));
} else {
- __ mov(result, Operand(result, LSR, shift_count));
+ if (instr->can_deopt()) {
+ __ tst(left, Operand(0x80000000));
+ DeoptimizeIf(ne, instr->environment());
+ }
+ __ Move(result, left);
}
break;
case Token::SHL:
if (shift_count != 0) {
- __ mov(result, Operand(result, LSL, shift_count));
+ __ mov(result, Operand(left, LSL, shift_count));
+ } else {
+ __ Move(result, left);
}
break;
default:
@@ -1311,16 +1317,16 @@
void LCodeGen::DoSubI(LSubI* instr) {
LOperand* left = instr->InputAt(0);
LOperand* right = instr->InputAt(1);
- ASSERT(left->Equals(instr->result()));
+ LOperand* result = instr->result();
bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
SBit set_cond = can_overflow ? SetCC : LeaveCC;
if (right->IsStackSlot() || right->IsArgument()) {
Register right_reg = EmitLoadRegister(right, ip);
- __ sub(ToRegister(left), ToRegister(left), Operand(right_reg),
set_cond);
+ __ sub(ToRegister(result), ToRegister(left), Operand(right_reg),
set_cond);
} else {
ASSERT(right->IsRegister() || right->IsConstantOperand());
- __ sub(ToRegister(left), ToRegister(left), ToOperand(right), set_cond);
+ __ sub(ToRegister(result), ToRegister(left), ToOperand(right),
set_cond);
}
if (can_overflow) {
@@ -1339,7 +1345,7 @@
ASSERT(instr->result()->IsDoubleRegister());
DwVfpRegister result = ToDoubleRegister(instr->result());
double v = instr->value();
- __ vmov(result, v);
+ __ Vmov(result, v);
}
@@ -1388,14 +1394,16 @@
Register input = ToRegister(instr->InputAt(0));
Register result = ToRegister(instr->result());
Register map = ToRegister(instr->TempAt(0));
- ASSERT(input.is(result));
Label done;
// If the object is a smi return the object.
- __ JumpIfSmi(input, &done);
+ __ tst(input, Operand(kSmiTagMask));
+ __ Move(result, input, eq);
+ __ b(eq, &done);
// If the object is not a value type, return the object.
__ CompareObjectType(input, map, map, JS_VALUE_TYPE);
+ __ Move(result, input, ne);
__ b(ne, &done);
__ ldr(result, FieldMemOperand(input, JSValue::kValueOffset));
@@ -1404,9 +1412,9 @@
void LCodeGen::DoBitNotI(LBitNotI* instr) {
- LOperand* input = instr->InputAt(0);
- ASSERT(input->Equals(instr->result()));
- __ mvn(ToRegister(input), Operand(ToRegister(input)));
+ Register input = ToRegister(instr->InputAt(0));
+ Register result = ToRegister(instr->result());
+ __ mvn(result, Operand(input));
}
@@ -1424,16 +1432,16 @@
void LCodeGen::DoAddI(LAddI* instr) {
LOperand* left = instr->InputAt(0);
LOperand* right = instr->InputAt(1);
- ASSERT(left->Equals(instr->result()));
+ LOperand* result = instr->result();
bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
SBit set_cond = can_overflow ? SetCC : LeaveCC;
if (right->IsStackSlot() || right->IsArgument()) {
Register right_reg = EmitLoadRegister(right, ip);
- __ add(ToRegister(left), ToRegister(left), Operand(right_reg),
set_cond);
+ __ add(ToRegister(result), ToRegister(left), Operand(right_reg),
set_cond);
} else {
ASSERT(right->IsRegister() || right->IsConstantOperand());
- __ add(ToRegister(left), ToRegister(left), ToOperand(right), set_cond);
+ __ add(ToRegister(result), ToRegister(left), ToOperand(right),
set_cond);
}
if (can_overflow) {
@@ -1445,18 +1453,19 @@
void LCodeGen::DoArithmeticD(LArithmeticD* instr) {
DoubleRegister left = ToDoubleRegister(instr->InputAt(0));
DoubleRegister right = ToDoubleRegister(instr->InputAt(1));
+ DoubleRegister result = ToDoubleRegister(instr->result());
switch (instr->op()) {
case Token::ADD:
- __ vadd(left, left, right);
+ __ vadd(result, left, right);
break;
case Token::SUB:
- __ vsub(left, left, right);
+ __ vsub(result, left, right);
break;
case Token::MUL:
- __ vmul(left, left, right);
+ __ vmul(result, left, right);
break;
case Token::DIV:
- __ vdiv(left, left, right);
+ __ vdiv(result, left, right);
break;
case Token::MOD: {
// Save r0-r3 on the stack.
@@ -1468,7 +1477,7 @@
ExternalReference::double_fp_operation(Token::MOD, isolate()),
0, 2);
// Move the result in the double result register.
- __ GetCFunctionDoubleResult(ToDoubleRegister(instr->result()));
+ __ GetCFunctionDoubleResult(result);
// Restore r0-r3.
__ ldm(ia_w, sp, r0.bit() | r1.bit() | r2.bit() | r3.bit());
@@ -1561,7 +1570,7 @@
// Test double values. Zero and NaN are false.
Label call_stub;
- DoubleRegister dbl_scratch = d0;
+ DoubleRegister dbl_scratch = double_scratch0();
Register scratch = scratch0();
__ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset));
__ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
@@ -2578,7 +2587,6 @@
Register key = EmitLoadRegister(instr->key(), scratch0());
Register result = ToRegister(instr->result());
Register scratch = scratch0();
- ASSERT(result.is(elements));
// Load the result.
__ add(scratch, elements, Operand(key, LSL, kPointerSizeLog2));
@@ -2898,8 +2906,8 @@
void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation*
instr) {
- ASSERT(instr->InputAt(0)->Equals(instr->result()));
Register input = ToRegister(instr->InputAt(0));
+ Register result = ToRegister(instr->result());
Register scratch = scratch0();
// Deoptimize if not a heap number.
@@ -2913,10 +2921,10 @@
scratch = no_reg;
__ ldr(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset));
// Check the sign of the argument. If the argument is positive, just
- // return it. We do not need to patch the stack since |input| and
- // |result| are the same register and |input| would be restored
- // unchanged by popping safepoint registers.
+ // return it.
__ tst(exponent, Operand(HeapNumber::kSignMask));
+ // Move the input to the result if necessary.
+ __ Move(result, input);
__ b(eq, &done);
// Input is negative. Reverse its sign.
@@ -2956,7 +2964,7 @@
__ ldr(tmp2, FieldMemOperand(input, HeapNumber::kMantissaOffset));
__ str(tmp2, FieldMemOperand(tmp1, HeapNumber::kMantissaOffset));
- __ StoreToSafepointRegisterSlot(tmp1, input);
+ __ StoreToSafepointRegisterSlot(tmp1, result);
}
__ bind(&done);
@@ -2965,11 +2973,13 @@
void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) {
Register input = ToRegister(instr->InputAt(0));
+ Register result = ToRegister(instr->result());
__ cmp(input, Operand(0));
+ __ Move(result, input, pl);
// We can make rsb conditional because the previous cmp instruction
// will clear the V (overflow) flag and rsb won't set this flag
// if input is positive.
- __ rsb(input, input, Operand(0), SetCC, mi);
+ __ rsb(result, input, Operand(0), SetCC, mi);
// Deoptimize on overflow.
DeoptimizeIf(vs, instr->environment());
}
@@ -2989,11 +2999,11 @@
LUnaryMathOperation* instr_;
};
- ASSERT(instr->InputAt(0)->Equals(instr->result()));
Representation r = instr->hydrogen()->value()->representation();
if (r.IsDouble()) {
DwVfpRegister input = ToDoubleRegister(instr->InputAt(0));
- __ vabs(input, input);
+ DwVfpRegister result = ToDoubleRegister(instr->result());
+ __ vabs(result, input);
} else if (r.IsInteger32()) {
EmitIntegerMathAbs(instr);
} else {
@@ -3071,7 +3081,7 @@
// Save the original sign for later comparison.
__ and_(scratch2, scratch1, Operand(HeapNumber::kSignMask));
- __ vmov(double_scratch0(), 0.5);
+ __ Vmov(double_scratch0(), 0.5);
__ vadd(input, input, double_scratch0());
// Check sign of the result: if the sign changed, the input
@@ -3108,24 +3118,17 @@
void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) {
DoubleRegister input = ToDoubleRegister(instr->InputAt(0));
- ASSERT(ToDoubleRegister(instr->result()).is(input));
- __ vsqrt(input, input);
+ DoubleRegister result = ToDoubleRegister(instr->result());
+ __ vsqrt(result, input);
}
void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) {
DoubleRegister input = ToDoubleRegister(instr->InputAt(0));
- Register scratch = scratch0();
- SwVfpRegister single_scratch = double_scratch0().low();
- DoubleRegister double_scratch = double_scratch0();
- ASSERT(ToDoubleRegister(instr->result()).is(input));
-
+ DoubleRegister result = ToDoubleRegister(instr->result());
// Add +0 to convert -0 to +0.
- __ mov(scratch, Operand(0));
- __ vmov(single_scratch, scratch);
- __ vcvt_f64_s32(double_scratch, single_scratch);
- __ vadd(input, input, double_scratch);
- __ vsqrt(input, input);
+ __ vadd(result, input, kDoubleRegZero);
+ __ vsqrt(result, result);
}
@@ -3724,8 +3727,8 @@
void LCodeGen::DoDeferredNumberTagI(LNumberTagI* instr) {
Label slow;
Register reg = ToRegister(instr->InputAt(0));
- DoubleRegister dbl_scratch = d0;
- SwVfpRegister flt_scratch = s0;
+ DoubleRegister dbl_scratch = double_scratch0();
+ SwVfpRegister flt_scratch = dbl_scratch.low();
// Preserve the value of all registers.
PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
@@ -3834,8 +3837,8 @@
bool deoptimize_on_undefined,
LEnvironment* env) {
Register scratch = scratch0();
- SwVfpRegister flt_scratch = s0;
- ASSERT(!result_reg.is(d0));
+ SwVfpRegister flt_scratch = double_scratch0().low();
+ ASSERT(!result_reg.is(double_scratch0()));
Label load_smi, heap_number, done;
=======================================
--- /branches/bleeding_edge/src/arm/lithium-codegen-arm.h Tue Jun 28
07:21:55 2011
+++ /branches/bleeding_edge/src/arm/lithium-codegen-arm.h Wed Jun 29
03:51:06 2011
@@ -148,7 +148,7 @@
HGraph* graph() const { return chunk_->graph(); }
Register scratch0() { return r9; }
- DwVfpRegister double_scratch0() { return d0; }
+ DwVfpRegister double_scratch0() { return d15; }
int GetNextEmittedBlock(int block);
LInstruction* GetNextInstruction();
=======================================
--- /branches/bleeding_edge/src/arm/macro-assembler-arm.cc Tue Jun 28
08:22:08 2011
+++ /branches/bleeding_edge/src/arm/macro-assembler-arm.cc Wed Jun 29
03:51:06 2011
@@ -309,9 +309,9 @@
}
-void MacroAssembler::Move(Register dst, Register src) {
+void MacroAssembler::Move(Register dst, Register src, Condition cond) {
if (!dst.is(src)) {
- mov(dst, src);
+ mov(dst, src, LeaveCC, cond);
}
}
@@ -755,6 +755,23 @@
vmrs(fpscr_flags, cond);
}
+void MacroAssembler::Vmov(const DwVfpRegister dst,
+ const double imm,
+ const Condition cond) {
+ ASSERT(CpuFeatures::IsEnabled(VFP3));
+ static const DoubleRepresentation minus_zero(-0.0);
+ static const DoubleRepresentation zero(0.0);
+ DoubleRepresentation value(imm);
+ // Handle special values first.
+ if (value.bits == zero.bits) {
+ vmov(dst, kDoubleRegZero, cond);
+ } else if (value.bits == minus_zero.bits) {
+ vneg(dst, kDoubleRegZero, cond);
+ } else {
+ vmov(dst, imm, cond);
+ }
+}
+
void MacroAssembler::EnterFrame(StackFrame::Type type) {
// r0-r3: preserved
@@ -3101,7 +3118,7 @@
Label done;
Label in_bounds;
- vmov(temp_double_reg, 0.0);
+ Vmov(temp_double_reg, 0.0);
VFPCompareAndSetFlags(input_reg, temp_double_reg);
b(gt, &above_zero);
@@ -3111,7 +3128,7 @@
// Double value is >= 255, return 255.
bind(&above_zero);
- vmov(temp_double_reg, 255.0);
+ Vmov(temp_double_reg, 255.0);
VFPCompareAndSetFlags(input_reg, temp_double_reg);
b(le, &in_bounds);
mov(result_reg, Operand(255));
@@ -3119,7 +3136,7 @@
// In 0-255 range, round and truncate.
bind(&in_bounds);
- vmov(temp_double_reg, 0.5);
+ Vmov(temp_double_reg, 0.5);
vadd(temp_double_reg, input_reg, temp_double_reg);
vcvt_u32_f64(s0, temp_double_reg);
vmov(result_reg, s0);
=======================================
--- /branches/bleeding_edge/src/arm/macro-assembler-arm.h Thu Jun 23
05:03:16 2011
+++ /branches/bleeding_edge/src/arm/macro-assembler-arm.h Wed Jun 29
03:51:06 2011
@@ -143,7 +143,7 @@
// Register move. May do nothing if the registers are identical.
void Move(Register dst, Handle<Object> value);
- void Move(Register dst, Register src);
+ void Move(Register dst, Register src, Condition cond = al);
void Move(DoubleRegister dst, DoubleRegister src);
// Load an object from the root table.
@@ -312,6 +312,10 @@
const Register fpscr_flags,
const Condition cond = al);
+ void Vmov(const DwVfpRegister dst,
+ const double imm,
+ const Condition cond = al);
+
//
---------------------------------------------------------------------------
// Activation frames
=======================================
--- /branches/bleeding_edge/test/mjsunit/div-mod.js Tue Dec 7 03:01:02 2010
+++ /branches/bleeding_edge/test/mjsunit/div-mod.js Wed Jun 29 03:51:06 2011
@@ -25,6 +25,8 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// Flags: --allow-natives-syntax
+
// Test fast div and mod.
function divmod(div_func, mod_func, x, y) {
@@ -190,3 +192,113 @@
}
negative_zero_modulus_test();
+
+
+function lithium_integer_mod() {
+ var left_operands = [
+ 0,
+ 305419896, // 0x12345678
+ ];
+
+ // Test the standard lithium code for modulo opeartions.
+ var mod_func;
+ for (var i = 0; i < left_operands.length; i++) {
+ for (var j = 0; j < divisors.length; j++) {
+ mod_func = this.eval("(function(left) { return left % " +
divisors[j]+ "; })");
+ assertEquals((mod_func)(left_operands[i]), left_operands[i] %
divisors[j]);
+ assertEquals((mod_func)(-left_operands[i]), -left_operands[i] %
divisors[j]);
+ }
+ }
+
+ var results_powers_of_two = [
+ // 0
+ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0],
+ // 305419896 == 0x12345678
+ [0, 0, 0, 8, 24, 56, 120, 120, 120, 632, 1656, 1656, 5752, 5752,
22136, 22136, 22136, 22136, 284280, 284280, 1332856, 3430008, 3430008,
3430008, 3430008, 36984440, 36984440, 36984440, 305419896, 305419896,
305419896],
+ ];
+
+ // Test the lithium code for modulo operations with a variable power of
two
+ // right hand side operand.
+ for (var i = 0; i < left_operands.length; i++) {
+ for (var j = 0; j < 31; j++) {
+ assertEquals(results_powers_of_two[i][j], left_operands[i] % (2 <<
j));
+ assertEquals(results_powers_of_two[i][j], left_operands[i] % -(2 <<
j));
+ assertEquals(-results_powers_of_two[i][j], -left_operands[i] % (2 <<
j));
+ assertEquals(-results_powers_of_two[i][j], -left_operands[i] % -(2
<< j));
+ }
+ }
+
+ // Test the lithium code for modulo operations with a constant power of
two
+ // right hand side operand.
+ for (var i = 0; i < left_operands.length; i++) {
+ // With positive left hand side operand.
+ assertEquals(results_powers_of_two[i][0], left_operands[i] % -(2 <<
0));
+ assertEquals(results_powers_of_two[i][1], left_operands[i] % (2 << 1));
+ assertEquals(results_powers_of_two[i][2], left_operands[i] % -(2 <<
2));
+ assertEquals(results_powers_of_two[i][3], left_operands[i] % (2 << 3));
+ assertEquals(results_powers_of_two[i][4], left_operands[i] % -(2 <<
4));
+ assertEquals(results_powers_of_two[i][5], left_operands[i] % (2 << 5));
+ assertEquals(results_powers_of_two[i][6], left_operands[i] % -(2 <<
6));
+ assertEquals(results_powers_of_two[i][7], left_operands[i] % (2 << 7));
+ assertEquals(results_powers_of_two[i][8], left_operands[i] % -(2 <<
8));
+ assertEquals(results_powers_of_two[i][9], left_operands[i] % (2 << 9));
+ assertEquals(results_powers_of_two[i][10], left_operands[i] % -(2 <<
10));
+ assertEquals(results_powers_of_two[i][11], left_operands[i] % (2 <<
11));
+ assertEquals(results_powers_of_two[i][12], left_operands[i] % -(2 <<
12));
+ assertEquals(results_powers_of_two[i][13], left_operands[i] % (2 <<
13));
+ assertEquals(results_powers_of_two[i][14], left_operands[i] % -(2 <<
14));
+ assertEquals(results_powers_of_two[i][15], left_operands[i] % (2 <<
15));
+ assertEquals(results_powers_of_two[i][16], left_operands[i] % -(2 <<
16));
+ assertEquals(results_powers_of_two[i][17], left_operands[i] % (2 <<
17));
+ assertEquals(results_powers_of_two[i][18], left_operands[i] % -(2 <<
18));
+ assertEquals(results_powers_of_two[i][19], left_operands[i] % (2 <<
19));
+ assertEquals(results_powers_of_two[i][20], left_operands[i] % -(2 <<
20));
+ assertEquals(results_powers_of_two[i][21], left_operands[i] % (2 <<
21));
+ assertEquals(results_powers_of_two[i][22], left_operands[i] % -(2 <<
22));
+ assertEquals(results_powers_of_two[i][23], left_operands[i] % (2 <<
23));
+ assertEquals(results_powers_of_two[i][24], left_operands[i] % -(2 <<
24));
+ assertEquals(results_powers_of_two[i][25], left_operands[i] % (2 <<
25));
+ assertEquals(results_powers_of_two[i][26], left_operands[i] % -(2 <<
26));
+ assertEquals(results_powers_of_two[i][27], left_operands[i] % (2 <<
27));
+ assertEquals(results_powers_of_two[i][28], left_operands[i] % -(2 <<
28));
+ assertEquals(results_powers_of_two[i][29], left_operands[i] % (2 <<
29));
+ assertEquals(results_powers_of_two[i][30], left_operands[i] % -(2 <<
30));
+ // With negative left hand side operand.
+ assertEquals(-results_powers_of_two[i][0], -left_operands[i] % -(2 <<
0));
+ assertEquals(-results_powers_of_two[i][1], -left_operands[i] % (2 <<
1));
+ assertEquals(-results_powers_of_two[i][2], -left_operands[i] % -(2 <<
2));
+ assertEquals(-results_powers_of_two[i][3], -left_operands[i] % (2 <<
3));
+ assertEquals(-results_powers_of_two[i][4], -left_operands[i] % -(2 <<
4));
+ assertEquals(-results_powers_of_two[i][5], -left_operands[i] % (2 <<
5));
+ assertEquals(-results_powers_of_two[i][6], -left_operands[i] % -(2 <<
6));
+ assertEquals(-results_powers_of_two[i][7], -left_operands[i] % (2 <<
7));
+ assertEquals(-results_powers_of_two[i][8], -left_operands[i] % -(2 <<
8));
+ assertEquals(-results_powers_of_two[i][9], -left_operands[i] % (2 <<
9));
+ assertEquals(-results_powers_of_two[i][10], -left_operands[i] % -(2 <<
10));
+ assertEquals(-results_powers_of_two[i][11], -left_operands[i] % (2 <<
11));
+ assertEquals(-results_powers_of_two[i][12], -left_operands[i] % -(2 <<
12));
+ assertEquals(-results_powers_of_two[i][13], -left_operands[i] % (2 <<
13));
+ assertEquals(-results_powers_of_two[i][14], -left_operands[i] % -(2 <<
14));
+ assertEquals(-results_powers_of_two[i][15], -left_operands[i] % (2 <<
15));
+ assertEquals(-results_powers_of_two[i][16], -left_operands[i] % -(2 <<
16));
+ assertEquals(-results_powers_of_two[i][17], -left_operands[i] % (2 <<
17));
+ assertEquals(-results_powers_of_two[i][18], -left_operands[i] % -(2 <<
18));
+ assertEquals(-results_powers_of_two[i][19], -left_operands[i] % (2 <<
19));
+ assertEquals(-results_powers_of_two[i][20], -left_operands[i] % -(2 <<
20));
+ assertEquals(-results_powers_of_two[i][21], -left_operands[i] % (2 <<
21));
+ assertEquals(-results_powers_of_two[i][22], -left_operands[i] % -(2 <<
22));
+ assertEquals(-results_powers_of_two[i][23], -left_operands[i] % (2 <<
23));
+ assertEquals(-results_powers_of_two[i][24], -left_operands[i] % -(2 <<
24));
+ assertEquals(-results_powers_of_two[i][25], -left_operands[i] % (2 <<
25));
+ assertEquals(-results_powers_of_two[i][26], -left_operands[i] % -(2 <<
26));
+ assertEquals(-results_powers_of_two[i][27], -left_operands[i] % (2 <<
27));
+ assertEquals(-results_powers_of_two[i][28], -left_operands[i] % -(2 <<
28));
+ assertEquals(-results_powers_of_two[i][29], -left_operands[i] % (2 <<
29));
+ assertEquals(-results_powers_of_two[i][30], -left_operands[i] % -(2 <<
30));
+ }
+
+}
+
+lithium_integer_mod();
+%OptimizeFunctionOnNextCall(lithium_integer_mod)
+lithium_integer_mod();
--
v8-dev mailing list
v8-dev@googlegroups.com
http://groups.google.com/group/v8-dev