ARM: Small optimisation of VFP immediate creation

Save an instruction in VFP immediate creation by passing a scratch register.

BUG=none
TEST=none

Review URL: https://chromiumcodereview.appspot.com/10990024
Patch from Martyn Capewell <m.m.capewell@googlemail.com>.

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@12605 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
danno@chromium.org 2012-09-25 14:32:07 +00:00
parent 72e9f1bea1
commit c467b2659f
6 changed files with 26 additions and 22 deletions

View File

@ -1975,6 +1975,7 @@ static bool FitsVMOVDoubleImmediate(double d, uint32_t *encoding) {
void Assembler::vmov(const DwVfpRegister dst, void Assembler::vmov(const DwVfpRegister dst,
double imm, double imm,
const Register scratch,
const Condition cond) { const Condition cond) {
// Dd = immediate // Dd = immediate
// Instruction details available in ARM DDI 0406B, A8-640. // Instruction details available in ARM DDI 0406B, A8-640.
@ -1989,22 +1990,22 @@ void Assembler::vmov(const DwVfpRegister dst,
// using vldr from a constant pool. // using vldr from a constant pool.
uint32_t lo, hi; uint32_t lo, hi;
DoubleAsTwoUInt32(imm, &lo, &hi); DoubleAsTwoUInt32(imm, &lo, &hi);
mov(ip, Operand(lo));
if (lo == hi) { if (scratch.is(no_reg)) {
// If the lo and hi parts of the double are equal, the literal is easier
// to create. This is the case with 0.0.
mov(ip, Operand(lo));
vmov(dst, ip, ip);
} else {
// Move the low part of the double into the lower of the corresponsing S // Move the low part of the double into the lower of the corresponsing S
// registers of D register dst. // registers of D register dst.
mov(ip, Operand(lo));
vmov(dst.low(), ip, cond); vmov(dst.low(), ip, cond);
// Move the high part of the double into the higher of the corresponsing S // Move the high part of the double into the higher of the corresponsing S
// registers of D register dst. // registers of D register dst.
mov(ip, Operand(hi)); mov(ip, Operand(hi));
vmov(dst.high(), ip, cond); vmov(dst.high(), ip, cond);
} else {
// Move the low and high parts of the double to a D register in one
// instruction.
mov(scratch, Operand(hi));
vmov(dst, ip, scratch, cond);
} }
} }
} }

View File

@ -1053,6 +1053,7 @@ class Assembler : public AssemblerBase {
void vmov(const DwVfpRegister dst, void vmov(const DwVfpRegister dst,
double imm, double imm,
const Register scratch = no_reg,
const Condition cond = al); const Condition cond = al);
void vmov(const SwVfpRegister dst, void vmov(const SwVfpRegister dst,
const SwVfpRegister src, const SwVfpRegister src,

View File

@ -3636,13 +3636,13 @@ void MathPowStub::Generate(MacroAssembler* masm) {
Label not_plus_half; Label not_plus_half;
// Test for 0.5. // Test for 0.5.
__ vmov(double_scratch, 0.5); __ vmov(double_scratch, 0.5, scratch);
__ VFPCompareAndSetFlags(double_exponent, double_scratch); __ VFPCompareAndSetFlags(double_exponent, double_scratch);
__ b(ne, &not_plus_half); __ b(ne, &not_plus_half);
// Calculates square root of base. Check for the special case of // Calculates square root of base. Check for the special case of
// Math.pow(-Infinity, 0.5) == Infinity (ECMA spec, 15.8.2.13). // Math.pow(-Infinity, 0.5) == Infinity (ECMA spec, 15.8.2.13).
__ vmov(double_scratch, -V8_INFINITY); __ vmov(double_scratch, -V8_INFINITY, scratch);
__ VFPCompareAndSetFlags(double_base, double_scratch); __ VFPCompareAndSetFlags(double_base, double_scratch);
__ vneg(double_result, double_scratch, eq); __ vneg(double_result, double_scratch, eq);
__ b(eq, &done); __ b(eq, &done);
@ -3653,20 +3653,20 @@ void MathPowStub::Generate(MacroAssembler* masm) {
__ jmp(&done); __ jmp(&done);
__ bind(&not_plus_half); __ bind(&not_plus_half);
__ vmov(double_scratch, -0.5); __ vmov(double_scratch, -0.5, scratch);
__ VFPCompareAndSetFlags(double_exponent, double_scratch); __ VFPCompareAndSetFlags(double_exponent, double_scratch);
__ b(ne, &call_runtime); __ b(ne, &call_runtime);
// Calculates square root of base. Check for the special case of // Calculates square root of base. Check for the special case of
// Math.pow(-Infinity, -0.5) == 0 (ECMA spec, 15.8.2.13). // Math.pow(-Infinity, -0.5) == 0 (ECMA spec, 15.8.2.13).
__ vmov(double_scratch, -V8_INFINITY); __ vmov(double_scratch, -V8_INFINITY, scratch);
__ VFPCompareAndSetFlags(double_base, double_scratch); __ VFPCompareAndSetFlags(double_base, double_scratch);
__ vmov(double_result, kDoubleRegZero, eq); __ vmov(double_result, kDoubleRegZero, eq);
__ b(eq, &done); __ b(eq, &done);
// Add +0 to convert -0 to +0. // Add +0 to convert -0 to +0.
__ vadd(double_scratch, double_base, kDoubleRegZero); __ vadd(double_scratch, double_base, kDoubleRegZero);
__ vmov(double_result, 1.0); __ vmov(double_result, 1.0, scratch);
__ vsqrt(double_scratch, double_scratch); __ vsqrt(double_scratch, double_scratch);
__ vdiv(double_result, double_result, double_scratch); __ vdiv(double_result, double_result, double_scratch);
__ jmp(&done); __ jmp(&done);
@ -3701,7 +3701,7 @@ void MathPowStub::Generate(MacroAssembler* masm) {
__ mov(exponent, scratch); __ mov(exponent, scratch);
} }
__ vmov(double_scratch, double_base); // Back up base. __ vmov(double_scratch, double_base); // Back up base.
__ vmov(double_result, 1.0); __ vmov(double_result, 1.0, scratch2);
// Get absolute value of exponent. // Get absolute value of exponent.
__ cmp(scratch, Operand(0)); __ cmp(scratch, Operand(0));
@ -3717,7 +3717,7 @@ void MathPowStub::Generate(MacroAssembler* masm) {
__ cmp(exponent, Operand(0)); __ cmp(exponent, Operand(0));
__ b(ge, &done); __ b(ge, &done);
__ vmov(double_scratch, 1.0); __ vmov(double_scratch, 1.0, scratch);
__ vdiv(double_result, double_scratch, double_result); __ vdiv(double_result, double_scratch, double_result);
// Test whether result is zero. Bail out to check for subnormal result. // Test whether result is zero. Bail out to check for subnormal result.
// Due to subnormals, x^-y == (1/x)^y does not hold in all cases. // Due to subnormals, x^-y == (1/x)^y does not hold in all cases.

View File

@ -1551,7 +1551,7 @@ void LCodeGen::DoConstantD(LConstantD* instr) {
ASSERT(instr->result()->IsDoubleRegister()); ASSERT(instr->result()->IsDoubleRegister());
DwVfpRegister result = ToDoubleRegister(instr->result()); DwVfpRegister result = ToDoubleRegister(instr->result());
double v = instr->value(); double v = instr->value();
__ Vmov(result, v); __ Vmov(result, v, scratch0());
} }
@ -3530,12 +3530,12 @@ void LCodeGen::DoMathRound(LUnaryMathOperation* instr) {
__ cmp(scratch, Operand(HeapNumber::kExponentBias + 32)); __ cmp(scratch, Operand(HeapNumber::kExponentBias + 32));
DeoptimizeIf(ge, instr->environment()); DeoptimizeIf(ge, instr->environment());
__ Vmov(double_scratch0(), 0.5, scratch);
__ vadd(double_scratch0(), input, double_scratch0());
// Save the original sign for later comparison. // Save the original sign for later comparison.
__ and_(scratch, result, Operand(HeapNumber::kSignMask)); __ and_(scratch, result, Operand(HeapNumber::kSignMask));
__ Vmov(double_scratch0(), 0.5);
__ vadd(double_scratch0(), input, double_scratch0());
// Check sign of the result: if the sign changed, the input // Check sign of the result: if the sign changed, the input
// value was in ]0.5, 0[ and the result should be -0. // value was in ]0.5, 0[ and the result should be -0.
__ vmov(result, double_scratch0().high()); __ vmov(result, double_scratch0().high());
@ -3584,7 +3584,7 @@ void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) {
// Math.pow(-Infinity, 0.5) == Infinity // Math.pow(-Infinity, 0.5) == Infinity
// Math.sqrt(-Infinity) == NaN // Math.sqrt(-Infinity) == NaN
Label done; Label done;
__ vmov(temp, -V8_INFINITY); __ vmov(temp, -V8_INFINITY, scratch0());
__ VFPCompareAndSetFlags(input, temp); __ VFPCompareAndSetFlags(input, temp);
__ vneg(result, temp, eq); __ vneg(result, temp, eq);
__ b(&done, eq); __ b(&done, eq);
@ -4066,7 +4066,7 @@ void LCodeGen::DoStoreKeyedFastDoubleElement(
// Only load canonical NaN if the comparison above set the overflow. // Only load canonical NaN if the comparison above set the overflow.
__ Vmov(value, __ Vmov(value,
FixedDoubleArray::canonical_not_the_hole_nan_as_double(), FixedDoubleArray::canonical_not_the_hole_nan_as_double(),
vs); no_reg, vs);
} }
__ vstr(value, scratch, instr->additional_index() << element_size_shift); __ vstr(value, scratch, instr->additional_index() << element_size_shift);

View File

@ -789,6 +789,7 @@ void MacroAssembler::VFPCompareAndLoadFlags(const DwVfpRegister src1,
void MacroAssembler::Vmov(const DwVfpRegister dst, void MacroAssembler::Vmov(const DwVfpRegister dst,
const double imm, const double imm,
const Register scratch,
const Condition cond) { const Condition cond) {
ASSERT(CpuFeatures::IsEnabled(VFP2)); ASSERT(CpuFeatures::IsEnabled(VFP2));
static const DoubleRepresentation minus_zero(-0.0); static const DoubleRepresentation minus_zero(-0.0);
@ -800,7 +801,7 @@ void MacroAssembler::Vmov(const DwVfpRegister dst,
} else if (value.bits == minus_zero.bits) { } else if (value.bits == minus_zero.bits) {
vneg(dst, kDoubleRegZero, cond); vneg(dst, kDoubleRegZero, cond);
} else { } else {
vmov(dst, imm, cond); vmov(dst, imm, scratch, cond);
} }
} }
@ -3676,7 +3677,7 @@ void MacroAssembler::ClampDoubleToUint8(Register result_reg,
// Double value is >= 255, return 255. // Double value is >= 255, return 255.
bind(&above_zero); bind(&above_zero);
Vmov(temp_double_reg, 255.0); Vmov(temp_double_reg, 255.0, result_reg);
VFPCompareAndSetFlags(input_reg, temp_double_reg); VFPCompareAndSetFlags(input_reg, temp_double_reg);
b(le, &in_bounds); b(le, &in_bounds);
mov(result_reg, Operand(255)); mov(result_reg, Operand(255));

View File

@ -483,6 +483,7 @@ class MacroAssembler: public Assembler {
void Vmov(const DwVfpRegister dst, void Vmov(const DwVfpRegister dst,
const double imm, const double imm,
const Register scratch = no_reg,
const Condition cond = al); const Condition cond = al);
// Enter exit frame. // Enter exit frame.