| OLD | NEW |
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/assembler.h" | 5 #include "src/assembler.h" |
| 6 #include "src/codegen.h" | 6 #include "src/codegen.h" |
| 7 #include "src/compiler/linkage.h" | 7 #include "src/compiler/linkage.h" |
| 8 #include "src/compiler/machine-type.h" | 8 #include "src/compiler/machine-type.h" |
| 9 #include "src/compiler/raw-machine-assembler.h" | 9 #include "src/compiler/raw-machine-assembler.h" |
| 10 #include "src/register-configuration.h" |
| 10 | 11 |
| 11 #include "test/cctest/cctest.h" | 12 #include "test/cctest/cctest.h" |
| 12 #include "test/cctest/compiler/codegen-tester.h" | 13 #include "test/cctest/compiler/codegen-tester.h" |
| 13 #include "test/cctest/compiler/graph-builder-tester.h" | 14 #include "test/cctest/compiler/graph-builder-tester.h" |
| 14 #include "test/cctest/compiler/value-helper.h" | 15 #include "test/cctest/compiler/value-helper.h" |
| 15 | 16 |
| 16 using namespace v8::base; | 17 using namespace v8::base; |
| 17 using namespace v8::internal; | 18 using namespace v8::internal; |
| 18 using namespace v8::internal::compiler; | 19 using namespace v8::internal::compiler; |
| 19 | 20 |
| 20 typedef RawMachineAssembler::Label MLabel; | 21 typedef RawMachineAssembler::Label MLabel; |
| 21 | 22 |
| 22 #if V8_TARGET_ARCH_ARM64 | 23 #if V8_TARGET_ARCH_ARM64 |
| 23 // TODO(titzer): fix native stack parameters on arm64 | 24 // TODO(titzer): fix native stack parameters on arm64 |
| 24 #define DISABLE_NATIVE_STACK_PARAMS true | 25 #define DISABLE_NATIVE_STACK_PARAMS true |
| 25 #else | 26 #else |
| 26 #define DISABLE_NATIVE_STACK_PARAMS false | 27 #define DISABLE_NATIVE_STACK_PARAMS false |
| 27 #endif | 28 #endif |
| 28 | 29 |
| 29 namespace { | 30 namespace { |
| 30 typedef float float32; | 31 typedef float float32; |
| 31 typedef double float64; | 32 typedef double float64; |
| 32 | 33 |
| 33 // Picks a representative pair of integers from the given range. | 34 // Picks a representative pair of integers from the given range. |
| 34 // If there are less than {max_pairs} possible pairs, do them all, otherwise try | 35 // If there are less than {max_pairs} possible pairs, do them all, otherwise try |
| 35 // to select a representative set. | 36 // to select a representative set. |
| 36 class Pairs { | 37 class Pairs { |
| 37 public: | 38 public: |
| 38 Pairs(int max_pairs, int range) | 39 Pairs(int max_pairs, int range, const int* codes) |
| 39 : range_(range), | 40 : range_(range), |
| 41 codes_(codes), |
| 40 max_pairs_(std::min(max_pairs, range_ * range_)), | 42 max_pairs_(std::min(max_pairs, range_ * range_)), |
| 41 counter_(0) {} | 43 counter_(0) {} |
| 42 | 44 |
| 43 bool More() { return counter_ < max_pairs_; } | 45 bool More() { return counter_ < max_pairs_; } |
| 44 | 46 |
| 45 void Next(int* r0, int* r1, bool same_is_ok) { | 47 void Next(int* r0, int* r1, bool same_is_ok) { |
| 46 do { | 48 do { |
| 47 // Find the next pair. | 49 // Find the next pair. |
| 48 if (exhaustive()) { | 50 if (exhaustive()) { |
| 49 *r0 = counter_ % range_; | 51 *r0 = codes_[counter_ % range_]; |
| 50 *r1 = counter_ / range_; | 52 *r1 = codes_[counter_ / range_]; |
| 51 } else { | 53 } else { |
| 52 // Try each integer at least once for both r0 and r1. | 54 // Try each integer at least once for both r0 and r1. |
| 53 int index = counter_ / 2; | 55 int index = counter_ / 2; |
| 54 if (counter_ & 1) { | 56 if (counter_ & 1) { |
| 55 *r0 = index % range_; | 57 *r0 = codes_[index % range_]; |
| 56 *r1 = index / range_; | 58 *r1 = codes_[index / range_]; |
| 57 } else { | 59 } else { |
| 58 *r1 = index % range_; | 60 *r1 = codes_[index % range_]; |
| 59 *r0 = index / range_; | 61 *r0 = codes_[index / range_]; |
| 60 } | 62 } |
| 61 } | 63 } |
| 62 counter_++; | 64 counter_++; |
| 63 if (same_is_ok) break; | 65 if ((same_is_ok) || (*r0 != *r1)) break; |
| 64 if (*r0 == *r1) { | 66 if (counter_ == max_pairs_) { |
| 65 if (counter_ >= max_pairs_) { | 67 // For the last hurrah, reg#0 with reg#n-1 |
| 66 // For the last hurrah, reg#0 with reg#n-1 | 68 *r0 = codes_[0]; |
| 67 *r0 = 0; | 69 *r1 = codes_[range_ - 1]; |
| 68 *r1 = range_ - 1; | 70 break; |
| 69 break; | |
| 70 } | |
| 71 } | 71 } |
| 72 } while (true); | 72 } while (true); |
| 73 | |
| 74 DCHECK(*r0 >= 0 && *r0 < range_); | |
| 75 DCHECK(*r1 >= 0 && *r1 < range_); | |
| 76 } | 73 } |
| 77 | 74 |
| 78 private: | 75 private: |
| 79 int range_; | 76 int range_; |
| 77 const int* codes_; |
| 80 int max_pairs_; | 78 int max_pairs_; |
| 81 int counter_; | 79 int counter_; |
| 82 bool exhaustive() { return max_pairs_ == (range_ * range_); } | 80 bool exhaustive() { return max_pairs_ == (range_ * range_); } |
| 83 }; | 81 }; |
| 84 | 82 |
| 85 | 83 |
| 86 // Pairs of general purpose registers. | 84 // Pairs of general purpose registers. |
| 87 class RegisterPairs : public Pairs { | 85 class RegisterPairs : public Pairs { |
| 88 public: | 86 public: |
| 89 RegisterPairs() : Pairs(100, Register::kMaxNumAllocatableRegisters) {} | 87 RegisterPairs() |
| 88 : Pairs( |
| 89 100, RegisterConfiguration::ArchDefault() |
| 90 ->num_allocatable_general_registers(), |
| 91 RegisterConfiguration::ArchDefault()->allocatable_general_codes()) { |
| 92 } |
| 90 }; | 93 }; |
| 91 | 94 |
| 92 | 95 |
| 93 // Pairs of double registers. | 96 // Pairs of double registers. |
| 94 class Float32RegisterPairs : public Pairs { | 97 class Float32RegisterPairs : public Pairs { |
| 95 public: | 98 public: |
| 96 Float32RegisterPairs() | 99 Float32RegisterPairs() |
| 97 : Pairs(100, DoubleRegister::NumAllocatableAliasedRegisters()) {} | 100 : Pairs( |
| 101 100, RegisterConfiguration::ArchDefault() |
| 102 ->num_allocatable_aliased_double_registers(), |
| 103 RegisterConfiguration::ArchDefault()->allocatable_double_codes()) {} |
| 98 }; | 104 }; |
| 99 | 105 |
| 100 | 106 |
| 101 // Pairs of double registers. | 107 // Pairs of double registers. |
| 102 class Float64RegisterPairs : public Pairs { | 108 class Float64RegisterPairs : public Pairs { |
| 103 public: | 109 public: |
| 104 Float64RegisterPairs() | 110 Float64RegisterPairs() |
| 105 : Pairs(100, DoubleRegister::NumAllocatableAliasedRegisters()) {} | 111 : Pairs( |
| 112 100, RegisterConfiguration::ArchDefault() |
| 113 ->num_allocatable_aliased_double_registers(), |
| 114 RegisterConfiguration::ArchDefault()->allocatable_double_codes()) {} |
| 106 }; | 115 }; |
| 107 | 116 |
| 108 | 117 |
| 109 // Helper for allocating either an GP or FP reg, or the next stack slot. | 118 // Helper for allocating either an GP or FP reg, or the next stack slot. |
| 110 struct Allocator { | 119 struct Allocator { |
| 111 Allocator(int* gp, int gpc, int* fp, int fpc) | 120 Allocator(int* gp, int gpc, int* fp, int fpc) |
| 112 : gp_count(gpc), | 121 : gp_count(gpc), |
| 113 gp_offset(0), | 122 gp_offset(0), |
| 114 gp_regs(gp), | 123 gp_regs(gp), |
| 115 fp_count(fpc), | 124 fp_count(fpc), |
| (...skipping 501 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 617 Allocator params(parray, 2, nullptr, 0); | 626 Allocator params(parray, 2, nullptr, 0); |
| 618 Allocator rets(rarray, 1, nullptr, 0); | 627 Allocator rets(rarray, 1, nullptr, 0); |
| 619 RegisterConfig config(params, rets); | 628 RegisterConfig config(params, rets); |
| 620 CallDescriptor* desc = config.Create(&zone, &sig); | 629 CallDescriptor* desc = config.Create(&zone, &sig); |
| 621 TestInt32Sub(desc); | 630 TestInt32Sub(desc); |
| 622 } | 631 } |
| 623 } | 632 } |
| 624 | 633 |
| 625 | 634 |
| 626 // Separate tests for parallelization. | 635 // Separate tests for parallelization. |
| 627 #define TEST_INT32_SUB_WITH_RET(x) \ | 636 #define TEST_INT32_SUB_WITH_RET(x) \ |
| 628 TEST(Run_Int32Sub_all_allocatable_pairs_##x) { \ | 637 TEST(Run_Int32Sub_all_allocatable_pairs_##x) { \ |
| 629 if (Register::kMaxNumAllocatableRegisters > x) Test_RunInt32SubWithRet(x); \ | 638 if (x < Register::kNumRegisters && \ |
| 639 Register::from_code(x).IsAllocatable()) { \ |
| 640 Test_RunInt32SubWithRet(x); \ |
| 641 } \ |
| 630 } | 642 } |
| 631 | 643 |
| 632 | 644 |
| 633 TEST_INT32_SUB_WITH_RET(0) | 645 TEST_INT32_SUB_WITH_RET(0) |
| 634 TEST_INT32_SUB_WITH_RET(1) | 646 TEST_INT32_SUB_WITH_RET(1) |
| 635 TEST_INT32_SUB_WITH_RET(2) | 647 TEST_INT32_SUB_WITH_RET(2) |
| 636 TEST_INT32_SUB_WITH_RET(3) | 648 TEST_INT32_SUB_WITH_RET(3) |
| 637 TEST_INT32_SUB_WITH_RET(4) | 649 TEST_INT32_SUB_WITH_RET(4) |
| 638 TEST_INT32_SUB_WITH_RET(5) | 650 TEST_INT32_SUB_WITH_RET(5) |
| 639 TEST_INT32_SUB_WITH_RET(6) | 651 TEST_INT32_SUB_WITH_RET(6) |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 717 for (int i = 0; i < ParamCount(desc); i++) { | 729 for (int i = 0; i < ParamCount(desc); i++) { |
| 718 result += static_cast<uint32_t>(input[i]) * coeff[i]; | 730 result += static_cast<uint32_t>(input[i]) * coeff[i]; |
| 719 } | 731 } |
| 720 return static_cast<int32_t>(result); | 732 return static_cast<int32_t>(result); |
| 721 } | 733 } |
| 722 | 734 |
| 723 | 735 |
| 724 static void Test_Int32_WeightedSum_of_size(int count) { | 736 static void Test_Int32_WeightedSum_of_size(int count) { |
| 725 if (DISABLE_NATIVE_STACK_PARAMS) return; | 737 if (DISABLE_NATIVE_STACK_PARAMS) return; |
| 726 Int32Signature sig(count); | 738 Int32Signature sig(count); |
| 727 for (int p0 = 0; p0 < Register::kMaxNumAllocatableRegisters; p0++) { | 739 for (int p0 = 0; p0 < Register::kNumRegisters; p0++) { |
| 728 Zone zone; | 740 if (Register::from_code(p0).IsAllocatable()) { |
| 741 Zone zone; |
| 729 | 742 |
| 730 int parray[] = {p0}; | 743 int parray[] = {p0}; |
| 731 int rarray[] = {0}; | 744 int rarray[] = {0}; |
| 732 Allocator params(parray, 1, nullptr, 0); | 745 Allocator params(parray, 1, nullptr, 0); |
| 733 Allocator rets(rarray, 1, nullptr, 0); | 746 Allocator rets(rarray, 1, nullptr, 0); |
| 734 RegisterConfig config(params, rets); | 747 RegisterConfig config(params, rets); |
| 735 CallDescriptor* desc = config.Create(&zone, &sig); | 748 CallDescriptor* desc = config.Create(&zone, &sig); |
| 736 Run_Computation<int32_t>(desc, Build_Int32_WeightedSum, | 749 Run_Computation<int32_t>(desc, Build_Int32_WeightedSum, |
| 737 Compute_Int32_WeightedSum, 257 + count); | 750 Compute_Int32_WeightedSum, 257 + count); |
| 751 } |
| 738 } | 752 } |
| 739 } | 753 } |
| 740 | 754 |
| 741 | 755 |
| 742 // Separate tests for parallelization. | 756 // Separate tests for parallelization. |
| 743 #define TEST_INT32_WEIGHTEDSUM(x) \ | 757 #define TEST_INT32_WEIGHTEDSUM(x) \ |
| 744 TEST(Run_Int32_WeightedSum_##x) { Test_Int32_WeightedSum_of_size(x); } | 758 TEST(Run_Int32_WeightedSum_##x) { Test_Int32_WeightedSum_of_size(x); } |
| 745 | 759 |
| 746 | 760 |
| 747 TEST_INT32_WEIGHTEDSUM(1) | 761 TEST_INT32_WEIGHTEDSUM(1) |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 812 TEST_INT32_SELECT(6) | 826 TEST_INT32_SELECT(6) |
| 813 TEST_INT32_SELECT(11) | 827 TEST_INT32_SELECT(11) |
| 814 TEST_INT32_SELECT(15) | 828 TEST_INT32_SELECT(15) |
| 815 TEST_INT32_SELECT(19) | 829 TEST_INT32_SELECT(19) |
| 816 TEST_INT32_SELECT(45) | 830 TEST_INT32_SELECT(45) |
| 817 TEST_INT32_SELECT(62) | 831 TEST_INT32_SELECT(62) |
| 818 TEST_INT32_SELECT(63) | 832 TEST_INT32_SELECT(63) |
| 819 | 833 |
| 820 | 834 |
| 821 TEST(Int64Select_registers) { | 835 TEST(Int64Select_registers) { |
| 822 if (Register::kMaxNumAllocatableRegisters < 2) return; | 836 if (RegisterConfiguration::ArchDefault() |
| 837 ->num_allocatable_general_registers() < 2) |
| 838 return; |
| 823 if (kPointerSize < 8) return; // TODO(titzer): int64 on 32-bit platforms | 839 if (kPointerSize < 8) return; // TODO(titzer): int64 on 32-bit platforms |
| 824 | 840 |
| 825 int rarray[] = {0}; | 841 int rarray[] = {0}; |
| 826 ArgsBuffer<int64_t>::Sig sig(2); | 842 ArgsBuffer<int64_t>::Sig sig(2); |
| 827 | 843 |
| 828 RegisterPairs pairs; | 844 RegisterPairs pairs; |
| 829 Zone zone; | 845 Zone zone; |
| 830 while (pairs.More()) { | 846 while (pairs.More()) { |
| 831 int parray[2]; | 847 int parray[2]; |
| 832 pairs.Next(&parray[0], &parray[1], false); | 848 pairs.Next(&parray[0], &parray[1], false); |
| 833 Allocator params(parray, 2, nullptr, 0); | 849 Allocator params(parray, 2, nullptr, 0); |
| 834 Allocator rets(rarray, 1, nullptr, 0); | 850 Allocator rets(rarray, 1, nullptr, 0); |
| 835 RegisterConfig config(params, rets); | 851 RegisterConfig config(params, rets); |
| 836 | 852 |
| 837 CallDescriptor* desc = config.Create(&zone, &sig); | 853 CallDescriptor* desc = config.Create(&zone, &sig); |
| 838 RunSelect<int64_t, 0>(desc); | 854 RunSelect<int64_t, 0>(desc); |
| 839 RunSelect<int64_t, 1>(desc); | 855 RunSelect<int64_t, 1>(desc); |
| 840 } | 856 } |
| 841 } | 857 } |
| 842 | 858 |
| 843 | 859 |
| 844 TEST(Float32Select_registers) { | 860 TEST(Float32Select_registers) { |
| 845 if (RegisterConfiguration::ArchDefault()->num_double_registers() < 2) return; | 861 if (RegisterConfiguration::ArchDefault()->num_allocatable_double_registers() < |
| 862 2) { |
| 863 return; |
| 864 } |
| 846 | 865 |
| 847 int rarray[] = {0}; | 866 int rarray[] = {0}; |
| 848 ArgsBuffer<float32>::Sig sig(2); | 867 ArgsBuffer<float32>::Sig sig(2); |
| 849 | 868 |
| 850 Float32RegisterPairs pairs; | 869 Float32RegisterPairs pairs; |
| 851 Zone zone; | 870 Zone zone; |
| 852 while (pairs.More()) { | 871 while (pairs.More()) { |
| 853 int parray[2]; | 872 int parray[2]; |
| 854 pairs.Next(&parray[0], &parray[1], false); | 873 pairs.Next(&parray[0], &parray[1], false); |
| 855 Allocator params(nullptr, 0, parray, 2); | 874 Allocator params(nullptr, 0, parray, 2); |
| 856 Allocator rets(nullptr, 0, rarray, 1); | 875 Allocator rets(nullptr, 0, rarray, 1); |
| 857 RegisterConfig config(params, rets); | 876 RegisterConfig config(params, rets); |
| 858 | 877 |
| 859 CallDescriptor* desc = config.Create(&zone, &sig); | 878 CallDescriptor* desc = config.Create(&zone, &sig); |
| 860 RunSelect<float32, 0>(desc); | 879 RunSelect<float32, 0>(desc); |
| 861 RunSelect<float32, 1>(desc); | 880 RunSelect<float32, 1>(desc); |
| 862 } | 881 } |
| 863 } | 882 } |
| 864 | 883 |
| 865 | 884 |
| 866 TEST(Float64Select_registers) { | 885 TEST(Float64Select_registers) { |
| 867 if (RegisterConfiguration::ArchDefault()->num_double_registers() < 2) return; | 886 if (RegisterConfiguration::ArchDefault()->num_allocatable_double_registers() < |
| 868 | 887 2) |
| 888 return; |
| 889 if (RegisterConfiguration::ArchDefault() |
| 890 ->num_allocatable_general_registers() < 2) |
| 891 return; |
| 869 int rarray[] = {0}; | 892 int rarray[] = {0}; |
| 870 ArgsBuffer<float64>::Sig sig(2); | 893 ArgsBuffer<float64>::Sig sig(2); |
| 871 | 894 |
| 872 Float64RegisterPairs pairs; | 895 Float64RegisterPairs pairs; |
| 873 Zone zone; | 896 Zone zone; |
| 874 while (pairs.More()) { | 897 while (pairs.More()) { |
| 875 int parray[2]; | 898 int parray[2]; |
| 876 pairs.Next(&parray[0], &parray[1], false); | 899 pairs.Next(&parray[0], &parray[1], false); |
| 877 Allocator params(nullptr, 0, parray, 2); | 900 Allocator params(nullptr, 0, parray, 2); |
| 878 Allocator rets(nullptr, 0, rarray, 1); | 901 Allocator rets(nullptr, 0, rarray, 1); |
| (...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1092 } | 1115 } |
| 1093 } | 1116 } |
| 1094 } | 1117 } |
| 1095 } | 1118 } |
| 1096 | 1119 |
| 1097 | 1120 |
| 1098 TEST(MixedParams_0) { MixedParamTest(0); } | 1121 TEST(MixedParams_0) { MixedParamTest(0); } |
| 1099 TEST(MixedParams_1) { MixedParamTest(1); } | 1122 TEST(MixedParams_1) { MixedParamTest(1); } |
| 1100 TEST(MixedParams_2) { MixedParamTest(2); } | 1123 TEST(MixedParams_2) { MixedParamTest(2); } |
| 1101 TEST(MixedParams_3) { MixedParamTest(3); } | 1124 TEST(MixedParams_3) { MixedParamTest(3); } |
| OLD | NEW |