Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. |
| 6 #if defined(TARGET_ARCH_ARM) | 6 #if defined(TARGET_ARCH_ARM) |
| 7 | 7 |
| 8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 | 9 |
| 10 #include "vm/cpu.h" | 10 #include "vm/cpu.h" |
| (...skipping 5096 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5107 if (recognized_kind() != MethodRecognizer::kMathDoublePow) { | 5107 if (recognized_kind() != MethodRecognizer::kMathDoublePow) { |
| 5108 result->AddTemp(Location::RegisterLocation(R2)); | 5108 result->AddTemp(Location::RegisterLocation(R2)); |
| 5109 } | 5109 } |
| 5110 result->AddTemp(Location::RegisterLocation(R3)); | 5110 result->AddTemp(Location::RegisterLocation(R3)); |
| 5111 #endif | 5111 #endif |
| 5112 result->set_out(0, Location::FpuRegisterLocation(Q0)); | 5112 result->set_out(0, Location::FpuRegisterLocation(Q0)); |
| 5113 return result; | 5113 return result; |
| 5114 } | 5114 } |
| 5115 | 5115 |
| 5116 | 5116 |
| 5117 // Pseudo code: | |
| 5118 // if (exponent == 0.0) return 1.0; | |
| 5119 // // Speed up simple cases. | |
| 5120 // if (exponent == 1.0) return base; | |
| 5121 // if (exponent == 2.0) return base * base; | |
| 5122 // if (exponent == 3.0) return base * base * base; | |
| 5123 // if (base == 1.0) return 1.0; | |
| 5124 // if (base.isNaN || exponent.isNaN) { | |
| 5125 // return double.NAN; | |
| 5126 // } | |
| 5127 // if (base != -Infinity && exponent == 0.5) { | |
| 5128 // if (base == 0.0) return 0.0; | |
| 5129 // return sqrt(value); | |
| 5130 // } | |
| 5131 // TODO(srdjan): Move into a stub? | |
| 5132 static void InvokeDoublePow(FlowGraphCompiler* compiler, | |
| 5133 InvokeMathCFunctionInstr* instr) { | |
| 5134 ASSERT(instr->recognized_kind() == MethodRecognizer::kMathDoublePow); | |
| 5135 const intptr_t kInputCount = 2; | |
| 5136 ASSERT(instr->InputCount() == kInputCount); | |
| 5137 LocationSummary* locs = instr->locs(); | |
| 5138 | |
| 5139 const DRegister base = EvenDRegisterOf(locs->in(0).fpu_reg()); | |
| 5140 const DRegister exp = EvenDRegisterOf(locs->in(1).fpu_reg()); | |
| 5141 const DRegister result = EvenDRegisterOf(locs->out(0).fpu_reg()); | |
| 5142 const Register temp = locs->temp(0).reg(); | |
| 5143 const DRegister saved_base = EvenDRegisterOf(locs->temp(1).fpu_reg()); | |
|
zra
2014/05/08 19:07:57
Now that I stare at this harder, I think you can u
srdjan
2014/05/08 22:15:31
Done.
| |
| 5144 ASSERT((base == result) && (result != saved_base)); | |
| 5145 | |
| 5146 Label skip_call, try_sqrt, check_base, return_nan; | |
| 5147 __ vmovd(saved_base, base); | |
| 5148 __ LoadDImmediate(DTMP, 0.0, temp); | |
| 5149 __ LoadDImmediate(result, 1.0, temp); | |
| 5150 // exponent == 0.0 -> return 1.0; | |
| 5151 __ vcmpd(exp, DTMP); | |
|
zra
2014/05/08 19:07:57
__ vcmpdz(exp); and remove load of zero into DTMP.
srdjan
2014/05/08 22:15:31
Done.
srdjan
2014/05/08 22:15:31
Done.
| |
| 5152 __ vmstat(); | |
| 5153 __ b(&check_base, VS); // NaN -> check base. | |
| 5154 __ b(&skip_call, EQ); // exp is 0.0, result is 1.0. | |
| 5155 | |
| 5156 // exponent == 1.0 ? | |
| 5157 __ vcmpd(exp, result); | |
| 5158 __ vmstat(); | |
| 5159 Label return_base; | |
| 5160 __ b(&return_base, EQ); | |
| 5161 | |
| 5162 // exponent == 2.0 ? | |
| 5163 __ LoadDImmediate(DTMP, 2.0, temp); | |
| 5164 __ vcmpd(exp, DTMP); | |
| 5165 __ vmstat(); | |
| 5166 Label return_base_times_2; | |
| 5167 __ b(&return_base_times_2, EQ); | |
| 5168 | |
| 5169 // exponent == 3.0 ? | |
| 5170 __ LoadDImmediate(DTMP, 3.0, temp); | |
| 5171 __ vcmpd(exp, DTMP); | |
| 5172 __ vmstat(); | |
| 5173 __ b(&check_base, NE); | |
| 5174 | |
| 5175 // base_times_3. | |
| 5176 __ vmuld(result, saved_base, saved_base); | |
| 5177 __ vmuld(result, result, saved_base); | |
| 5178 __ b(&skip_call); | |
| 5179 | |
| 5180 __ Bind(&return_base); | |
| 5181 __ vmovd(result, saved_base); | |
| 5182 __ b(&skip_call); | |
| 5183 | |
| 5184 __ Bind(&return_base_times_2); | |
| 5185 __ vmuld(result, saved_base, saved_base); | |
| 5186 __ b(&skip_call); | |
| 5187 | |
| 5188 __ Bind(&check_base); | |
| 5189 // Note: 'exp' could be NaN. | |
| 5190 // base == 1.0 -> return 1.0; | |
| 5191 __ vcmpd(saved_base, result); | |
| 5192 __ vmstat(); | |
| 5193 __ b(&return_nan, VS); | |
| 5194 __ b(&skip_call, EQ); // base is 1.0, result is 1.0. | |
| 5195 | |
| 5196 __ vcmpd(saved_base, exp); | |
| 5197 __ b(&try_sqrt, VC); // // Neither 'exp' nor 'base' is NaN. | |
| 5198 | |
| 5199 __ Bind(&return_nan); | |
| 5200 __ LoadDImmediate(result, NAN, temp); | |
| 5201 __ b(&skip_call); | |
| 5202 | |
| 5203 Label do_pow, return_zero; | |
| 5204 __ Bind(&try_sqrt); | |
| 5205 | |
| 5206 // Before calling pow, check if we could use sqrt instead of pow. | |
| 5207 __ LoadDImmediate(result, -INFINITY, temp); | |
| 5208 | |
| 5209 // base == -Infinity -> call pow; | |
| 5210 __ vcmpd(saved_base, result); | |
| 5211 __ b(&do_pow, EQ); | |
| 5212 | |
| 5213 // exponent == 0.5 ? | |
| 5214 __ LoadDImmediate(result, 0.5, temp); | |
| 5215 __ vcmpd(exp, result); | |
| 5216 __ b(&do_pow, NE); | |
| 5217 | |
| 5218 // base == 0 -> return 0; | |
| 5219 __ LoadDImmediate(DTMP, 0.0, temp); | |
| 5220 __ vcmpd(base, DTMP); | |
|
zra
2014/05/08 19:07:57
__ vcmpdz(base); and remove immediate load.
srdjan
2014/05/08 22:15:31
Done.
| |
| 5221 __ b(&return_zero, EQ); | |
| 5222 | |
| 5223 __ vsqrtd(result, saved_base); | |
| 5224 __ b(&skip_call); | |
| 5225 | |
| 5226 __ Bind(&return_zero); | |
| 5227 __ vmovd(result, DTMP); | |
| 5228 __ b(&skip_call); | |
| 5229 | |
| 5230 __ Bind(&do_pow); | |
| 5231 __ vmovd(base, saved_base); // Restore base. | |
| 5232 | |
| 5233 // Args must be in D0 and D1, so move arg from Q1(== D3:D2) to D1. | |
| 5234 __ vmovd(D1, D2); | |
| 5235 #if defined(ARM_FLOAT_ABI_HARD) | |
| 5236 __ CallRuntime(instr->TargetFunction(), kInputCount); | |
| 5237 #else | |
| 5238 // If the ABI is not "hardfp", then we have to move the double arguments | |
| 5239 // to the integer registers, and take the results from the integer | |
| 5240 // registers. | |
| 5241 __ vmovrrd(R0, R1, D0); | |
| 5242 __ vmovrrd(R2, R3, D1); | |
| 5243 __ CallRuntime(instr->TargetFunction(), kInputCount); | |
| 5244 __ vmovdrr(D0, R0, R1); | |
| 5245 __ vmovdrr(D1, R2, R3); | |
| 5246 #endif | |
| 5247 __ Bind(&skip_call); | |
| 5248 } | |
| 5249 | |
| 5250 | |
| 5117 void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5251 void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5118 // For pow-function return NaN if exponent is NaN. | |
| 5119 Label skip_call; | |
| 5120 if (recognized_kind() == MethodRecognizer::kMathDoublePow) { | 5252 if (recognized_kind() == MethodRecognizer::kMathDoublePow) { |
| 5121 // Pseudo code: | 5253 InvokeDoublePow(compiler, this); |
| 5122 // if (exponent == 0.0) return 1.0; | 5254 return; |
| 5123 // if (base == 1.0) return 1.0; | |
| 5124 // if (base.isNaN || exponent.isNaN) { | |
| 5125 // return double.NAN; | |
| 5126 // } | |
| 5127 // if (base != -Infinity && exponent == 0.5) { | |
| 5128 // if (base == 0.0) return 0.0; | |
| 5129 // return sqrt(value); | |
| 5130 // } | |
| 5131 const DRegister base = EvenDRegisterOf(locs()->in(0).fpu_reg()); | |
| 5132 const DRegister exp = EvenDRegisterOf(locs()->in(1).fpu_reg()); | |
| 5133 const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); | |
| 5134 const Register temp = locs()->temp(0).reg(); | |
| 5135 const DRegister saved_base = EvenDRegisterOf(locs()->temp(1).fpu_reg()); | |
| 5136 ASSERT((base == result) && (result != saved_base)); | |
| 5137 | |
| 5138 Label try_sqrt, check_base, return_nan; | |
| 5139 __ vmovd(saved_base, base); | |
| 5140 __ LoadDImmediate(DTMP, 0.0, temp); | |
| 5141 __ LoadDImmediate(result, 1.0, temp); | |
| 5142 // exponent == 0.0 -> return 1.0; | |
| 5143 __ vcmpd(exp, DTMP); | |
| 5144 __ vmstat(); | |
| 5145 __ b(&check_base, VS); // NaN -> check base. | |
| 5146 __ b(&skip_call, EQ); // exp is 0.0, result is 1.0. | |
| 5147 | |
| 5148 __ Bind(&check_base); | |
| 5149 // Note: 'exp' could be NaN. | |
| 5150 // base == 1.0 -> return 1.0; | |
| 5151 __ vcmpd(saved_base, result); | |
| 5152 __ vmstat(); | |
| 5153 __ b(&return_nan, VS); | |
| 5154 __ b(&skip_call, EQ); // base is 1.0, result is 1.0. | |
| 5155 | |
| 5156 __ vcmpd(saved_base, exp); | |
| 5157 __ b(&try_sqrt, VC); // // Neither 'exp' nor 'base' is NaN. | |
| 5158 | |
| 5159 __ Bind(&return_nan); | |
| 5160 __ LoadDImmediate(result, NAN, temp); | |
| 5161 __ b(&skip_call); | |
| 5162 | |
| 5163 Label do_pow, return_zero; | |
| 5164 __ Bind(&try_sqrt); | |
| 5165 | |
| 5166 // Before calling pow, check if we could use sqrt instead of pow. | |
| 5167 __ LoadDImmediate(result, -INFINITY, temp); | |
| 5168 | |
| 5169 // base == -Infinity -> call pow; | |
| 5170 __ vcmpd(saved_base, result); | |
| 5171 __ b(&do_pow, EQ); | |
| 5172 | |
| 5173 // exponent == 0.5 ? | |
| 5174 __ LoadDImmediate(result, 0.5, temp); | |
| 5175 __ vcmpd(exp, result); | |
| 5176 __ b(&do_pow, NE); | |
| 5177 | |
| 5178 // base == 0 -> return 0; | |
| 5179 __ vcmpd(base, DTMP); | |
| 5180 __ b(&return_zero, EQ); | |
| 5181 | |
| 5182 __ vsqrtd(result, saved_base); | |
| 5183 __ b(&skip_call); | |
| 5184 | |
| 5185 __ Bind(&return_zero); | |
| 5186 __ vmovd(result, DTMP); | |
| 5187 __ b(&skip_call); | |
| 5188 | |
| 5189 __ Bind(&do_pow); | |
| 5190 __ vmovd(base, saved_base); // Restore base. | |
| 5191 } | 5255 } |
| 5192 | 5256 |
| 5193 if (InputCount() == 2) { | 5257 if (InputCount() == 2) { |
| 5194 // Args must be in D0 and D1, so move arg from Q1(== D3:D2) to D1. | 5258 // Args must be in D0 and D1, so move arg from Q1(== D3:D2) to D1. |
| 5195 __ vmovd(D1, D2); | 5259 __ vmovd(D1, D2); |
| 5196 } | 5260 } |
| 5197 #if defined(ARM_FLOAT_ABI_HARD) | 5261 #if defined(ARM_FLOAT_ABI_HARD) |
| 5198 __ CallRuntime(TargetFunction(), InputCount()); | 5262 __ CallRuntime(TargetFunction(), InputCount()); |
| 5199 #else | 5263 #else |
| 5200 // If the ABI is not "hardfp", then we have to move the double arguments | 5264 // If the ABI is not "hardfp", then we have to move the double arguments |
| 5201 // to the integer registers, and take the results from the integer | 5265 // to the integer registers, and take the results from the integer |
| 5202 // registers. | 5266 // registers. |
| 5203 __ vmovrrd(R0, R1, D0); | 5267 __ vmovrrd(R0, R1, D0); |
| 5204 __ vmovrrd(R2, R3, D1); | 5268 __ vmovrrd(R2, R3, D1); |
| 5205 __ CallRuntime(TargetFunction(), InputCount()); | 5269 __ CallRuntime(TargetFunction(), InputCount()); |
| 5206 __ vmovdrr(D0, R0, R1); | 5270 __ vmovdrr(D0, R0, R1); |
| 5207 __ vmovdrr(D1, R2, R3); | 5271 __ vmovdrr(D1, R2, R3); |
| 5208 #endif | 5272 #endif |
| 5209 __ Bind(&skip_call); | |
| 5210 } | 5273 } |
| 5211 | 5274 |
| 5212 | 5275 |
| 5213 LocationSummary* ExtractNthOutputInstr::MakeLocationSummary(bool opt) const { | 5276 LocationSummary* ExtractNthOutputInstr::MakeLocationSummary(bool opt) const { |
| 5214 // Only use this instruction in optimized code. | 5277 // Only use this instruction in optimized code. |
| 5215 ASSERT(opt); | 5278 ASSERT(opt); |
| 5216 const intptr_t kNumInputs = 1; | 5279 const intptr_t kNumInputs = 1; |
| 5217 LocationSummary* summary = | 5280 LocationSummary* summary = |
| 5218 new LocationSummary(kNumInputs, 0, LocationSummary::kNoCall); | 5281 new LocationSummary(kNumInputs, 0, LocationSummary::kNoCall); |
| 5219 if (representation() == kUnboxedDouble) { | 5282 if (representation() == kUnboxedDouble) { |
| (...skipping 863 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6083 compiler->GenerateCall(token_pos(), | 6146 compiler->GenerateCall(token_pos(), |
| 6084 &label, | 6147 &label, |
| 6085 PcDescriptors::kOther, | 6148 PcDescriptors::kOther, |
| 6086 locs()); | 6149 locs()); |
| 6087 __ Drop(ArgumentCount()); // Discard arguments. | 6150 __ Drop(ArgumentCount()); // Discard arguments. |
| 6088 } | 6151 } |
| 6089 | 6152 |
| 6090 } // namespace dart | 6153 } // namespace dart |
| 6091 | 6154 |
| 6092 #endif // defined TARGET_ARCH_ARM | 6155 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |