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

Side by Side Diff: runtime/vm/intermediate_language_x64.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_mips.cc ('k') | no next file » | 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_X64. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64.
6 #if defined(TARGET_ARCH_X64) 6 #if defined(TARGET_ARCH_X64)
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 4780 matching lines...) Expand 10 before | Expand all | Expand 10 after
4791 // Temp index 1. 4791 // Temp index 1.
4792 result->AddTemp(Location::RegisterLocation(RAX)); 4792 result->AddTemp(Location::RegisterLocation(RAX));
4793 // Temp index 2. 4793 // Temp index 2.
4794 result->AddTemp(Location::FpuRegisterLocation(XMM4)); 4794 result->AddTemp(Location::FpuRegisterLocation(XMM4));
4795 } 4795 }
4796 result->set_out(0, Location::FpuRegisterLocation(XMM3)); 4796 result->set_out(0, Location::FpuRegisterLocation(XMM3));
4797 return result; 4797 return result;
4798 } 4798 }
4799 4799
4800 4800
4801 // Pseudo code:
4802 // if (exponent == 0.0) return 1.0;
4803 // // Speed up simple cases.
4804 // if (exponent == 1.0) return base;
4805 // if (exponent == 2.0) return base * base;
4806 // if (exponent == 3.0) return base * base * base;
4807 // if (base == 1.0) return 1.0;
4808 // if (base.isNaN || exponent.isNaN) {
4809 // return double.NAN;
4810 // }
4811 // if (base != -Infinity && exponent == 0.5) {
4812 // if (base == 0.0) return 0.0;
4813 // return sqrt(value);
4814 // }
4815 // TODO(srdjan): Move into a stub?
4816 static void InvokeDoublePow(FlowGraphCompiler* compiler,
4817 InvokeMathCFunctionInstr* instr) {
4818 ASSERT(instr->recognized_kind() == MethodRecognizer::kMathDoublePow);
4819 const intptr_t kInputCount = 2;
4820 ASSERT(instr->InputCount() == kInputCount);
4821 LocationSummary* locs = instr->locs();
4822
4823 XmmRegister base = locs->in(0).fpu_reg();
4824 XmmRegister exp = locs->in(1).fpu_reg();
4825 XmmRegister result = locs->out(0).fpu_reg();
4826 Register temp =
4827 locs->temp(InvokeMathCFunctionInstr::kObjectTempIndex).reg();
4828 XmmRegister zero_temp =
4829 locs->temp(InvokeMathCFunctionInstr::kDoubleTempIndex).fpu_reg();
4830
4831 __ xorps(zero_temp, zero_temp);
4832 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(1)), PP);
4833 __ movsd(result, FieldAddress(temp, Double::value_offset()));
4834
4835 Label check_base, skip_call;
4836 // exponent == 0.0 -> return 1.0;
4837 __ comisd(exp, zero_temp);
4838 __ j(PARITY_EVEN, &check_base, Assembler::kNearJump);
4839 __ j(EQUAL, &skip_call); // 'result' is 1.0.
4840
4841 // exponent == 1.0 ?
4842 __ comisd(exp, result);
4843 Label return_base;
4844 __ j(EQUAL, &return_base, Assembler::kNearJump);
4845
4846 // exponent == 2.0 ?
4847 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(2.0)), PP);
4848 __ movsd(XMM0, FieldAddress(temp, Double::value_offset()));
4849 __ comisd(exp, XMM0);
4850 Label return_base_times_2;
4851 __ j(EQUAL, &return_base_times_2, Assembler::kNearJump);
4852
4853 // exponent == 3.0 ?
4854 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(3.0)), PP);
4855 __ movsd(XMM0, FieldAddress(temp, Double::value_offset()));
4856 __ comisd(exp, XMM0);
4857 __ j(NOT_EQUAL, &check_base);
4858
4859 // Base times 3.
4860 __ movsd(result, base);
4861 __ mulsd(result, base);
4862 __ mulsd(result, base);
4863 __ jmp(&skip_call);
4864
4865 __ Bind(&return_base);
4866 __ movsd(result, base);
4867 __ jmp(&skip_call);
4868
4869 __ Bind(&return_base_times_2);
4870 __ movsd(result, base);
4871 __ mulsd(result, base);
4872 __ jmp(&skip_call);
4873
4874 __ Bind(&check_base);
4875 // Note: 'exp' could be NaN.
4876
4877 Label return_nan;
4878 // base == 1.0 -> return 1.0;
4879 __ comisd(base, result);
4880 __ j(PARITY_EVEN, &return_nan, Assembler::kNearJump);
4881 __ j(EQUAL, &skip_call, Assembler::kNearJump);
4882 // Note: 'base' could be NaN.
4883 __ comisd(exp, base);
4884 // Neither 'exp' nor 'base' is NaN.
4885 Label try_sqrt;
4886 __ j(PARITY_ODD, &try_sqrt, Assembler::kNearJump);
4887 // Return NaN.
4888 __ Bind(&return_nan);
4889 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(NAN)), PP);
4890 __ movsd(result, FieldAddress(temp, Double::value_offset()));
4891 __ jmp(&skip_call);
4892
4893 Label do_pow, return_zero;
4894 __ Bind(&try_sqrt);
4895 // Before calling pow, check if we could use sqrt instead of pow.
4896 __ LoadObject(temp,
4897 Double::ZoneHandle(Double::NewCanonical(-INFINITY)), PP);
4898 __ movsd(result, FieldAddress(temp, Double::value_offset()));
4899 // base == -Infinity -> call pow;
4900 __ comisd(base, result);
4901 __ j(EQUAL, &do_pow, Assembler::kNearJump);
4902
4903 // exponent == 0.5 ?
4904 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(0.5)), PP);
4905 __ movsd(result, FieldAddress(temp, Double::value_offset()));
4906 __ comisd(exp, result);
4907 __ j(NOT_EQUAL, &do_pow, Assembler::kNearJump);
4908
4909 // base == 0 -> return 0;
4910 __ comisd(base, zero_temp);
4911 __ j(EQUAL, &return_zero, Assembler::kNearJump);
4912
4913 __ sqrtsd(result, base);
4914 __ jmp(&skip_call, Assembler::kNearJump);
4915
4916 __ Bind(&return_zero);
4917 __ movsd(result, zero_temp);
4918 __ jmp(&skip_call);
4919
4920 __ Bind(&do_pow);
4921
4922 // Save RSP.
4923 __ movq(locs->temp(InvokeMathCFunctionInstr::kSavedSpTempIndex).reg(), RSP);
4924 __ ReserveAlignedFrameSpace(0);
4925 __ movaps(XMM0, locs->in(0).fpu_reg());
4926 ASSERT(locs->in(1).fpu_reg() == XMM1);
4927
4928 __ CallRuntime(instr->TargetFunction(), kInputCount);
4929 __ movaps(locs->out(0).fpu_reg(), XMM0);
4930 // Restore RSP.
4931 __ movq(RSP, locs->temp(InvokeMathCFunctionInstr::kSavedSpTempIndex).reg());
4932 __ Bind(&skip_call);
4933 }
4934
4935
4801 void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4936 void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4937 if (recognized_kind() == MethodRecognizer::kMathDoublePow) {
4938 InvokeDoublePow(compiler, this);
4939 return;
4940 }
4802 // Save RSP. 4941 // Save RSP.
4803 __ movq(locs()->temp(kSavedSpTempIndex).reg(), RSP); 4942 __ movq(locs()->temp(kSavedSpTempIndex).reg(), RSP);
4804 __ ReserveAlignedFrameSpace(0); 4943 __ ReserveAlignedFrameSpace(0);
4805 __ movaps(XMM0, locs()->in(0).fpu_reg()); 4944 __ movaps(XMM0, locs()->in(0).fpu_reg());
4806 if (InputCount() == 2) { 4945 if (InputCount() == 2) {
4807 ASSERT(locs()->in(1).fpu_reg() == XMM1); 4946 ASSERT(locs()->in(1).fpu_reg() == XMM1);
4808 } 4947 }
4809 4948
4810 Label skip_call;
4811 if (recognized_kind() == MethodRecognizer::kMathDoublePow) {
4812 // Pseudo code:
4813 // if (exponent == 0.0) return 1.0;
4814 // if (base == 1.0) return 1.0;
4815 // if (base.isNaN || exponent.isNaN) {
4816 // return double.NAN;
4817 // }
4818 // if (base != -Infinity && exponent == 0.5) {
4819 // if (base == 0.0) return 0.0;
4820 // return sqrt(value);
4821 // }
4822 XmmRegister base = locs()->in(0).fpu_reg();
4823 XmmRegister exp = locs()->in(1).fpu_reg();
4824 XmmRegister result = locs()->out(0).fpu_reg();
4825 Register temp = locs()->temp(kObjectTempIndex).reg();
4826 XmmRegister zero_temp = locs()->temp(kDoubleTempIndex).fpu_reg();
4827
4828 Label try_sqrt, check_base, return_nan;
4829 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(0)), PP);
4830 __ movsd(zero_temp, FieldAddress(temp, Double::value_offset()));
4831 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(1)), PP);
4832 __ movsd(result, FieldAddress(temp, Double::value_offset()));
4833
4834 // exponent == 0.0 -> return 1.0;
4835 __ comisd(exp, zero_temp);
4836 __ j(PARITY_EVEN, &check_base, Assembler::kNearJump);
4837 __ j(EQUAL, &skip_call, Assembler::kNearJump); // 'result' is 1.0.
4838
4839 __ Bind(&check_base);
4840 // Note: 'exp' could be NaN.
4841
4842 // base == 1.0 -> return 1.0;
4843 __ comisd(base, result);
4844 __ j(PARITY_EVEN, &return_nan, Assembler::kNearJump);
4845 __ j(EQUAL, &skip_call, Assembler::kNearJump);
4846 // Note: 'base' could be NaN.
4847 __ comisd(exp, base);
4848 // Neither 'exp' nor 'base' is NaN.
4849 __ j(PARITY_ODD, &try_sqrt, Assembler::kNearJump);
4850 // Return NaN.
4851 __ Bind(&return_nan);
4852 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(NAN)), PP);
4853 __ movsd(result, FieldAddress(temp, Double::value_offset()));
4854 __ jmp(&skip_call);
4855
4856 Label do_pow, return_zero;
4857 __ Bind(&try_sqrt);
4858 // Before calling pow, check if we could use sqrt instead of pow.
4859 __ LoadObject(temp,
4860 Double::ZoneHandle(Double::NewCanonical(-INFINITY)), PP);
4861 __ movsd(result, FieldAddress(temp, Double::value_offset()));
4862 // base == -Infinity -> call pow;
4863 __ comisd(base, result);
4864 __ j(EQUAL, &do_pow, Assembler::kNearJump);
4865
4866 // exponent == 0.5 ?
4867 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(0.5)), PP);
4868 __ movsd(result, FieldAddress(temp, Double::value_offset()));
4869 __ comisd(exp, result);
4870 __ j(NOT_EQUAL, &do_pow, Assembler::kNearJump);
4871
4872 // base == 0 -> return 0;
4873 __ comisd(base, zero_temp);
4874 __ j(EQUAL, &return_zero, Assembler::kNearJump);
4875
4876 __ sqrtsd(result, base);
4877 __ jmp(&skip_call, Assembler::kNearJump);
4878
4879 __ Bind(&return_zero);
4880 __ movsd(result, zero_temp);
4881 __ jmp(&skip_call);
4882
4883 __ Bind(&do_pow);
4884 }
4885 __ CallRuntime(TargetFunction(), InputCount()); 4949 __ CallRuntime(TargetFunction(), InputCount());
4886 __ movaps(locs()->out(0).fpu_reg(), XMM0); 4950 __ movaps(locs()->out(0).fpu_reg(), XMM0);
4887 __ Bind(&skip_call);
4888 // Restore RSP. 4951 // Restore RSP.
4889 __ movq(RSP, locs()->temp(kSavedSpTempIndex).reg()); 4952 __ movq(RSP, locs()->temp(kSavedSpTempIndex).reg());
4890 } 4953 }
4891 4954
4892 4955
4893 LocationSummary* ExtractNthOutputInstr::MakeLocationSummary(bool opt) const { 4956 LocationSummary* ExtractNthOutputInstr::MakeLocationSummary(bool opt) const {
4894 // Only use this instruction in optimized code. 4957 // Only use this instruction in optimized code.
4895 ASSERT(opt); 4958 ASSERT(opt);
4896 const intptr_t kNumInputs = 1; 4959 const intptr_t kNumInputs = 1;
4897 LocationSummary* summary = 4960 LocationSummary* summary =
(...skipping 711 matching lines...) Expand 10 before | Expand all | Expand 10 after
5609 PcDescriptors::kOther, 5672 PcDescriptors::kOther,
5610 locs()); 5673 locs());
5611 __ Drop(ArgumentCount()); // Discard arguments. 5674 __ Drop(ArgumentCount()); // Discard arguments.
5612 } 5675 }
5613 5676
5614 } // namespace dart 5677 } // namespace dart
5615 5678
5616 #undef __ 5679 #undef __
5617 5680
5618 #endif // defined TARGET_ARCH_X64 5681 #endif // defined TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « runtime/vm/intermediate_language_mips.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698