@@ -64,130 +64,13 @@ struct InstrProfTest : ::testing::Test {
64
64
}
65
65
};
66
66
67
- static const char callee1[] = " callee1" ;
68
- static const char callee2[] = " callee2" ;
69
- static const char callee3[] = " callee3" ;
70
- static const char callee4[] = " callee4" ;
71
- static const char callee5[] = " callee5" ;
72
- static const char callee6[] = " callee6" ;
73
-
74
- static const auto Err = [](Error E) {
75
- consumeError (std::move (E));
76
- FAIL ();
77
- };
78
-
79
- typedef std::vector<MutableArrayRef<InstrProfValueData>> VDArray;
80
-
81
- // This helper function adds the value profile data to Record. The type of
82
- // value profiles is specified by 'ValueKind'. 'ValueDataArray' is a non-const
83
- // reference and the vector element is a mutable array reference. This is mainly
84
- // because method `InstrProfRecord::addValueData` takes a pointer and might
85
- // modify the pointed-to content.
86
- static void addValueProfData (InstrProfRecord &Record, uint32_t ValueKind,
87
- VDArray &ValueDataArray) {
88
- Record.reserveSites (ValueKind, ValueDataArray.size ());
89
- for (long unsigned int i = 0 ; i < ValueDataArray.size (); i++) {
90
- // The state of vector::data() is not specified when the vector is empty,
91
- // and MutableArrayRef takes vector::data() when initialized with a vector.
92
- Record.addValueData (ValueKind, i,
93
- ValueDataArray[i].empty () ? nullptr
94
- : ValueDataArray[i].data (),
95
- ValueDataArray[i].size (), nullptr );
96
- }
97
- }
98
-
99
67
struct SparseInstrProfTest : public InstrProfTest {
100
68
void SetUp () override { Writer.setOutputSparse (true ); }
101
69
};
102
70
103
71
struct MaybeSparseInstrProfTest : public InstrProfTest ,
104
72
public ::testing::WithParamInterface<bool > {
105
73
void SetUp () override { Writer.setOutputSparse (GetParam ()); }
106
-
107
- public:
108
- // Tests that value profiles in Record has the same content as (possibly
109
- // weighted and sorted) InputVDs for each value kind. ValueProfSorted is true
110
- // iff the value profiles of Record are already sorted by count.
111
- // InputVDs is a non-const reference since it might need a in-place sort.
112
- void testValueDataArray (
113
- std::vector<std::pair<uint32_t /* ValueKind */ , VDArray &>> &InputVDs,
114
- InstrProfRecord &Record, bool ValueProfSorted = false ,
115
- uint64_t ProfWeight = 1 ) {
116
- for (auto &[ValueKind, InputVD] : InputVDs) {
117
- ASSERT_EQ (InputVD.size (), Record.getNumValueSites (ValueKind));
118
- for (unsigned i = 0 ; i < InputVD.size (); i++) {
119
- ASSERT_EQ (InputVD[i].size (),
120
- Record.getNumValueDataForSite (ValueKind, i));
121
-
122
- uint64_t WantTotalC = 0 , GetTotalC = 0 ;
123
- std::unique_ptr<InstrProfValueData[]> OutputVD =
124
- Record.getValueForSite (ValueKind, i, &GetTotalC);
125
-
126
- // If value profile elements of the same instrumented site are sorted by
127
- // count in Record, sort the input value data array the same way for
128
- // comparison purpose.
129
- if (ValueProfSorted) {
130
- llvm::stable_sort (InputVD[i], [](const InstrProfValueData &lhs,
131
- const InstrProfValueData &rhs) {
132
- return lhs.Count > rhs.Count ;
133
- });
134
- }
135
-
136
- // The previous ASSERT_EQ already tests the number of value data is
137
- // InputVD[i].size(), so there won't be out-of-bound access.
138
- for (unsigned j = 0 ; j < InputVD[i].size (); j++) {
139
- EXPECT_EQ (InputVD[i][j].Count * ProfWeight, OutputVD[j].Count );
140
- EXPECT_EQ (InputVD[i][j].Value , OutputVD[j].Value );
141
- WantTotalC += InputVD[i][j].Count ;
142
- }
143
- EXPECT_EQ (WantTotalC * ProfWeight, GetTotalC);
144
- }
145
- }
146
- }
147
-
148
- // A helper function to test the writes and reads of indirect call value
149
- // profiles. The profile writer will scale counters by `ProfWeight` when
150
- // adding a record. `Endianness` specifies the endianness used by profile
151
- // writer and reader when handling value profile records.
152
- void testICallDataReadWrite (
153
- uint64_t ProfWeight = 1 ,
154
- llvm::endianness Endianness = llvm::endianness::little) {
155
- NamedInstrProfRecord Record1 (" caller" , 0x1234 , {1 , 2 });
156
-
157
- // 4 function value sites.
158
- std::vector<InstrProfValueData> FuncVD0 = {
159
- {uint64_t (callee1), 1 }, {uint64_t (callee2), 2 }, {uint64_t (callee3), 3 }};
160
- std::vector<InstrProfValueData> FuncVD2 = {{uint64_t (callee1), 1 },
161
- {uint64_t (callee2), 2 }};
162
- std::vector<InstrProfValueData> FuncVD3 = {{uint64_t (callee1), 1 }};
163
- VDArray FuncVD = {FuncVD0, {}, FuncVD2, FuncVD3};
164
- addValueProfData (Record1, IPVK_IndirectCallTarget, FuncVD);
165
-
166
- if (ProfWeight == 1U ) {
167
- Writer.addRecord (std::move (Record1), Err);
168
- } else {
169
- Writer.addRecord (std::move (Record1), ProfWeight, Err);
170
- }
171
- Writer.addRecord ({" callee1" , 0x1235 , {3 , 4 }}, Err);
172
- Writer.addRecord ({" callee2" , 0x1235 , {3 , 4 }}, Err);
173
- Writer.addRecord ({" callee3" , 0x1235 , {3 , 4 }}, Err);
174
-
175
- // Set writer endianness.
176
- Writer.setValueProfDataEndianness (Endianness);
177
-
178
- auto Profile = Writer.writeBuffer ();
179
- readProfile (std::move (Profile));
180
-
181
- // Set reader endianness.
182
- Reader->setValueProfDataEndianness (Endianness);
183
-
184
- Expected<InstrProfRecord> R = Reader->getInstrProfRecord (" caller" , 0x1234 );
185
- EXPECT_THAT_ERROR (R.takeError (), Succeeded ());
186
-
187
- std::vector<std::pair<uint32_t , VDArray &>> InputVDs = {
188
- std::pair<uint32_t , VDArray &>{IPVK_IndirectCallTarget, FuncVD}};
189
- testValueDataArray (InputVDs, R.get (), true , ProfWeight);
190
- }
191
74
};
192
75
193
76
TEST_P (MaybeSparseInstrProfTest, write_and_read_empty_profile) {
@@ -196,6 +79,11 @@ TEST_P(MaybeSparseInstrProfTest, write_and_read_empty_profile) {
196
79
ASSERT_TRUE (Reader->begin () == Reader->end ());
197
80
}
198
81
82
+ static const auto Err = [](Error E) {
83
+ consumeError (std::move (E));
84
+ FAIL ();
85
+ };
86
+
199
87
TEST_P (MaybeSparseInstrProfTest, write_and_read_one_function) {
200
88
Writer.addRecord ({" foo" , 0x1234 , {1 , 2 , 3 , 4 }}, Err);
201
89
auto Profile = Writer.writeBuffer ();
@@ -745,8 +633,55 @@ TEST_F(InstrProfTest, test_irpgo_read_deprecated_names) {
745
633
Succeeded ());
746
634
}
747
635
748
- TEST_P (MaybeSparseInstrProfTest, icall_data_read_write) {
749
- testICallDataReadWrite ();
636
+ static const char callee1[] = " callee1" ;
637
+ static const char callee2[] = " callee2" ;
638
+ static const char callee3[] = " callee3" ;
639
+ static const char callee4[] = " callee4" ;
640
+ static const char callee5[] = " callee5" ;
641
+ static const char callee6[] = " callee6" ;
642
+
643
+ TEST_P (MaybeSparseInstrProfTest, get_icall_data_read_write) {
644
+ NamedInstrProfRecord Record1 (" caller" , 0x1234 , {1 , 2 });
645
+
646
+ // 4 value sites.
647
+ Record1.reserveSites (IPVK_IndirectCallTarget, 4 );
648
+ InstrProfValueData VD0[] = {
649
+ {(uint64_t )callee1, 1 }, {(uint64_t )callee2, 2 }, {(uint64_t )callee3, 3 }};
650
+ Record1.addValueData (IPVK_IndirectCallTarget, 0 , VD0, 3 , nullptr );
651
+ // No value profile data at the second site.
652
+ Record1.addValueData (IPVK_IndirectCallTarget, 1 , nullptr , 0 , nullptr );
653
+ InstrProfValueData VD2[] = {{(uint64_t )callee1, 1 }, {(uint64_t )callee2, 2 }};
654
+ Record1.addValueData (IPVK_IndirectCallTarget, 2 , VD2, 2 , nullptr );
655
+ InstrProfValueData VD3[] = {{(uint64_t )callee1, 1 }};
656
+ Record1.addValueData (IPVK_IndirectCallTarget, 3 , VD3, 1 , nullptr );
657
+
658
+ Writer.addRecord (std::move (Record1), Err);
659
+ Writer.addRecord ({" callee1" , 0x1235 , {3 , 4 }}, Err);
660
+ Writer.addRecord ({" callee2" , 0x1235 , {3 , 4 }}, Err);
661
+ Writer.addRecord ({" callee3" , 0x1235 , {3 , 4 }}, Err);
662
+ auto Profile = Writer.writeBuffer ();
663
+ readProfile (std::move (Profile));
664
+
665
+ Expected<InstrProfRecord> R = Reader->getInstrProfRecord (" caller" , 0x1234 );
666
+ EXPECT_THAT_ERROR (R.takeError (), Succeeded ());
667
+ ASSERT_EQ (4U , R->getNumValueSites (IPVK_IndirectCallTarget));
668
+ ASSERT_EQ (3U , R->getNumValueDataForSite (IPVK_IndirectCallTarget, 0 ));
669
+ ASSERT_EQ (0U , R->getNumValueDataForSite (IPVK_IndirectCallTarget, 1 ));
670
+ ASSERT_EQ (2U , R->getNumValueDataForSite (IPVK_IndirectCallTarget, 2 ));
671
+ ASSERT_EQ (1U , R->getNumValueDataForSite (IPVK_IndirectCallTarget, 3 ));
672
+
673
+ uint64_t TotalC;
674
+ std::unique_ptr<InstrProfValueData[]> VD =
675
+ R->getValueForSite (IPVK_IndirectCallTarget, 0 , &TotalC);
676
+
677
+ ASSERT_EQ (3U , VD[0 ].Count );
678
+ ASSERT_EQ (2U , VD[1 ].Count );
679
+ ASSERT_EQ (1U , VD[2 ].Count );
680
+ ASSERT_EQ (6U , TotalC);
681
+
682
+ ASSERT_EQ (StringRef ((const char *)VD[0 ].Value , 7 ), StringRef (" callee3" ));
683
+ ASSERT_EQ (StringRef ((const char *)VD[1 ].Value , 7 ), StringRef (" callee2" ));
684
+ ASSERT_EQ (StringRef ((const char *)VD[2 ].Value , 7 ), StringRef (" callee1" ));
750
685
}
751
686
752
687
TEST_P (MaybeSparseInstrProfTest, annotate_vp_data) {
@@ -845,15 +780,94 @@ TEST_P(MaybeSparseInstrProfTest, annotate_vp_data) {
845
780
ASSERT_EQ (1U , ValueData[3 ].Count );
846
781
}
847
782
848
- TEST_P (MaybeSparseInstrProfTest, icall_data_read_write_with_weight) {
849
- testICallDataReadWrite (10 /* ProfWeight */ );
783
+ TEST_P (MaybeSparseInstrProfTest, get_icall_data_read_write_with_weight) {
784
+ NamedInstrProfRecord Record1 (" caller" , 0x1234 , {1 , 2 });
785
+
786
+ // 4 value sites.
787
+ Record1.reserveSites (IPVK_IndirectCallTarget, 4 );
788
+ InstrProfValueData VD0[] = {
789
+ {(uint64_t )callee1, 1 }, {(uint64_t )callee2, 2 }, {(uint64_t )callee3, 3 }};
790
+ Record1.addValueData (IPVK_IndirectCallTarget, 0 , VD0, 3 , nullptr );
791
+ // No value profile data at the second site.
792
+ Record1.addValueData (IPVK_IndirectCallTarget, 1 , nullptr , 0 , nullptr );
793
+ InstrProfValueData VD2[] = {{(uint64_t )callee1, 1 }, {(uint64_t )callee2, 2 }};
794
+ Record1.addValueData (IPVK_IndirectCallTarget, 2 , VD2, 2 , nullptr );
795
+ InstrProfValueData VD3[] = {{(uint64_t )callee1, 1 }};
796
+ Record1.addValueData (IPVK_IndirectCallTarget, 3 , VD3, 1 , nullptr );
797
+
798
+ Writer.addRecord (std::move (Record1), 10 , Err);
799
+ Writer.addRecord ({" callee1" , 0x1235 , {3 , 4 }}, Err);
800
+ Writer.addRecord ({" callee2" , 0x1235 , {3 , 4 }}, Err);
801
+ Writer.addRecord ({" callee3" , 0x1235 , {3 , 4 }}, Err);
802
+ auto Profile = Writer.writeBuffer ();
803
+ readProfile (std::move (Profile));
804
+
805
+ Expected<InstrProfRecord> R = Reader->getInstrProfRecord (" caller" , 0x1234 );
806
+ EXPECT_THAT_ERROR (R.takeError (), Succeeded ());
807
+ ASSERT_EQ (4U , R->getNumValueSites (IPVK_IndirectCallTarget));
808
+ ASSERT_EQ (3U , R->getNumValueDataForSite (IPVK_IndirectCallTarget, 0 ));
809
+ ASSERT_EQ (0U , R->getNumValueDataForSite (IPVK_IndirectCallTarget, 1 ));
810
+ ASSERT_EQ (2U , R->getNumValueDataForSite (IPVK_IndirectCallTarget, 2 ));
811
+ ASSERT_EQ (1U , R->getNumValueDataForSite (IPVK_IndirectCallTarget, 3 ));
812
+
813
+ uint64_t TotalC;
814
+ std::unique_ptr<InstrProfValueData[]> VD =
815
+ R->getValueForSite (IPVK_IndirectCallTarget, 0 , &TotalC);
816
+ ASSERT_EQ (30U , VD[0 ].Count );
817
+ ASSERT_EQ (20U , VD[1 ].Count );
818
+ ASSERT_EQ (10U , VD[2 ].Count );
819
+ ASSERT_EQ (60U , TotalC);
820
+
821
+ ASSERT_EQ (StringRef ((const char *)VD[0 ].Value , 7 ), StringRef (" callee3" ));
822
+ ASSERT_EQ (StringRef ((const char *)VD[1 ].Value , 7 ), StringRef (" callee2" ));
823
+ ASSERT_EQ (StringRef ((const char *)VD[2 ].Value , 7 ), StringRef (" callee1" ));
850
824
}
851
825
852
- TEST_P (MaybeSparseInstrProfTest, icall_data_read_write_big_endian) {
853
- testICallDataReadWrite (1 /* ProfWeight */ , llvm::endianness::big);
854
- // Restore little endianness after this test case.
826
+ TEST_P (MaybeSparseInstrProfTest, get_icall_data_read_write_big_endian) {
827
+ NamedInstrProfRecord Record1 (" caller" , 0x1234 , {1 , 2 });
828
+
829
+ // 4 value sites.
830
+ Record1.reserveSites (IPVK_IndirectCallTarget, 4 );
831
+ InstrProfValueData VD0[] = {
832
+ {(uint64_t )callee1, 1 }, {(uint64_t )callee2, 2 }, {(uint64_t )callee3, 3 }};
833
+ Record1.addValueData (IPVK_IndirectCallTarget, 0 , VD0, 3 , nullptr );
834
+ // No value profile data at the second site.
835
+ Record1.addValueData (IPVK_IndirectCallTarget, 1 , nullptr , 0 , nullptr );
836
+ InstrProfValueData VD2[] = {{(uint64_t )callee1, 1 }, {(uint64_t )callee2, 2 }};
837
+ Record1.addValueData (IPVK_IndirectCallTarget, 2 , VD2, 2 , nullptr );
838
+ InstrProfValueData VD3[] = {{(uint64_t )callee1, 1 }};
839
+ Record1.addValueData (IPVK_IndirectCallTarget, 3 , VD3, 1 , nullptr );
840
+
841
+ Writer.addRecord (std::move (Record1), Err);
842
+ Writer.addRecord ({" callee1" , 0x1235 , {3 , 4 }}, Err);
843
+ Writer.addRecord ({" callee2" , 0x1235 , {3 , 4 }}, Err);
844
+ Writer.addRecord ({" callee3" , 0x1235 , {3 , 4 }}, Err);
845
+
846
+ // Set big endian output.
847
+ Writer.setValueProfDataEndianness (llvm::endianness::big);
848
+
849
+ auto Profile = Writer.writeBuffer ();
850
+ readProfile (std::move (Profile));
851
+
852
+ // Set big endian input.
853
+ Reader->setValueProfDataEndianness (llvm::endianness::big);
854
+
855
+ Expected<InstrProfRecord> R = Reader->getInstrProfRecord (" caller" , 0x1234 );
856
+ EXPECT_THAT_ERROR (R.takeError (), Succeeded ());
857
+ ASSERT_EQ (4U , R->getNumValueSites (IPVK_IndirectCallTarget));
858
+ ASSERT_EQ (3U , R->getNumValueDataForSite (IPVK_IndirectCallTarget, 0 ));
859
+ ASSERT_EQ (0U , R->getNumValueDataForSite (IPVK_IndirectCallTarget, 1 ));
860
+ ASSERT_EQ (2U , R->getNumValueDataForSite (IPVK_IndirectCallTarget, 2 ));
861
+ ASSERT_EQ (1U , R->getNumValueDataForSite (IPVK_IndirectCallTarget, 3 ));
862
+
863
+ std::unique_ptr<InstrProfValueData[]> VD =
864
+ R->getValueForSite (IPVK_IndirectCallTarget, 0 );
865
+ ASSERT_EQ (StringRef ((const char *)VD[0 ].Value , 7 ), StringRef (" callee3" ));
866
+ ASSERT_EQ (StringRef ((const char *)VD[1 ].Value , 7 ), StringRef (" callee2" ));
867
+ ASSERT_EQ (StringRef ((const char *)VD[2 ].Value , 7 ), StringRef (" callee1" ));
868
+
869
+ // Restore little endian default:
855
870
Writer.setValueProfDataEndianness (llvm::endianness::little);
856
- Reader->setValueProfDataEndianness (llvm::endianness::little);
857
871
}
858
872
859
873
TEST_P (MaybeSparseInstrProfTest, get_icall_data_merge1) {
@@ -879,8 +893,9 @@ TEST_P(MaybeSparseInstrProfTest, get_icall_data_merge1) {
879
893
InstrProfValueData VD3[] = {{uint64_t (callee1), 1 }};
880
894
Record11.addValueData (IPVK_IndirectCallTarget, 3 , VD3, 1 , nullptr );
881
895
882
- InstrProfValueData VD4[] = {
883
- {uint64_t (callee1), 1 }, {uint64_t (callee2), 2 }, {uint64_t (callee3), 3 }};
896
+ InstrProfValueData VD4[] = {{uint64_t (callee1), 1 },
897
+ {uint64_t (callee2), 2 },
898
+ {uint64_t (callee3), 3 }};
884
899
Record11.addValueData (IPVK_IndirectCallTarget, 4 , VD4, 3 , nullptr );
885
900
886
901
// A different record for the same caller.
@@ -897,8 +912,9 @@ TEST_P(MaybeSparseInstrProfTest, get_icall_data_merge1) {
897
912
898
913
Record12.addValueData (IPVK_IndirectCallTarget, 3 , nullptr , 0 , nullptr );
899
914
900
- InstrProfValueData VD42[] = {
901
- {uint64_t (callee1), 1 }, {uint64_t (callee2), 2 }, {uint64_t (callee3), 3 }};
915
+ InstrProfValueData VD42[] = {{uint64_t (callee1), 1 },
916
+ {uint64_t (callee2), 2 },
917
+ {uint64_t (callee3), 3 }};
902
918
Record12.addValueData (IPVK_IndirectCallTarget, 4 , VD42, 3 , nullptr );
903
919
904
920
Writer.addRecord (std::move (Record11), Err);
0 commit comments