Index: src/arm/lithium-codegen-arm.cc |
=================================================================== |
--- src/arm/lithium-codegen-arm.cc (revision 8362) |
+++ src/arm/lithium-codegen-arm.cc (working copy) |
@@ -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_(dividend, 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, dividend, 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)); |
@@ -925,6 +922,8 @@ |
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)); |
__ b(eq, &done); |
@@ -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); |
+ 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->IsStackSlot() || right->IsArgument()) { |
- Register right_reg = EmitLoadRegister(right, ip); |
- right_operand = Operand(right_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); |
@@ -2607,7 +2616,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)); |
@@ -2927,8 +2935,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. |
@@ -2942,10 +2950,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. |
@@ -2985,7 +2993,7 @@ |
__ ldr(tmp2, FieldMemOperand(input, HeapNumber::kMantissaOffset)); |
__ str(tmp2, FieldMemOperand(tmp1, HeapNumber::kMantissaOffset)); |
- __ StoreToSafepointRegisterSlot(tmp1, input); |
+ __ StoreToSafepointRegisterSlot(tmp1, result); |
} |
__ bind(&done); |
@@ -2994,11 +3002,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()); |
} |
@@ -3018,11 +3028,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 { |
@@ -3100,7 +3110,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 |
@@ -3137,24 +3147,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); |
} |
@@ -3753,8 +3756,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); |
@@ -3863,8 +3866,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; |