Commit 0e29b3d2 authored by palfia@homejinni.com's avatar palfia@homejinni.com

MIPS: Improve TruncateNumberToI implementation after DoubleToIStub usage (r16461).

Using TruncateHeapNumberToI here simplifies the code and we get rid of ConvertToInt32 and EmitOutOfInt32RangeTruncate macro assembler instructions.

BUG=

Review URL: https://codereview.chromium.org/23444033
Patch from Balazs Kilvady <kilvadyb@homejinni.com>.

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@16505 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent d9052d41
......@@ -567,10 +567,80 @@ void DoubleToIStub::Generate(MacroAssembler* masm) {
Register input_low = scratch3;
__ Move(input_low, input_high, double_input);
__ EmitOutOfInt32RangeTruncate(result_reg,
input_high,
input_low,
scratch);
Label normal_exponent, restore_sign;
// Extract the biased exponent in result.
__ Ext(result_reg,
input_high,
HeapNumber::kExponentShift,
HeapNumber::kExponentBits);
// Check for Infinity and NaNs, which should return 0.
__ Subu(scratch, result_reg, HeapNumber::kExponentMask);
__ Movz(result_reg, zero_reg, scratch);
__ Branch(&done, eq, scratch, Operand(zero_reg));
// Express exponent as delta to (number of mantissa bits + 31).
__ Subu(result_reg,
result_reg,
Operand(HeapNumber::kExponentBias + HeapNumber::kMantissaBits + 31));
// If the delta is strictly positive, all bits would be shifted away,
// which means that we can return 0.
__ Branch(&normal_exponent, le, result_reg, Operand(zero_reg));
__ mov(result_reg, zero_reg);
__ Branch(&done);
__ bind(&normal_exponent);
const int kShiftBase = HeapNumber::kNonMantissaBitsInTopWord - 1;
// Calculate shift.
__ Addu(scratch, result_reg, Operand(kShiftBase + HeapNumber::kMantissaBits));
// Save the sign.
Register sign = result_reg;
result_reg = no_reg;
__ And(sign, input_high, Operand(HeapNumber::kSignMask));
// On ARM shifts > 31 bits are valid and will result in zero. On MIPS we need
// to check for this specific case.
Label high_shift_needed, high_shift_done;
__ Branch(&high_shift_needed, lt, scratch, Operand(32));
__ mov(input_high, zero_reg);
__ Branch(&high_shift_done);
__ bind(&high_shift_needed);
// Set the implicit 1 before the mantissa part in input_high.
__ Or(input_high,
input_high,
Operand(1 << HeapNumber::kMantissaBitsInTopWord));
// Shift the mantissa bits to the correct position.
// We don't need to clear non-mantissa bits as they will be shifted away.
// If they weren't, it would mean that the answer is in the 32bit range.
__ sllv(input_high, input_high, scratch);
__ bind(&high_shift_done);
// Replace the shifted bits with bits from the lower mantissa word.
Label pos_shift, shift_done;
__ li(at, 32);
__ subu(scratch, at, scratch);
__ Branch(&pos_shift, ge, scratch, Operand(zero_reg));
// Negate scratch.
__ Subu(scratch, zero_reg, scratch);
__ sllv(input_low, input_low, scratch);
__ Branch(&shift_done);
__ bind(&pos_shift);
__ srlv(input_low, input_low, scratch);
__ bind(&shift_done);
__ Or(input_high, input_high, Operand(input_low));
// Restore sign if necessary.
__ mov(scratch, sign);
result_reg = sign;
sign = no_reg;
__ Subu(result_reg, zero_reg, input_high);
__ Movz(result_reg, input_high, scratch);
__ bind(&done);
......@@ -1486,7 +1556,6 @@ void BinaryOpStub_GenerateFPOperation(MacroAssembler* masm,
Register right = a0;
Register scratch1 = t3;
Register scratch2 = t5;
Register scratch3 = t0;
ASSERT(smi_operands || (not_numbers != NULL));
if (smi_operands) {
......@@ -1590,12 +1659,8 @@ void BinaryOpStub_GenerateFPOperation(MacroAssembler* masm,
__ SmiUntag(a2, right);
} else {
// Convert operands to 32-bit integers. Right in a2 and left in a3.
__ TruncateNumberToI(
left, a3, heap_number_map,
scratch1, scratch2, scratch3, not_numbers);
__ TruncateNumberToI(
right, a2, heap_number_map,
scratch1, scratch2, scratch3, not_numbers);
__ TruncateNumberToI(left, a3, heap_number_map, scratch1, not_numbers);
__ TruncateNumberToI(right, a2, heap_number_map, scratch1, not_numbers);
}
Label result_not_a_smi;
switch (op) {
......
......@@ -1298,60 +1298,6 @@ void MacroAssembler::Clz(Register rd, Register rs) {
}
// Tries to get a signed int32 out of a double precision floating point heap
// number. Rounds towards 0. Branch to 'not_int32' if the double is out of the
// 32bits signed integer range.
// This method implementation differs from the ARM version for performance
// reasons.
void MacroAssembler::ConvertToInt32(Register source,
Register dest,
Register scratch,
Register scratch2,
FPURegister double_scratch,
Label *not_int32) {
Label right_exponent, done;
// Get exponent word (ENDIAN issues).
lw(scratch, FieldMemOperand(source, HeapNumber::kExponentOffset));
// Get exponent alone in scratch2.
And(scratch2, scratch, Operand(HeapNumber::kExponentMask));
// Load dest with zero. We use this either for the final shift or
// for the answer.
mov(dest, zero_reg);
// Check whether the exponent matches a 32 bit signed int that is not a Smi.
// A non-Smi integer is 1.xxx * 2^30 so the exponent is 30 (biased). This is
// the exponent that we are fastest at and also the highest exponent we can
// handle here.
const uint32_t non_smi_exponent =
(HeapNumber::kExponentBias + 30) << HeapNumber::kExponentShift;
// If we have a match of the int32-but-not-Smi exponent then skip some logic.
Branch(&right_exponent, eq, scratch2, Operand(non_smi_exponent));
// If the exponent is higher than that then go to not_int32 case. This
// catches numbers that don't fit in a signed int32, infinities and NaNs.
Branch(not_int32, gt, scratch2, Operand(non_smi_exponent));
// We know the exponent is smaller than 30 (biased). If it is less than
// 0 (biased) then the number is smaller in magnitude than 1.0 * 2^0, i.e.
// it rounds to zero.
const uint32_t zero_exponent =
(HeapNumber::kExponentBias + 0) << HeapNumber::kExponentShift;
Subu(scratch2, scratch2, Operand(zero_exponent));
// Dest already has a Smi zero.
Branch(&done, lt, scratch2, Operand(zero_reg));
bind(&right_exponent);
// MIPS FPU instructions implementing double precision to integer
// conversion using round to zero. Since the FP value was qualified
// above, the resulting integer should be a legal int32.
// The original 'Exponent' word is still in scratch.
lwc1(double_scratch, FieldMemOperand(source, HeapNumber::kMantissaOffset));
mtc1(scratch, FPURegister::from_code(double_scratch.code() + 1));
trunc_w_d(double_scratch, double_scratch);
mfc1(dest, double_scratch);
bind(&done);
}
void MacroAssembler::EmitFPUTruncate(FPURoundingMode rounding_mode,
Register result,
DoubleRegister double_input,
......@@ -1416,88 +1362,6 @@ void MacroAssembler::EmitFPUTruncate(FPURoundingMode rounding_mode,
}
void MacroAssembler::EmitOutOfInt32RangeTruncate(Register result,
Register input_high,
Register input_low,
Register scratch) {
Label done, normal_exponent, restore_sign;
// Extract the biased exponent in result.
Ext(result,
input_high,
HeapNumber::kExponentShift,
HeapNumber::kExponentBits);
// Check for Infinity and NaNs, which should return 0.
Subu(scratch, result, HeapNumber::kExponentMask);
Movz(result, zero_reg, scratch);
Branch(&done, eq, scratch, Operand(zero_reg));
// Express exponent as delta to (number of mantissa bits + 31).
Subu(result,
result,
Operand(HeapNumber::kExponentBias + HeapNumber::kMantissaBits + 31));
// If the delta is strictly positive, all bits would be shifted away,
// which means that we can return 0.
Branch(&normal_exponent, le, result, Operand(zero_reg));
mov(result, zero_reg);
Branch(&done);
bind(&normal_exponent);
const int kShiftBase = HeapNumber::kNonMantissaBitsInTopWord - 1;
// Calculate shift.
Addu(scratch, result, Operand(kShiftBase + HeapNumber::kMantissaBits));
// Save the sign.
Register sign = result;
result = no_reg;
And(sign, input_high, Operand(HeapNumber::kSignMask));
// On ARM shifts > 31 bits are valid and will result in zero. On MIPS we need
// to check for this specific case.
Label high_shift_needed, high_shift_done;
Branch(&high_shift_needed, lt, scratch, Operand(32));
mov(input_high, zero_reg);
Branch(&high_shift_done);
bind(&high_shift_needed);
// Set the implicit 1 before the mantissa part in input_high.
Or(input_high,
input_high,
Operand(1 << HeapNumber::kMantissaBitsInTopWord));
// Shift the mantissa bits to the correct position.
// We don't need to clear non-mantissa bits as they will be shifted away.
// If they weren't, it would mean that the answer is in the 32bit range.
sllv(input_high, input_high, scratch);
bind(&high_shift_done);
// Replace the shifted bits with bits from the lower mantissa word.
Label pos_shift, shift_done;
li(at, 32);
subu(scratch, at, scratch);
Branch(&pos_shift, ge, scratch, Operand(zero_reg));
// Negate scratch.
Subu(scratch, zero_reg, scratch);
sllv(input_low, input_low, scratch);
Branch(&shift_done);
bind(&pos_shift);
srlv(input_low, input_low, scratch);
bind(&shift_done);
Or(input_high, input_high, Operand(input_low));
// Restore sign if necessary.
mov(scratch, sign);
result = sign;
sign = no_reg;
Subu(result, zero_reg, input_high);
Movz(result, input_high, scratch);
bind(&done);
}
void MacroAssembler::TryInlineTruncateDoubleToI(Register result,
DoubleRegister double_input,
Label* done) {
......@@ -1570,31 +1434,14 @@ void MacroAssembler::TruncateHeapNumberToI(Register result, Register object) {
void MacroAssembler::TruncateNumberToI(Register object,
Register result,
Register heap_number_map,
Register scratch1,
Register scratch2,
Register scratch3,
Register scratch,
Label* not_number) {
Label done;
Label not_in_int32_range;
DoubleRegister double_scratch = f12;
ASSERT(!result.is(object));
UntagAndJumpIfSmi(result, object, &done);
JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_number);
ConvertToInt32(object,
result,
scratch1,
scratch2,
double_scratch,
&not_in_int32_range);
jmp(&done);
bind(&not_in_int32_range);
lw(scratch1, FieldMemOperand(object, HeapNumber::kExponentOffset));
lw(scratch2, FieldMemOperand(object, HeapNumber::kMantissaOffset));
EmitOutOfInt32RangeTruncate(result,
scratch1,
scratch2,
scratch3);
JumpIfNotHeapNumber(object, heap_number_map, scratch, not_number);
TruncateHeapNumberToI(result, object);
bind(&done);
}
......
......@@ -758,17 +758,6 @@ class MacroAssembler: public Assembler {
BranchF(target, nan, cc, cmp1, cmp2, bd);
};
// Convert the HeapNumber pointed to by source to a 32bits signed integer
// dest. If the HeapNumber does not fit into a 32bits signed integer branch
// to not_int32 label. If FPU is available double_scratch is used but not
// scratch2.
void ConvertToInt32(Register source,
Register dest,
Register scratch,
Register scratch2,
FPURegister double_scratch,
Label *not_int32);
// Truncates a double using a specific rounding mode, and writes the value
// to the result register.
// The except_flag will contain any exceptions caused by the instruction.
......@@ -783,17 +772,6 @@ class MacroAssembler: public Assembler {
CheckForInexactConversion check_inexact
= kDontCheckForInexactConversion);
// Helper for EmitECMATruncate.
// This will truncate a floating-point value outside of the singed 32bit
// integer range to a 32bit signed integer.
// Expects the double value loaded in input_high and input_low.
// Exits with the answer in 'result'.
// Note that this code does not work for values in the 32bit range!
void EmitOutOfInt32RangeTruncate(Register result,
Register input_high,
Register input_low,
Register scratch);
// Performs a truncating conversion of a floating point number as used by
// the JS bitwise operations. See ECMA-262 9.5: ToInt32. Goes to 'done' if it
// succeeds, otherwise falls through if result is saturated. On return
......@@ -821,9 +799,7 @@ class MacroAssembler: public Assembler {
void TruncateNumberToI(Register object,
Register result,
Register heap_number_map,
Register scratch1,
Register scratch2,
Register scratch3,
Register scratch,
Label* not_int32);
// Loads the number from object into dst register.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment