Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(101)

Side by Side Diff: runtime/vm/intermediate_language_arm.cc

Issue 270743004: Refactor and improve code for pow. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698