Chromium Code Reviews| Index: runtime/vm/intermediate_language_arm.cc |
| =================================================================== |
| --- runtime/vm/intermediate_language_arm.cc (revision 26548) |
| +++ runtime/vm/intermediate_language_arm.cc (working copy) |
| @@ -4132,6 +4132,10 @@ |
| if (InputCount() == 2) { |
| result->set_in(1, Location::FpuRegisterLocation(Q1)); |
| } |
| + if (recognized_kind() == MethodRecognizer::kMathDoublePow) { |
| + result->AddTemp(Location::RegisterLocation(R2)); |
|
zra
2013/08/23 22:43:03
Why does this have to be R2? I think you can use T
srdjan
2013/08/23 23:26:04
The IP is used because the offset is not 4-byte al
|
| + result->AddTemp(Location::FpuRegisterLocation(Q2)); |
| + } |
| result->set_out(Location::FpuRegisterLocation(Q0)); |
| return result; |
| } |
| @@ -4141,16 +4145,45 @@ |
| // For pow-function return NaN if exponent is NaN. |
| Label do_call, skip_call; |
| if (recognized_kind() == MethodRecognizer::kMathDoublePow) { |
| + // if (exponent == 0.0) return 0.0; |
|
regis
2013/08/26 17:03:26
I would add a comment like this, otherwise it look
srdjan
2013/08/26 17:24:00
Done.
|
| + // if (base == 1.0) return 1.0; |
| + // if (base.isNaN || exponent.isNaN) { |
| + // return double.NAN; |
| + // } |
| + DRegister base = EvenDRegisterOf(locs()->in(0).fpu_reg()); |
| DRegister exp = EvenDRegisterOf(locs()->in(1).fpu_reg()); |
| DRegister result = EvenDRegisterOf(locs()->out().fpu_reg()); |
| - __ vcmpd(exp, exp); |
| + Register temp = locs()->temp(0).reg(); |
| + DRegister saved_base = EvenDRegisterOf(locs()->temp(1).fpu_reg()); |
| + ASSERT((base == result) && (result != saved_base)); |
| + Label check_base_is_one; |
| + // Check if exponent is 0.0 -> return 1.0; |
| + __ vmovd(saved_base, base); |
| + __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(0))); |
| + __ LoadDFromOffset(DTMP, temp, Double::value_offset() - kHeapObjectTag); |
| + __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(1))); |
| + __ LoadDFromOffset(result, temp, Double::value_offset() - kHeapObjectTag); |
| + __ vcmpd(exp, DTMP); |
| __ vmstat(); |
| - __ b(&do_call, VC); // NaN -> false; |
| - // Exponent is NaN, return NaN. |
| - __ vmovd(result, exp); |
| + __ b(&check_base_is_one, VS); // NaN -> not zero. |
| + __ b(&skip_call, EQ); // exp is 0.0, result is 1.0. |
| + |
| + Label base_is_nan; |
| + __ Bind(&check_base_is_one); |
| + __ vcmpd(saved_base, result); |
| + __ vmstat(); |
| + __ b(&base_is_nan, VS); |
|
regis
2013/08/26 17:03:26
Instead of:
__ b(&base_is_nan, VS);
and
__ Bind(&b
srdjan
2013/08/26 17:24:00
Done.
|
| + __ b(&skip_call, EQ); // base and result are 1.0. |
| + __ b(&do_call); |
| + |
| + __ Bind(&base_is_nan); |
| + __ vmovd(result, saved_base); // base is NaN, return NaN. |
| __ b(&skip_call); |
| + __ Bind(&do_call); |
| + __ vmovd(base, saved_base); // Restore base. |
| + } else { |
| + __ Bind(&do_call); |
| } |
| - __ Bind(&do_call); |
| // We currently use 'hardfp' ('gnueabihf') rather than 'softfp' |
| // ('gnueabi') float ABI for leaf runtime calls, i.e. double values |
| // are passed and returned in vfp registers rather than in integer |