Index: src/arm/lithium-codegen-arm.cc |
diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc |
index 434090fcdeeb2dff3fb5d3b35e166976361ada66..46e0754ddd0cd28f9f4274397f3f12af619f72ac 100644 |
--- a/src/arm/lithium-codegen-arm.cc |
+++ b/src/arm/lithium-codegen-arm.cc |
@@ -873,7 +873,6 @@ void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { |
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(); |
@@ -883,15 +882,17 @@ void LCodeGen::DoModI(LModI* instr) { |
Label positive_dividend, done; |
__ cmp(dividend, Operand(0)); |
__ b(pl, &positive_dividend); |
- __ rsb(result, dividend, Operand(0)); |
- __ and_(dividend, result, Operand(divisor - 1), SetCC); |
+ __ rsb(dividend, dividend, Operand(0)); |
+ __ and_(dividend, dividend, Operand(divisor - 1)); |
+ __ rsb(dividend, dividend, Operand(0), SetCC); |
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
- DeoptimizeIf(eq, instr->environment()); |
+ __ b(ne, &done); |
+ DeoptimizeIf(al, instr->environment()); |
+ } else { |
+ __ b(&done); |
} |
- __ rsb(result, dividend, Operand(0)); |
- __ b(&done); |
__ bind(&positive_dividend); |
- __ and_(result, dividend, Operand(divisor - 1)); |
+ __ and_(dividend, dividend, Operand(divisor - 1)); |
__ bind(&done); |
return; |
} |
@@ -907,6 +908,8 @@ void LCodeGen::DoModI(LModI* instr) { |
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)); |
@@ -922,8 +925,6 @@ void LCodeGen::DoModI(LModI* instr) { |
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); |
@@ -1119,9 +1120,9 @@ void LCodeGen::DoDeferredBinaryOpStub(LTemplateInstruction<1, 2, T>* instr, |
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); |
@@ -1154,7 +1155,7 @@ void LCodeGen::DoMulI(LMulI* instr) { |
__ mov(result, Operand(0)); |
break; |
case 1: |
- __ Move(result, left); |
+ // Nothing to do. |
break; |
default: |
// Multiplying by powers of two and powers of two plus or minus |
@@ -1216,29 +1217,30 @@ void LCodeGen::DoMulI(LMulI* instr) { |
void LCodeGen::DoBitI(LBitI* instr) { |
- 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); |
+ 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_op->IsStackSlot() || right_op->IsArgument()) { |
- right = Operand(EmitLoadRegister(right_op, ip)); |
+ if (right->IsStackSlot() || right->IsArgument()) { |
+ Register right_reg = EmitLoadRegister(right, ip); |
+ right_operand = Operand(right_reg); |
} else { |
- ASSERT(right_op->IsRegister() || right_op->IsConstantOperand()); |
- right = ToOperand(right_op); |
+ ASSERT(right->IsRegister() || right->IsConstantOperand()); |
+ right_operand = ToOperand(right); |
} |
switch (instr->op()) { |
case Token::BIT_AND: |
- __ and_(result, left, right); |
+ __ and_(result, ToRegister(left), right_operand); |
break; |
case Token::BIT_OR: |
- __ orr(result, left, right); |
+ __ orr(result, ToRegister(left), right_operand); |
break; |
case Token::BIT_XOR: |
- __ eor(result, left, right); |
+ __ eor(result, ToRegister(left), right_operand); |
break; |
default: |
UNREACHABLE(); |
@@ -1248,62 +1250,54 @@ void LCodeGen::DoBitI(LBitI* instr) { |
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(); |
- if (right_op->IsRegister()) { |
- // Mask the right_op operand. |
- __ and_(scratch, ToRegister(right_op), Operand(0x1F)); |
+ 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)); |
switch (instr->op()) { |
case Token::SAR: |
- __ mov(result, Operand(left, ASR, scratch)); |
+ __ mov(result, Operand(result, ASR, scratch)); |
break; |
case Token::SHR: |
if (instr->can_deopt()) { |
- __ mov(result, Operand(left, LSR, scratch), SetCC); |
+ __ mov(result, Operand(result, LSR, scratch), SetCC); |
DeoptimizeIf(mi, instr->environment()); |
} else { |
- __ mov(result, Operand(left, LSR, scratch)); |
+ __ mov(result, Operand(result, LSR, scratch)); |
} |
break; |
case Token::SHL: |
- __ mov(result, Operand(left, LSL, scratch)); |
+ __ mov(result, Operand(result, LSL, scratch)); |
break; |
default: |
UNREACHABLE(); |
break; |
} |
} else { |
- // Mask the right_op operand. |
- int value = ToInteger32(LConstantOperand::cast(right_op)); |
+ int value = ToInteger32(LConstantOperand::cast(right)); |
uint8_t shift_count = static_cast<uint8_t>(value & 0x1F); |
switch (instr->op()) { |
case Token::SAR: |
if (shift_count != 0) { |
- __ mov(result, Operand(left, ASR, shift_count)); |
- } else { |
- __ Move(result, left); |
+ __ mov(result, Operand(result, ASR, shift_count)); |
} |
break; |
case Token::SHR: |
- if (shift_count != 0) { |
- __ mov(result, Operand(left, LSR, shift_count)); |
+ if (shift_count == 0 && instr->can_deopt()) { |
+ __ tst(result, Operand(0x80000000)); |
+ DeoptimizeIf(ne, instr->environment()); |
} else { |
- if (instr->can_deopt()) { |
- __ tst(left, Operand(0x80000000)); |
- DeoptimizeIf(ne, instr->environment()); |
- } |
- __ Move(result, left); |
+ __ mov(result, Operand(result, LSR, shift_count)); |
} |
break; |
case Token::SHL: |
if (shift_count != 0) { |
- __ mov(result, Operand(left, LSL, shift_count)); |
- } else { |
- __ Move(result, left); |
+ __ mov(result, Operand(result, LSL, shift_count)); |
} |
break; |
default: |
@@ -1317,16 +1311,16 @@ void LCodeGen::DoShiftI(LShiftI* instr) { |
void LCodeGen::DoSubI(LSubI* instr) { |
LOperand* left = instr->InputAt(0); |
LOperand* right = instr->InputAt(1); |
- LOperand* result = instr->result(); |
+ ASSERT(left->Equals(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(result), ToRegister(left), Operand(right_reg), set_cond); |
+ __ sub(ToRegister(left), ToRegister(left), Operand(right_reg), set_cond); |
} else { |
ASSERT(right->IsRegister() || right->IsConstantOperand()); |
- __ sub(ToRegister(result), ToRegister(left), ToOperand(right), set_cond); |
+ __ sub(ToRegister(left), ToRegister(left), ToOperand(right), set_cond); |
} |
if (can_overflow) { |
@@ -1345,7 +1339,7 @@ void LCodeGen::DoConstantD(LConstantD* instr) { |
ASSERT(instr->result()->IsDoubleRegister()); |
DwVfpRegister result = ToDoubleRegister(instr->result()); |
double v = instr->value(); |
- __ Vmov(result, v); |
+ __ vmov(result, v); |
} |
@@ -1394,16 +1388,14 @@ void LCodeGen::DoValueOf(LValueOf* instr) { |
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. |
- __ tst(input, Operand(kSmiTagMask)); |
- __ Move(result, input, eq); |
- __ b(eq, &done); |
+ __ JumpIfSmi(input, &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)); |
@@ -1412,9 +1404,9 @@ void LCodeGen::DoValueOf(LValueOf* instr) { |
void LCodeGen::DoBitNotI(LBitNotI* instr) { |
- Register input = ToRegister(instr->InputAt(0)); |
- Register result = ToRegister(instr->result()); |
- __ mvn(result, Operand(input)); |
+ LOperand* input = instr->InputAt(0); |
+ ASSERT(input->Equals(instr->result())); |
+ __ mvn(ToRegister(input), Operand(ToRegister(input))); |
} |
@@ -1432,16 +1424,16 @@ void LCodeGen::DoThrow(LThrow* instr) { |
void LCodeGen::DoAddI(LAddI* instr) { |
LOperand* left = instr->InputAt(0); |
LOperand* right = instr->InputAt(1); |
- LOperand* result = instr->result(); |
+ ASSERT(left->Equals(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(result), ToRegister(left), Operand(right_reg), set_cond); |
+ __ add(ToRegister(left), ToRegister(left), Operand(right_reg), set_cond); |
} else { |
ASSERT(right->IsRegister() || right->IsConstantOperand()); |
- __ add(ToRegister(result), ToRegister(left), ToOperand(right), set_cond); |
+ __ add(ToRegister(left), ToRegister(left), ToOperand(right), set_cond); |
} |
if (can_overflow) { |
@@ -1453,19 +1445,18 @@ void LCodeGen::DoAddI(LAddI* instr) { |
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(result, left, right); |
+ __ vadd(left, left, right); |
break; |
case Token::SUB: |
- __ vsub(result, left, right); |
+ __ vsub(left, left, right); |
break; |
case Token::MUL: |
- __ vmul(result, left, right); |
+ __ vmul(left, left, right); |
break; |
case Token::DIV: |
- __ vdiv(result, left, right); |
+ __ vdiv(left, left, right); |
break; |
case Token::MOD: { |
// Save r0-r3 on the stack. |
@@ -1477,7 +1468,7 @@ void LCodeGen::DoArithmeticD(LArithmeticD* instr) { |
ExternalReference::double_fp_operation(Token::MOD, isolate()), |
0, 2); |
// Move the result in the double result register. |
- __ GetCFunctionDoubleResult(result); |
+ __ GetCFunctionDoubleResult(ToDoubleRegister(instr->result())); |
// Restore r0-r3. |
__ ldm(ia_w, sp, r0.bit() | r1.bit() | r2.bit() | r3.bit()); |
@@ -1570,7 +1561,7 @@ void LCodeGen::DoBranch(LBranch* instr) { |
// Test double values. Zero and NaN are false. |
Label call_stub; |
- DoubleRegister dbl_scratch = double_scratch0(); |
+ DoubleRegister dbl_scratch = d0; |
Register scratch = scratch0(); |
__ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset)); |
__ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); |
@@ -2616,6 +2607,7 @@ void LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) { |
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)); |
@@ -2935,8 +2927,8 @@ void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { |
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. |
@@ -2950,10 +2942,10 @@ void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) { |
scratch = no_reg; |
__ ldr(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset)); |
// Check the sign of the argument. If the argument is positive, just |
- // return it. |
+ // 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. |
__ 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. |
@@ -2993,7 +2985,7 @@ void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) { |
__ ldr(tmp2, FieldMemOperand(input, HeapNumber::kMantissaOffset)); |
__ str(tmp2, FieldMemOperand(tmp1, HeapNumber::kMantissaOffset)); |
- __ StoreToSafepointRegisterSlot(tmp1, result); |
+ __ StoreToSafepointRegisterSlot(tmp1, input); |
} |
__ bind(&done); |
@@ -3002,13 +2994,11 @@ void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) { |
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(result, input, Operand(0), SetCC, mi); |
+ __ rsb(input, input, Operand(0), SetCC, mi); |
// Deoptimize on overflow. |
DeoptimizeIf(vs, instr->environment()); |
} |
@@ -3028,11 +3018,11 @@ void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) { |
LUnaryMathOperation* instr_; |
}; |
+ ASSERT(instr->InputAt(0)->Equals(instr->result())); |
Representation r = instr->hydrogen()->value()->representation(); |
if (r.IsDouble()) { |
DwVfpRegister input = ToDoubleRegister(instr->InputAt(0)); |
- DwVfpRegister result = ToDoubleRegister(instr->result()); |
- __ vabs(result, input); |
+ __ vabs(input, input); |
} else if (r.IsInteger32()) { |
EmitIntegerMathAbs(instr); |
} else { |
@@ -3110,7 +3100,7 @@ void LCodeGen::DoMathRound(LUnaryMathOperation* instr) { |
// 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 |
@@ -3147,17 +3137,24 @@ void LCodeGen::DoMathRound(LUnaryMathOperation* instr) { |
void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) { |
DoubleRegister input = ToDoubleRegister(instr->InputAt(0)); |
- DoubleRegister result = ToDoubleRegister(instr->result()); |
- __ vsqrt(result, input); |
+ ASSERT(ToDoubleRegister(instr->result()).is(input)); |
+ __ vsqrt(input, input); |
} |
void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) { |
DoubleRegister input = ToDoubleRegister(instr->InputAt(0)); |
- DoubleRegister result = ToDoubleRegister(instr->result()); |
+ Register scratch = scratch0(); |
+ SwVfpRegister single_scratch = double_scratch0().low(); |
+ DoubleRegister double_scratch = double_scratch0(); |
+ ASSERT(ToDoubleRegister(instr->result()).is(input)); |
+ |
// Add +0 to convert -0 to +0. |
- __ vadd(result, input, kDoubleRegZero); |
- __ vsqrt(result, result); |
+ __ mov(scratch, Operand(0)); |
+ __ vmov(single_scratch, scratch); |
+ __ vcvt_f64_s32(double_scratch, single_scratch); |
+ __ vadd(input, input, double_scratch); |
+ __ vsqrt(input, input); |
} |
@@ -3756,8 +3753,8 @@ void LCodeGen::DoNumberTagI(LNumberTagI* instr) { |
void LCodeGen::DoDeferredNumberTagI(LNumberTagI* instr) { |
Label slow; |
Register reg = ToRegister(instr->InputAt(0)); |
- DoubleRegister dbl_scratch = double_scratch0(); |
- SwVfpRegister flt_scratch = dbl_scratch.low(); |
+ DoubleRegister dbl_scratch = d0; |
+ SwVfpRegister flt_scratch = s0; |
// Preserve the value of all registers. |
PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
@@ -3866,8 +3863,8 @@ void LCodeGen::EmitNumberUntagD(Register input_reg, |
bool deoptimize_on_undefined, |
LEnvironment* env) { |
Register scratch = scratch0(); |
- SwVfpRegister flt_scratch = double_scratch0().low(); |
- ASSERT(!result_reg.is(double_scratch0())); |
+ SwVfpRegister flt_scratch = s0; |
+ ASSERT(!result_reg.is(d0)); |
Label load_smi, heap_number, done; |