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

Side by Side Diff: runtime/vm/intermediate_language_ia32.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_IA32. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32.
6 #if defined(TARGET_ARCH_IA32) 6 #if defined(TARGET_ARCH_IA32)
7 7
8 #include "vm/intermediate_language.h" 8 #include "vm/intermediate_language.h"
9 9
10 #include "vm/dart_entry.h" 10 #include "vm/dart_entry.h"
(...skipping 4882 matching lines...) Expand 10 before | Expand all | Expand 10 after
4893 // Temp index 1. 4893 // Temp index 1.
4894 result->AddTemp(Location::RegisterLocation(EAX)); 4894 result->AddTemp(Location::RegisterLocation(EAX));
4895 // Temp index 2. 4895 // Temp index 2.
4896 result->AddTemp(Location::FpuRegisterLocation(XMM4)); 4896 result->AddTemp(Location::FpuRegisterLocation(XMM4));
4897 } 4897 }
4898 result->set_out(0, Location::FpuRegisterLocation(XMM3)); 4898 result->set_out(0, Location::FpuRegisterLocation(XMM3));
4899 return result; 4899 return result;
4900 } 4900 }
4901 4901
4902 4902
4903 // Pseudo code:
4904 // if (exponent == 0.0) return 1.0;
4905 // // Speed up simple cases.
4906 // if (exponent == 1.0) return base;
4907 // if (exponent == 2.0) return base * base;
4908 // if (exponent == 3.0) return base * base * base;
4909 // if (base == 1.0) return 1.0;
4910 // if (base.isNaN || exponent.isNaN) {
4911 // return double.NAN;
4912 // }
4913 // if (base != -Infinity && exponent == 0.5) {
4914 // if (base == 0.0) return 0.0;
4915 // return sqrt(value);
4916 // }
4917 // TODO(srdjan): Move into a stub?
4918 static void InvokeDoublePow(FlowGraphCompiler* compiler,
4919 InvokeMathCFunctionInstr* instr) {
4920 ASSERT(instr->recognized_kind() == MethodRecognizer::kMathDoublePow);
4921 const intptr_t kInputCount = 2;
4922 ASSERT(instr->InputCount() == kInputCount);
4923 LocationSummary* locs = instr->locs();
4924
4925 XmmRegister base = locs->in(0).fpu_reg();
4926 XmmRegister exp = locs->in(1).fpu_reg();
4927 XmmRegister result = locs->out(0).fpu_reg();
4928 Register temp = locs->temp(InvokeMathCFunctionInstr::kObjectTempIndex).reg();
4929 XmmRegister zero_temp =
4930 locs->temp(InvokeMathCFunctionInstr::kDoubleTempIndex).fpu_reg();
4931
4932 __ xorps(zero_temp, zero_temp); // 0.0.
4933 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(1.0)));
4934 __ movsd(result, FieldAddress(temp, Double::value_offset()));
4935
4936 Label check_base, skip_call;
4937 // exponent == 0.0 -> return 1.0;
4938 __ comisd(exp, zero_temp);
4939 __ j(PARITY_EVEN, &check_base);
4940 __ j(EQUAL, &skip_call); // 'result' is 1.0.
4941
4942 // exponent == 1.0 ?
4943 __ comisd(exp, result);
4944 Label return_base;
4945 __ j(EQUAL, &return_base, Assembler::kNearJump);
4946
4947 // exponent == 2.0 ?
4948 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(2.0)));
4949 __ movsd(XMM0, FieldAddress(temp, Double::value_offset()));
4950 __ comisd(exp, XMM0);
4951 Label return_base_times_2;
4952 __ j(EQUAL, &return_base_times_2, Assembler::kNearJump);
4953
4954 // exponent == 3.0 ?
4955 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(3.0)));
4956 __ movsd(XMM0, FieldAddress(temp, Double::value_offset()));
4957 __ comisd(exp, XMM0);
4958 __ j(NOT_EQUAL, &check_base);
4959
4960 // Base times 3.
4961 __ movsd(result, base);
4962 __ mulsd(result, base);
4963 __ mulsd(result, base);
4964 __ jmp(&skip_call);
4965
4966 __ Bind(&return_base);
4967 __ movsd(result, base);
4968 __ jmp(&skip_call);
4969
4970 __ Bind(&return_base_times_2);
4971 __ movsd(result, base);
4972 __ mulsd(result, base);
4973 __ jmp(&skip_call);
4974
4975 __ Bind(&check_base);
4976 // Note: 'exp' could be NaN.
4977
4978 // base == 1.0 -> return 1.0;
4979 __ comisd(base, result);
4980 Label return_nan;
4981 __ j(PARITY_EVEN, &return_nan, Assembler::kNearJump);
4982 __ j(EQUAL, &skip_call, Assembler::kNearJump);
4983 // Note: 'base' could be NaN.
4984 __ comisd(exp, base);
4985 // Neither 'exp' nor 'base' is NaN.
4986 Label try_sqrt;
4987 __ j(PARITY_ODD, &try_sqrt, Assembler::kNearJump);
4988 // Return NaN.
4989 __ Bind(&return_nan);
4990 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(NAN)));
4991 __ movsd(result, FieldAddress(temp, Double::value_offset()));
4992 __ jmp(&skip_call);
4993
4994 Label do_pow, return_zero;
4995 __ Bind(&try_sqrt);
4996 // Before calling pow, check if we could use sqrt instead of pow.
4997 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(-INFINITY)));
4998 __ movsd(result, FieldAddress(temp, Double::value_offset()));
4999 // base == -Infinity -> call pow;
5000 __ comisd(base, result);
5001 __ j(EQUAL, &do_pow, Assembler::kNearJump);
5002
5003 // exponent == 0.5 ?
5004 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(0.5)));
5005 __ movsd(result, FieldAddress(temp, Double::value_offset()));
5006 __ comisd(exp, result);
5007 __ j(NOT_EQUAL, &do_pow, Assembler::kNearJump);
5008
5009 // base == 0 -> return 0;
5010 __ comisd(base, zero_temp);
5011 __ j(EQUAL, &return_zero, Assembler::kNearJump);
5012
5013 __ sqrtsd(result, base);
5014 __ jmp(&skip_call, Assembler::kNearJump);
5015
5016 __ Bind(&return_zero);
5017 __ movsd(result, zero_temp);
5018 __ jmp(&skip_call);
5019
5020 __ Bind(&do_pow);
5021 // Save ESP.
5022 __ movl(locs->temp(InvokeMathCFunctionInstr::kSavedSpTempIndex).reg(), ESP);
5023 __ ReserveAlignedFrameSpace(kDoubleSize * kInputCount);
5024 for (intptr_t i = 0; i < kInputCount; i++) {
5025 __ movsd(Address(ESP, kDoubleSize * i), locs->in(i).fpu_reg());
5026 }
5027 __ CallRuntime(instr->TargetFunction(), kInputCount);
5028 __ fstpl(Address(ESP, 0));
5029 __ movsd(locs->out(0).fpu_reg(), Address(ESP, 0));
5030 // Restore ESP.
5031 __ movl(ESP, locs->temp(InvokeMathCFunctionInstr::kSavedSpTempIndex).reg());
5032 __ Bind(&skip_call);
5033 }
5034
5035
4903 void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5036 void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5037 if (recognized_kind() == MethodRecognizer::kMathDoublePow) {
5038 InvokeDoublePow(compiler, this);
5039 return;
5040 }
4904 // Save ESP. 5041 // Save ESP.
4905 __ movl(locs()->temp(kSavedSpTempIndex).reg(), ESP); 5042 __ movl(locs()->temp(kSavedSpTempIndex).reg(), ESP);
4906 __ ReserveAlignedFrameSpace(kDoubleSize * InputCount()); 5043 __ ReserveAlignedFrameSpace(kDoubleSize * InputCount());
4907 for (intptr_t i = 0; i < InputCount(); i++) { 5044 for (intptr_t i = 0; i < InputCount(); i++) {
4908 __ movsd(Address(ESP, kDoubleSize * i), locs()->in(i).fpu_reg()); 5045 __ movsd(Address(ESP, kDoubleSize * i), locs()->in(i).fpu_reg());
4909 } 5046 }
4910 Label skip_call;
4911 if (recognized_kind() == MethodRecognizer::kMathDoublePow) {
4912 // Pseudo code:
4913 // if (exponent == 0.0) return 1.0;
4914 // if (base == 1.0) return 1.0;
4915 // if (base.isNaN || exponent.isNaN) {
4916 // return double.NAN;
4917 // }
4918 // if (base != -Infinity && exponent == 0.5) {
4919 // if (base == 0.0) return 0.0;
4920 // return sqrt(value);
4921 // }
4922 XmmRegister base = locs()->in(0).fpu_reg();
4923 XmmRegister exp = locs()->in(1).fpu_reg();
4924 XmmRegister result = locs()->out(0).fpu_reg();
4925 Register temp = locs()->temp(kObjectTempIndex).reg();
4926 XmmRegister zero_temp = locs()->temp(kDoubleTempIndex).fpu_reg();
4927
4928 Label try_sqrt, check_base, return_nan;
4929 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(0)));
4930 __ movsd(zero_temp, FieldAddress(temp, Double::value_offset()));
4931 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(1)));
4932 __ movsd(result, FieldAddress(temp, Double::value_offset()));
4933
4934 // exponent == 0.0 -> return 1.0;
4935 __ comisd(exp, zero_temp);
4936 __ j(PARITY_EVEN, &check_base, Assembler::kNearJump);
4937 __ j(EQUAL, &skip_call, Assembler::kNearJump); // 'result' is 1.0.
4938
4939 __ Bind(&check_base);
4940 // Note: 'exp' could be NaN.
4941
4942 // base == 1.0 -> return 1.0;
4943 __ comisd(base, result);
4944 __ j(PARITY_EVEN, &return_nan, Assembler::kNearJump);
4945 __ j(EQUAL, &skip_call, Assembler::kNearJump);
4946 // Note: 'base' could be NaN.
4947 __ comisd(exp, base);
4948 // Neither 'exp' nor 'base' is NaN.
4949 __ j(PARITY_ODD, &try_sqrt, Assembler::kNearJump);
4950 // Return NaN.
4951 __ Bind(&return_nan);
4952 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(NAN)));
4953 __ movsd(result, FieldAddress(temp, Double::value_offset()));
4954 __ jmp(&skip_call);
4955
4956 Label do_pow, return_zero;
4957 __ Bind(&try_sqrt);
4958 // Before calling pow, check if we could use sqrt instead of pow.
4959 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(-INFINITY)));
4960 __ movsd(result, FieldAddress(temp, Double::value_offset()));
4961 // base == -Infinity -> call pow;
4962 __ comisd(base, result);
4963 __ j(EQUAL, &do_pow, Assembler::kNearJump);
4964
4965 // exponent == 0.5 ?
4966 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(0.5)));
4967 __ movsd(result, FieldAddress(temp, Double::value_offset()));
4968 __ comisd(exp, result);
4969 __ j(NOT_EQUAL, &do_pow, Assembler::kNearJump);
4970
4971 // base == 0 -> return 0;
4972 __ comisd(base, zero_temp);
4973 __ j(EQUAL, &return_zero, Assembler::kNearJump);
4974
4975 __ sqrtsd(result, base);
4976 __ jmp(&skip_call, Assembler::kNearJump);
4977
4978 __ Bind(&return_zero);
4979 __ movsd(result, zero_temp);
4980 __ jmp(&skip_call);
4981
4982 __ Bind(&do_pow);
4983 }
4984 5047
4985 __ CallRuntime(TargetFunction(), InputCount()); 5048 __ CallRuntime(TargetFunction(), InputCount());
4986 __ fstpl(Address(ESP, 0)); 5049 __ fstpl(Address(ESP, 0));
4987 __ movsd(locs()->out(0).fpu_reg(), Address(ESP, 0)); 5050 __ movsd(locs()->out(0).fpu_reg(), Address(ESP, 0));
4988 __ Bind(&skip_call);
4989 // Restore ESP. 5051 // Restore ESP.
4990 __ movl(ESP, locs()->temp(kSavedSpTempIndex).reg()); 5052 __ movl(ESP, locs()->temp(kSavedSpTempIndex).reg());
4991 } 5053 }
4992 5054
4993 5055
4994 LocationSummary* ExtractNthOutputInstr::MakeLocationSummary(bool opt) const { 5056 LocationSummary* ExtractNthOutputInstr::MakeLocationSummary(bool opt) const {
4995 // Only use this instruction in optimized code. 5057 // Only use this instruction in optimized code.
4996 ASSERT(opt); 5058 ASSERT(opt);
4997 const intptr_t kNumInputs = 1; 5059 const intptr_t kNumInputs = 1;
4998 LocationSummary* summary = 5060 LocationSummary* summary =
(...skipping 1029 matching lines...) Expand 10 before | Expand all | Expand 10 after
6028 PcDescriptors::kOther, 6090 PcDescriptors::kOther,
6029 locs()); 6091 locs());
6030 __ Drop(ArgumentCount()); // Discard arguments. 6092 __ Drop(ArgumentCount()); // Discard arguments.
6031 } 6093 }
6032 6094
6033 } // namespace dart 6095 } // namespace dart
6034 6096
6035 #undef __ 6097 #undef __
6036 6098
6037 #endif // defined TARGET_ARCH_IA32 6099 #endif // defined TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698