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

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
« no previous file with comments | « runtime/vm/intermediate_language.h ('k') | runtime/vm/intermediate_language_arm64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 5080 matching lines...) Expand 10 before | Expand all | Expand 10 after
5091 ASSERT((InputCount() == 1) || (InputCount() == 2)); 5091 ASSERT((InputCount() == 1) || (InputCount() == 2));
5092 const intptr_t kNumTemps = 0; 5092 const intptr_t kNumTemps = 0;
5093 LocationSummary* result = 5093 LocationSummary* result =
5094 new LocationSummary(InputCount(), kNumTemps, LocationSummary::kCall); 5094 new LocationSummary(InputCount(), kNumTemps, LocationSummary::kCall);
5095 result->set_in(0, Location::FpuRegisterLocation(Q0)); 5095 result->set_in(0, Location::FpuRegisterLocation(Q0));
5096 if (InputCount() == 2) { 5096 if (InputCount() == 2) {
5097 result->set_in(1, Location::FpuRegisterLocation(Q1)); 5097 result->set_in(1, Location::FpuRegisterLocation(Q1));
5098 } 5098 }
5099 if (recognized_kind() == MethodRecognizer::kMathDoublePow) { 5099 if (recognized_kind() == MethodRecognizer::kMathDoublePow) {
5100 result->AddTemp(Location::RegisterLocation(R2)); 5100 result->AddTemp(Location::RegisterLocation(R2));
5101 result->AddTemp(Location::FpuRegisterLocation(Q2));
5102 } 5101 }
5103 #if !defined(ARM_FLOAT_ABI_HARD) 5102 #if !defined(ARM_FLOAT_ABI_HARD)
5104 result->AddTemp(Location::RegisterLocation(R0)); 5103 result->AddTemp(Location::RegisterLocation(R0));
5105 result->AddTemp(Location::RegisterLocation(R1)); 5104 result->AddTemp(Location::RegisterLocation(R1));
5106 // Check if R2 is already added. 5105 // Check if R2 is already added.
5107 if (recognized_kind() != MethodRecognizer::kMathDoublePow) { 5106 if (recognized_kind() != MethodRecognizer::kMathDoublePow) {
5108 result->AddTemp(Location::RegisterLocation(R2)); 5107 result->AddTemp(Location::RegisterLocation(R2));
5109 } 5108 }
5110 result->AddTemp(Location::RegisterLocation(R3)); 5109 result->AddTemp(Location::RegisterLocation(R3));
5111 #endif 5110 #endif
5112 result->set_out(0, Location::FpuRegisterLocation(Q0)); 5111 result->set_out(0, Location::FpuRegisterLocation(Q0));
5113 return result; 5112 return result;
5114 } 5113 }
5115 5114
5116 5115
5116 // Pseudo code:
5117 // if (exponent == 0.0) return 1.0;
5118 // // Speed up simple cases.
5119 // if (exponent == 1.0) return base;
5120 // if (exponent == 2.0) return base * base;
5121 // if (exponent == 3.0) return base * base * base;
5122 // if (base == 1.0) return 1.0;
5123 // if (base.isNaN || exponent.isNaN) {
5124 // return double.NAN;
5125 // }
5126 // if (base != -Infinity && exponent == 0.5) {
5127 // if (base == 0.0) return 0.0;
5128 // return sqrt(value);
5129 // }
5130 // TODO(srdjan): Move into a stub?
5131 static void InvokeDoublePow(FlowGraphCompiler* compiler,
5132 InvokeMathCFunctionInstr* instr) {
5133 ASSERT(instr->recognized_kind() == MethodRecognizer::kMathDoublePow);
5134 const intptr_t kInputCount = 2;
5135 ASSERT(instr->InputCount() == kInputCount);
5136 LocationSummary* locs = instr->locs();
5137
5138 const DRegister base = EvenDRegisterOf(locs->in(0).fpu_reg());
5139 const DRegister exp = EvenDRegisterOf(locs->in(1).fpu_reg());
5140 const DRegister result = EvenDRegisterOf(locs->out(0).fpu_reg());
5141 const Register temp = locs->temp(0).reg();
5142 const DRegister saved_base = OddDRegisterOf(locs->in(0).fpu_reg());
5143 ASSERT((base == result) && (result != saved_base));
5144
5145 Label skip_call, try_sqrt, check_base, return_nan;
5146 __ vmovd(saved_base, base);
5147 __ LoadDImmediate(result, 1.0, temp);
5148 // exponent == 0.0 -> return 1.0;
5149 __ vcmpdz(exp);
5150 __ vmstat();
5151 __ b(&check_base, VS); // NaN -> check base.
5152 __ b(&skip_call, EQ); // exp is 0.0, result is 1.0.
5153
5154 // exponent == 1.0 ?
5155 __ vcmpd(exp, result);
5156 __ vmstat();
5157 Label return_base;
5158 __ b(&return_base, EQ);
5159
5160 // exponent == 2.0 ?
5161 __ LoadDImmediate(DTMP, 2.0, temp);
5162 __ vcmpd(exp, DTMP);
5163 __ vmstat();
5164 Label return_base_times_2;
5165 __ b(&return_base_times_2, EQ);
5166
5167 // exponent == 3.0 ?
5168 __ LoadDImmediate(DTMP, 3.0, temp);
5169 __ vcmpd(exp, DTMP);
5170 __ vmstat();
5171 __ b(&check_base, NE);
5172
5173 // base_times_3.
5174 __ vmuld(result, saved_base, saved_base);
5175 __ vmuld(result, result, saved_base);
5176 __ b(&skip_call);
5177
5178 __ Bind(&return_base);
5179 __ vmovd(result, saved_base);
5180 __ b(&skip_call);
5181
5182 __ Bind(&return_base_times_2);
5183 __ vmuld(result, saved_base, saved_base);
5184 __ b(&skip_call);
5185
5186 __ Bind(&check_base);
5187 // Note: 'exp' could be NaN.
5188 // base == 1.0 -> return 1.0;
5189 __ vcmpd(saved_base, result);
5190 __ vmstat();
5191 __ b(&return_nan, VS);
5192 __ b(&skip_call, EQ); // base is 1.0, result is 1.0.
5193
5194 __ vcmpd(saved_base, exp);
5195 __ b(&try_sqrt, VC); // // Neither 'exp' nor 'base' is NaN.
5196
5197 __ Bind(&return_nan);
5198 __ LoadDImmediate(result, NAN, temp);
5199 __ b(&skip_call);
5200
5201 Label do_pow, return_zero;
5202 __ Bind(&try_sqrt);
5203
5204 // Before calling pow, check if we could use sqrt instead of pow.
5205 __ LoadDImmediate(result, -INFINITY, temp);
5206
5207 // base == -Infinity -> call pow;
5208 __ vcmpd(saved_base, result);
5209 __ b(&do_pow, EQ);
5210
5211 // exponent == 0.5 ?
5212 __ LoadDImmediate(result, 0.5, temp);
5213 __ vcmpd(exp, result);
5214 __ b(&do_pow, NE);
5215
5216 // base == 0 -> return 0;
5217 __ vcmpdz(base);
5218 __ b(&return_zero, EQ);
5219
5220 __ vsqrtd(result, saved_base);
5221 __ b(&skip_call);
5222
5223 __ Bind(&return_zero);
5224 __ LoadDImmediate(result, 0.0, temp);
5225 __ b(&skip_call);
5226
5227 __ Bind(&do_pow);
5228 __ vmovd(base, saved_base); // Restore base.
5229
5230 // Args must be in D0 and D1, so move arg from Q1(== D3:D2) to D1.
5231 __ vmovd(D1, D2);
5232 #if defined(ARM_FLOAT_ABI_HARD)
5233 __ CallRuntime(instr->TargetFunction(), kInputCount);
5234 #else
5235 // If the ABI is not "hardfp", then we have to move the double arguments
5236 // to the integer registers, and take the results from the integer
5237 // registers.
5238 __ vmovrrd(R0, R1, D0);
5239 __ vmovrrd(R2, R3, D1);
5240 __ CallRuntime(instr->TargetFunction(), kInputCount);
5241 __ vmovdrr(D0, R0, R1);
5242 __ vmovdrr(D1, R2, R3);
5243 #endif
5244 __ Bind(&skip_call);
5245 }
5246
5247
5117 void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5248 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) { 5249 if (recognized_kind() == MethodRecognizer::kMathDoublePow) {
5121 // Pseudo code: 5250 InvokeDoublePow(compiler, this);
5122 // if (exponent == 0.0) return 1.0; 5251 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 } 5252 }
5192 5253
5193 if (InputCount() == 2) { 5254 if (InputCount() == 2) {
5194 // Args must be in D0 and D1, so move arg from Q1(== D3:D2) to D1. 5255 // Args must be in D0 and D1, so move arg from Q1(== D3:D2) to D1.
5195 __ vmovd(D1, D2); 5256 __ vmovd(D1, D2);
5196 } 5257 }
5197 #if defined(ARM_FLOAT_ABI_HARD) 5258 #if defined(ARM_FLOAT_ABI_HARD)
5198 __ CallRuntime(TargetFunction(), InputCount()); 5259 __ CallRuntime(TargetFunction(), InputCount());
5199 #else 5260 #else
5200 // If the ABI is not "hardfp", then we have to move the double arguments 5261 // 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 5262 // to the integer registers, and take the results from the integer
5202 // registers. 5263 // registers.
5203 __ vmovrrd(R0, R1, D0); 5264 __ vmovrrd(R0, R1, D0);
5204 __ vmovrrd(R2, R3, D1); 5265 __ vmovrrd(R2, R3, D1);
5205 __ CallRuntime(TargetFunction(), InputCount()); 5266 __ CallRuntime(TargetFunction(), InputCount());
5206 __ vmovdrr(D0, R0, R1); 5267 __ vmovdrr(D0, R0, R1);
5207 __ vmovdrr(D1, R2, R3); 5268 __ vmovdrr(D1, R2, R3);
5208 #endif 5269 #endif
5209 __ Bind(&skip_call);
5210 } 5270 }
5211 5271
5212 5272
5213 LocationSummary* ExtractNthOutputInstr::MakeLocationSummary(bool opt) const { 5273 LocationSummary* ExtractNthOutputInstr::MakeLocationSummary(bool opt) const {
5214 // Only use this instruction in optimized code. 5274 // Only use this instruction in optimized code.
5215 ASSERT(opt); 5275 ASSERT(opt);
5216 const intptr_t kNumInputs = 1; 5276 const intptr_t kNumInputs = 1;
5217 LocationSummary* summary = 5277 LocationSummary* summary =
5218 new LocationSummary(kNumInputs, 0, LocationSummary::kNoCall); 5278 new LocationSummary(kNumInputs, 0, LocationSummary::kNoCall);
5219 if (representation() == kUnboxedDouble) { 5279 if (representation() == kUnboxedDouble) {
(...skipping 863 matching lines...) Expand 10 before | Expand all | Expand 10 after
6083 compiler->GenerateCall(token_pos(), 6143 compiler->GenerateCall(token_pos(),
6084 &label, 6144 &label,
6085 PcDescriptors::kOther, 6145 PcDescriptors::kOther,
6086 locs()); 6146 locs());
6087 __ Drop(ArgumentCount()); // Discard arguments. 6147 __ Drop(ArgumentCount()); // Discard arguments.
6088 } 6148 }
6089 6149
6090 } // namespace dart 6150 } // namespace dart
6091 6151
6092 #endif // defined TARGET_ARCH_ARM 6152 #endif // defined TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « runtime/vm/intermediate_language.h ('k') | runtime/vm/intermediate_language_arm64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698