Revision: 12676
Author: [email protected]
Date: Mon Oct 8 05:50:15 2012
Log: ARM: Fast path for integer inputs to EmitVFPTruncate
BUG=none
TEST=none
Review URL: https://codereview.chromium.org/11049025
Patch from Martyn Capewell <[email protected]>.
http://code.google.com/p/v8/source/detail?r=12676
Modified:
/branches/bleeding_edge/src/arm/code-stubs-arm.cc
/branches/bleeding_edge/src/arm/code-stubs-arm.h
/branches/bleeding_edge/src/arm/lithium-arm.cc
/branches/bleeding_edge/src/arm/lithium-codegen-arm.cc
/branches/bleeding_edge/src/arm/macro-assembler-arm.cc
/branches/bleeding_edge/src/arm/macro-assembler-arm.h
/branches/bleeding_edge/src/arm/stub-cache-arm.cc
=======================================
--- /branches/bleeding_edge/src/arm/code-stubs-arm.cc Thu Sep 27 04:31:26
2012
+++ /branches/bleeding_edge/src/arm/code-stubs-arm.cc Mon Oct 8 05:50:15
2012
@@ -826,6 +826,7 @@
Register object,
Destination destination,
DwVfpRegister double_dst,
+ DwVfpRegister
double_scratch,
Register dst1,
Register dst2,
Register heap_number_map,
@@ -863,10 +864,10 @@
__ vldr(double_dst, scratch1, HeapNumber::kValueOffset);
__ EmitVFPTruncate(kRoundToZero,
- single_scratch,
+ scratch1,
double_dst,
- scratch1,
scratch2,
+ double_scratch,
kCheckForInexactConversion);
// Jump to not_int32 if the operation did not succeed.
@@ -906,7 +907,8 @@
Register scratch1,
Register scratch2,
Register scratch3,
- DwVfpRegister double_scratch,
+ DwVfpRegister double_scratch0,
+ DwVfpRegister double_scratch1,
Label* not_int32) {
ASSERT(!dst.is(object));
ASSERT(!scratch1.is(object) && !scratch2.is(object)
&& !scratch3.is(object));
@@ -929,23 +931,20 @@
// Convert the floating point value to a 32-bit integer.
if (CpuFeatures::IsSupported(VFP2)) {
CpuFeatures::Scope scope(VFP2);
- SwVfpRegister single_scratch = double_scratch.low();
+
// Load the double value.
__ sub(scratch1, object, Operand(kHeapObjectTag));
- __ vldr(double_scratch, scratch1, HeapNumber::kValueOffset);
+ __ vldr(double_scratch0, scratch1, HeapNumber::kValueOffset);
__ EmitVFPTruncate(kRoundToZero,
- single_scratch,
- double_scratch,
+ dst,
+ double_scratch0,
scratch1,
- scratch2,
+ double_scratch1,
kCheckForInexactConversion);
// Jump to not_int32 if the operation did not succeed.
__ b(ne, not_int32);
- // Get the result in the destination register.
- __ vmov(dst, single_scratch);
-
} else {
// Load the double value in the destination registers.
__ ldr(scratch1, FieldMemOperand(object, HeapNumber::kExponentOffset));
@@ -2850,7 +2849,6 @@
Register scratch1 = r7;
Register scratch2 = r9;
DwVfpRegister double_scratch = d0;
- SwVfpRegister single_scratch = s3;
Register heap_number_result = no_reg;
Register heap_number_map = r6;
@@ -2888,6 +2886,7 @@
right,
destination,
d7,
+ d8,
r2,
r3,
heap_number_map,
@@ -2899,6 +2898,7 @@
left,
destination,
d6,
+ d8,
r4,
r5,
heap_number_map,
@@ -2934,10 +2934,10 @@
// transition.
__ EmitVFPTruncate(kRoundToZero,
- single_scratch,
+ scratch1,
d5,
- scratch1,
- scratch2);
+ scratch2,
+ d8);
if (result_type_ <= BinaryOpIC::INT32) {
// If the ne condition is set, result does
@@ -2946,7 +2946,6 @@
}
// Check if the result fits in a smi.
- __ vmov(scratch1, single_scratch);
__ add(scratch2, scratch1, Operand(0x40000000), SetCC);
// If not try to return a heap number.
__ b(mi, &return_heap_number);
@@ -3041,6 +3040,7 @@
scratch2,
scratch3,
d0,
+ d1,
&transition);
FloatingPointHelper::LoadNumberAsInt32(masm,
right,
@@ -3050,6 +3050,7 @@
scratch2,
scratch3,
d0,
+ d1,
&transition);
// The ECMA-262 standard specifies that, for shift operations, only
the
=======================================
--- /branches/bleeding_edge/src/arm/code-stubs-arm.h Wed Jul 25 08:26:16
2012
+++ /branches/bleeding_edge/src/arm/code-stubs-arm.h Mon Oct 8 05:50:15
2012
@@ -773,6 +773,7 @@
Register object,
Destination destination,
DwVfpRegister double_dst,
+ DwVfpRegister double_scratch,
Register dst1,
Register dst2,
Register heap_number_map,
@@ -794,7 +795,8 @@
Register scratch1,
Register scratch2,
Register scratch3,
- DwVfpRegister double_scratch,
+ DwVfpRegister double_scratch0,
+ DwVfpRegister double_scratch1,
Label* not_int32);
// Generate non VFP3 code to check if a double can be exactly
represented by a
=======================================
--- /branches/bleeding_edge/src/arm/lithium-arm.cc Wed Sep 19 01:13:46 2012
+++ /branches/bleeding_edge/src/arm/lithium-arm.cc Mon Oct 8 05:50:15 2012
@@ -1040,7 +1040,8 @@
return DefineFixedDouble(result, d2);
} else {
LOperand* input = UseRegisterAtStart(instr->value());
- LOperand* temp = (op == kMathFloor) ? TempRegister() : NULL;
+
+ LOperand* temp = (op == kMathRound) ? FixedTemp(d3) : NULL;
LUnaryMathOperation* result = new(zone()) LUnaryMathOperation(input,
temp);
switch (op) {
case kMathAbs:
@@ -1616,8 +1617,7 @@
LOperand* temp1 = TempRegister();
LOperand* temp2 = instr->CanTruncateToInt32() ? TempRegister()
: NULL;
- LOperand* temp3 = instr->CanTruncateToInt32() ? FixedTemp(d11)
- : NULL;
+ LOperand* temp3 = FixedTemp(d11);
res = DefineSameAsFirst(new(zone()) LTaggedToI(value,
temp1,
temp2,
=======================================
--- /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Tue Oct 2
09:48:45 2012
+++ /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Mon Oct 8
05:50:15 2012
@@ -3499,27 +3499,22 @@
void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) {
DoubleRegister input = ToDoubleRegister(instr->value());
Register result = ToRegister(instr->result());
- SwVfpRegister single_scratch = double_scratch0().low();
- Register scratch1 = scratch0();
- Register scratch2 = ToRegister(instr->temp());
+ Register scratch = scratch0();
__ EmitVFPTruncate(kRoundToMinusInf,
- single_scratch,
+ result,
input,
- scratch1,
- scratch2);
+ scratch,
+ double_scratch0());
DeoptimizeIf(ne, instr->environment());
- // Move the result back to general purpose register r0.
- __ vmov(result, single_scratch);
-
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
// Test for -0.
Label done;
__ cmp(result, Operand(0));
__ b(ne, &done);
- __ vmov(scratch1, input.high());
- __ tst(scratch1, Operand(HeapNumber::kSignMask));
+ __ vmov(scratch, input.high());
+ __ tst(scratch, Operand(HeapNumber::kSignMask));
DeoptimizeIf(ne, instr->environment());
__ bind(&done);
}
@@ -3529,6 +3524,7 @@
void LCodeGen::DoMathRound(LUnaryMathOperation* instr) {
DoubleRegister input = ToDoubleRegister(instr->value());
Register result = ToRegister(instr->result());
+ DwVfpRegister double_scratch1 = ToDoubleRegister(instr->temp());
Register scratch = scratch0();
Label done, check_sign_on_zero;
@@ -3571,12 +3567,11 @@
}
__ EmitVFPTruncate(kRoundToMinusInf,
- double_scratch0().low(),
+ result,
double_scratch0(),
- result,
- scratch);
+ scratch,
+ double_scratch1);
DeoptimizeIf(ne, instr->environment());
- __ vmov(result, double_scratch0().low());
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
// Test for -0.
@@ -4602,7 +4597,7 @@
Register scratch1 = scratch0();
Register scratch2 = ToRegister(instr->temp());
DwVfpRegister double_scratch = double_scratch0();
- SwVfpRegister single_scratch = double_scratch.low();
+ DwVfpRegister double_scratch2 = ToDoubleRegister(instr->temp3());
ASSERT(!scratch1.is(input_reg) && !scratch1.is(scratch2));
ASSERT(!scratch2.is(input_reg) && !scratch2.is(scratch1));
@@ -4622,7 +4617,7 @@
if (instr->truncating()) {
Register scratch3 = ToRegister(instr->temp2());
- DwVfpRegister double_scratch2 = ToDoubleRegister(instr->temp3());
+ SwVfpRegister single_scratch = double_scratch.low();
ASSERT(!scratch3.is(input_reg) &&
!scratch3.is(scratch1) &&
!scratch3.is(scratch2));
@@ -4657,14 +4652,12 @@
__ sub(ip, input_reg, Operand(kHeapObjectTag));
__ vldr(double_scratch, ip, HeapNumber::kValueOffset);
__ EmitVFPTruncate(kRoundToZero,
- single_scratch,
+ input_reg,
double_scratch,
scratch1,
- scratch2,
+ double_scratch2,
kCheckForInexactConversion);
DeoptimizeIf(ne, instr->environment());
- // Load the result.
- __ vmov(input_reg, single_scratch);
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
__ cmp(input_reg, Operand(0));
@@ -4728,12 +4721,12 @@
Register scratch1 = scratch0();
Register scratch2 = ToRegister(instr->temp());
DwVfpRegister double_input = ToDoubleRegister(instr->value());
- SwVfpRegister single_scratch = double_scratch0().low();
Label done;
if (instr->truncating()) {
Register scratch3 = ToRegister(instr->temp2());
+ SwVfpRegister single_scratch = double_scratch0().low();
__ EmitECMATruncate(result_reg,
double_input,
single_scratch,
@@ -4741,18 +4734,17 @@
scratch2,
scratch3);
} else {
- VFPRoundingMode rounding_mode = kRoundToMinusInf;
- __ EmitVFPTruncate(rounding_mode,
- single_scratch,
+ DwVfpRegister double_scratch = double_scratch0();
+ __ EmitVFPTruncate(kRoundToMinusInf,
+ result_reg,
double_input,
scratch1,
- scratch2,
+ double_scratch,
kCheckForInexactConversion);
+
// Deoptimize if we had a vfp invalid exception,
// including inexact operation.
DeoptimizeIf(ne, instr->environment());
- // Retrieve the result.
- __ vmov(result_reg, single_scratch);
}
__ bind(&done);
}
=======================================
--- /branches/bleeding_edge/src/arm/macro-assembler-arm.cc Thu Sep 27
00:45:49 2012
+++ /branches/bleeding_edge/src/arm/macro-assembler-arm.cc Mon Oct 8
05:50:15 2012
@@ -2437,16 +2437,27 @@
void MacroAssembler::EmitVFPTruncate(VFPRoundingMode rounding_mode,
- SwVfpRegister result,
+ Register result,
DwVfpRegister double_input,
- Register scratch1,
- Register scratch2,
+ Register scratch,
+ DwVfpRegister double_scratch,
CheckForInexactConversion
check_inexact) {
+ ASSERT(!result.is(scratch));
+ ASSERT(!double_input.is(double_scratch));
+
ASSERT(CpuFeatures::IsSupported(VFP2));
CpuFeatures::Scope scope(VFP2);
- Register prev_fpscr = scratch1;
- Register scratch = scratch2;
+ Register prev_fpscr = result;
+ Label done;
+
+ // Test for values that can be exactly represented as a signed 32-bit
integer.
+ vcvt_s32_f64(double_scratch.low(), double_input);
+ vmov(result, double_scratch.low());
+ vcvt_f64_s32(double_scratch, double_scratch.low());
+ VFPCompareAndSetFlags(double_input, double_scratch);
+ b(eq, &done);
+ // Convert to integer, respecting rounding mode.
int32_t check_inexact_conversion =
(check_inexact == kCheckForInexactConversion) ?
kVFPInexactExceptionBit : 0;
@@ -2468,7 +2479,7 @@
vmsr(scratch);
// Convert the argument to an integer.
- vcvt_s32_f64(result,
+ vcvt_s32_f64(double_scratch.low(),
double_input,
(rounding_mode == kRoundToZero) ? kDefaultRoundToZero
: kFPSCRRounding);
@@ -2477,8 +2488,12 @@
vmrs(scratch);
// Restore FPSCR.
vmsr(prev_fpscr);
+ // Move the converted value into the result register.
+ vmov(result, double_scratch.low());
// Check for vfp exceptions.
tst(scratch, Operand(kVFPExceptionMask | check_inexact_conversion));
+
+ bind(&done);
}
=======================================
--- /branches/bleeding_edge/src/arm/macro-assembler-arm.h Thu Sep 27
00:45:49 2012
+++ /branches/bleeding_edge/src/arm/macro-assembler-arm.h Mon Oct 8
05:50:15 2012
@@ -939,21 +939,22 @@
DwVfpRegister double_scratch,
Label *not_int32);
- // Truncates a double using a specific rounding mode.
+ // Truncates a double using a specific rounding mode, and writes the
value
+ // to the result register.
// Clears the z flag (ne condition) if an overflow occurs.
- // If exact_conversion is true, the z flag is also cleared if the
conversion
- // was inexact, i.e. if the double value could not be converted exactly
- // to a 32bit integer.
+ // If kCheckForInexactConversion is passed, the z flag is also cleared
if the
+ // conversion was inexact, i.e. if the double value could not be
converted
+ // exactly to a 32-bit integer.
void EmitVFPTruncate(VFPRoundingMode rounding_mode,
- SwVfpRegister result,
+ Register result,
DwVfpRegister double_input,
- Register scratch1,
- Register scratch2,
+ Register scratch,
+ DwVfpRegister double_scratch,
CheckForInexactConversion check
= kDontCheckForInexactConversion);
// Helper for EmitECMATruncate.
- // This will truncate a floating-point value outside of the singed 32bit
+ // This will truncate a floating-point value outside of the signed 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'.
=======================================
--- /branches/bleeding_edge/src/arm/stub-cache-arm.cc Thu Sep 27 00:45:49
2012
+++ /branches/bleeding_edge/src/arm/stub-cache-arm.cc Mon Oct 8 05:50:15
2012
@@ -3646,6 +3646,7 @@
Register scratch0,
Register scratch1,
DwVfpRegister double_scratch0,
+ DwVfpRegister double_scratch1,
Label* fail) {
if (CpuFeatures::IsSupported(VFP2)) {
CpuFeatures::Scope scope(VFP2);
@@ -3662,13 +3663,12 @@
__ sub(ip, key, Operand(kHeapObjectTag));
__ vldr(double_scratch0, ip, HeapNumber::kValueOffset);
__ EmitVFPTruncate(kRoundToZero,
- double_scratch0.low(),
+ scratch0,
double_scratch0,
- scratch0,
scratch1,
+ double_scratch1,
kCheckForInexactConversion);
__ b(ne, fail);
- __ vmov(scratch0, double_scratch0.low());
__ TrySmiTag(scratch0, fail, scratch1);
__ mov(key, scratch0);
__ bind(&key_ok);
@@ -3696,7 +3696,7 @@
// have been verified by the caller to not be a smi.
// Check that the key is a smi or a heap number convertible to a smi.
- GenerateSmiKeyCheck(masm, key, r4, r5, d1, &miss_force_generic);
+ GenerateSmiKeyCheck(masm, key, r4, r5, d1, d2, &miss_force_generic);
__ ldr(r3, FieldMemOperand(receiver, JSObject::kElementsOffset));
// r3: elements array
@@ -4030,7 +4030,7 @@
// have been verified by the caller to not be a smi.
// Check that the key is a smi or a heap number convertible to a smi.
- GenerateSmiKeyCheck(masm, key, r4, r5, d1, &miss_force_generic);
+ GenerateSmiKeyCheck(masm, key, r4, r5, d1, d2, &miss_force_generic);
__ ldr(r3, FieldMemOperand(receiver, JSObject::kElementsOffset));
@@ -4365,7 +4365,7 @@
// have been verified by the caller to not be a smi.
// Check that the key is a smi or a heap number convertible to a smi.
- GenerateSmiKeyCheck(masm, r0, r4, r5, d1, &miss_force_generic);
+ GenerateSmiKeyCheck(masm, r0, r4, r5, d1, d2, &miss_force_generic);
// Get the elements array.
__ ldr(r2, FieldMemOperand(r1, JSObject::kElementsOffset));
@@ -4417,7 +4417,7 @@
// have been verified by the caller to not be a smi.
// Check that the key is a smi or a heap number convertible to a smi.
- GenerateSmiKeyCheck(masm, key_reg, r4, r5, d1, &miss_force_generic);
+ GenerateSmiKeyCheck(masm, key_reg, r4, r5, d1, d2, &miss_force_generic);
// Get the elements array.
__ ldr(elements_reg,
@@ -4493,7 +4493,7 @@
// have been verified by the caller to not be a smi.
// Check that the key is a smi or a heap number convertible to a smi.
- GenerateSmiKeyCheck(masm, key_reg, r4, r5, d1, &miss_force_generic);
+ GenerateSmiKeyCheck(masm, key_reg, r4, r5, d1, d2, &miss_force_generic);
if (IsFastSmiElementsKind(elements_kind)) {
__ JumpIfNotSmi(value_reg, &transition_elements_kind);
@@ -4661,7 +4661,7 @@
// have been verified by the caller to not be a smi.
// Check that the key is a smi or a heap number convertible to a smi.
- GenerateSmiKeyCheck(masm, key_reg, r4, r5, d1, &miss_force_generic);
+ GenerateSmiKeyCheck(masm, key_reg, r4, r5, d1, d2, &miss_force_generic);
__ ldr(elements_reg,
FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev