| 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_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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |