@@ -653,7 +653,8 @@ SampleProfileReaderBinary::readProfile(FunctionSamples &FProfile) {
653
653
}
654
654
655
655
std::error_code
656
- SampleProfileReaderBinary::readFuncProfile (const uint8_t *Start) {
656
+ SampleProfileReaderBinary::readFuncProfile (const uint8_t *Start,
657
+ SampleProfileMap &Profiles) {
657
658
Data = Start;
658
659
auto NumHeadSamples = readNumber<uint64_t >();
659
660
if (std::error_code EC = NumHeadSamples.getError ())
@@ -678,6 +679,11 @@ SampleProfileReaderBinary::readFuncProfile(const uint8_t *Start) {
678
679
return sampleprof_error::success;
679
680
}
680
681
682
+ std::error_code
683
+ SampleProfileReaderBinary::readFuncProfile (const uint8_t *Start) {
684
+ return readFuncProfile (Start, Profiles);
685
+ }
686
+
681
687
std::error_code SampleProfileReaderBinary::readImpl () {
682
688
ProfileIsFS = ProfileIsFSDisciminator;
683
689
FunctionSamples::ProfileIsFS = ProfileIsFS;
@@ -725,6 +731,7 @@ std::error_code SampleProfileReaderExtBinaryBase::readOneSection(
725
731
break ;
726
732
}
727
733
case SecLBRProfile:
734
+ ProfileSecRange = std::make_pair (Data, End);
728
735
if (std::error_code EC = readFuncProfiles ())
729
736
return EC;
730
737
break ;
@@ -745,9 +752,9 @@ std::error_code SampleProfileReaderExtBinaryBase::readOneSection(
745
752
ProfileIsProbeBased =
746
753
hasSecFlag (Entry, SecFuncMetadataFlags::SecFlagIsProbeBased);
747
754
FunctionSamples::ProfileIsProbeBased = ProfileIsProbeBased;
748
- bool HasAttribute =
755
+ ProfileHasAttribute =
749
756
hasSecFlag (Entry, SecFuncMetadataFlags::SecFlagHasAttribute);
750
- if (std::error_code EC = readFuncMetadata (HasAttribute ))
757
+ if (std::error_code EC = readFuncMetadata (ProfileHasAttribute ))
751
758
return EC;
752
759
break ;
753
760
}
@@ -791,6 +798,19 @@ bool SampleProfileReaderExtBinaryBase::useFuncOffsetList() const {
791
798
return false ;
792
799
}
793
800
801
+ std::error_code
802
+ SampleProfileReaderExtBinaryBase::read (const DenseSet<StringRef> &FuncsToUse,
803
+ SampleProfileMap &Profiles) {
804
+ Data = ProfileSecRange.first ;
805
+ End = ProfileSecRange.second ;
806
+ if (std::error_code EC = readFuncProfiles (FuncsToUse, Profiles))
807
+ return EC;
808
+ End = Data;
809
+
810
+ if (std::error_code EC = readFuncMetadata (ProfileHasAttribute, Profiles))
811
+ return EC;
812
+ return sampleprof_error::success;
813
+ }
794
814
795
815
bool SampleProfileReaderExtBinaryBase::collectFuncsFromModule () {
796
816
if (!M)
@@ -838,6 +858,97 @@ std::error_code SampleProfileReaderExtBinaryBase::readFuncOffsetTable() {
838
858
return sampleprof_error::success;
839
859
}
840
860
861
+ std::error_code SampleProfileReaderExtBinaryBase::readFuncProfiles (
862
+ const DenseSet<StringRef> &FuncsToUse, SampleProfileMap &Profiles) {
863
+ const uint8_t *Start = Data;
864
+
865
+ if (Remapper) {
866
+ for (auto Name : FuncsToUse) {
867
+ Remapper->insert (Name);
868
+ }
869
+ }
870
+
871
+ if (ProfileIsCS) {
872
+ assert (useFuncOffsetList ());
873
+ DenseSet<uint64_t > FuncGuidsToUse;
874
+ if (useMD5 ()) {
875
+ for (auto Name : FuncsToUse)
876
+ FuncGuidsToUse.insert (Function::getGUID (Name));
877
+ }
878
+
879
+ // For each function in current module, load all context profiles for
880
+ // the function as well as their callee contexts which can help profile
881
+ // guided importing for ThinLTO. This can be achieved by walking
882
+ // through an ordered context container, where contexts are laid out
883
+ // as if they were walked in preorder of a context trie. While
884
+ // traversing the trie, a link to the highest common ancestor node is
885
+ // kept so that all of its decendants will be loaded.
886
+ const SampleContext *CommonContext = nullptr ;
887
+ for (const auto &NameOffset : FuncOffsetList) {
888
+ const auto &FContext = NameOffset.first ;
889
+ FunctionId FName = FContext.getFunction ();
890
+ StringRef FNameString;
891
+ if (!useMD5 ())
892
+ FNameString = FName.stringRef ();
893
+
894
+ // For function in the current module, keep its farthest ancestor
895
+ // context. This can be used to load itself and its child and
896
+ // sibling contexts.
897
+ if ((useMD5 () && FuncGuidsToUse.count (FName.getHashCode ())) ||
898
+ (!useMD5 () && (FuncsToUse.count (FNameString) ||
899
+ (Remapper && Remapper->exist (FNameString))))) {
900
+ if (!CommonContext || !CommonContext->isPrefixOf (FContext))
901
+ CommonContext = &FContext;
902
+ }
903
+
904
+ if (CommonContext == &FContext ||
905
+ (CommonContext && CommonContext->isPrefixOf (FContext))) {
906
+ // Load profile for the current context which originated from
907
+ // the common ancestor.
908
+ const uint8_t *FuncProfileAddr = Start + NameOffset.second ;
909
+ if (std::error_code EC = readFuncProfile (FuncProfileAddr))
910
+ return EC;
911
+ }
912
+ }
913
+ } else if (useMD5 ()) {
914
+ assert (!useFuncOffsetList ());
915
+ for (auto Name : FuncsToUse) {
916
+ auto GUID = MD5Hash (Name);
917
+ auto iter = FuncOffsetTable.find (GUID);
918
+ if (iter == FuncOffsetTable.end ())
919
+ continue ;
920
+ const uint8_t *FuncProfileAddr = Start + iter->second ;
921
+ if (std::error_code EC = readFuncProfile (FuncProfileAddr, Profiles))
922
+ return EC;
923
+ }
924
+ } else if (Remapper) {
925
+ assert (useFuncOffsetList ());
926
+ for (auto NameOffset : FuncOffsetList) {
927
+ SampleContext FContext (NameOffset.first );
928
+ auto FuncName = FContext.getFunction ();
929
+ StringRef FuncNameStr = FuncName.stringRef ();
930
+ if (!FuncsToUse.count (FuncNameStr) && !Remapper->exist (FuncNameStr))
931
+ continue ;
932
+ const uint8_t *FuncProfileAddr = Start + NameOffset.second ;
933
+ if (std::error_code EC = readFuncProfile (FuncProfileAddr, Profiles))
934
+ return EC;
935
+ }
936
+ } else {
937
+ assert (!useFuncOffsetList ());
938
+ for (auto Name : FuncsToUse) {
939
+
940
+ auto iter = FuncOffsetTable.find (MD5Hash (Name));
941
+ if (iter == FuncOffsetTable.end ())
942
+ continue ;
943
+ const uint8_t *FuncProfileAddr = Start + iter->second ;
944
+ if (std::error_code EC = readFuncProfile (FuncProfileAddr, Profiles))
945
+ return EC;
946
+ }
947
+ }
948
+
949
+ return sampleprof_error::success;
950
+ }
951
+
841
952
std::error_code SampleProfileReaderExtBinaryBase::readFuncProfiles () {
842
953
// Collect functions used by current module if the Reader has been
843
954
// given a module.
@@ -849,7 +960,6 @@ std::error_code SampleProfileReaderExtBinaryBase::readFuncProfiles() {
849
960
850
961
// When LoadFuncsToBeUsed is false, we are using LLVM tool, need to read all
851
962
// profiles.
852
- const uint8_t *Start = Data;
853
963
if (!LoadFuncsToBeUsed) {
854
964
while (Data < End) {
855
965
if (std::error_code EC = readFuncProfile (Data))
@@ -858,88 +968,8 @@ std::error_code SampleProfileReaderExtBinaryBase::readFuncProfiles() {
858
968
assert (Data == End && " More data is read than expected" );
859
969
} else {
860
970
// Load function profiles on demand.
861
- if (Remapper) {
862
- for (auto Name : FuncsToUse) {
863
- Remapper->insert (Name);
864
- }
865
- }
866
-
867
- if (ProfileIsCS) {
868
- assert (useFuncOffsetList ());
869
- DenseSet<uint64_t > FuncGuidsToUse;
870
- if (useMD5 ()) {
871
- for (auto Name : FuncsToUse)
872
- FuncGuidsToUse.insert (Function::getGUID (Name));
873
- }
874
-
875
- // For each function in current module, load all context profiles for
876
- // the function as well as their callee contexts which can help profile
877
- // guided importing for ThinLTO. This can be achieved by walking
878
- // through an ordered context container, where contexts are laid out
879
- // as if they were walked in preorder of a context trie. While
880
- // traversing the trie, a link to the highest common ancestor node is
881
- // kept so that all of its decendants will be loaded.
882
- const SampleContext *CommonContext = nullptr ;
883
- for (const auto &NameOffset : FuncOffsetList) {
884
- const auto &FContext = NameOffset.first ;
885
- FunctionId FName = FContext.getFunction ();
886
- StringRef FNameString;
887
- if (!useMD5 ())
888
- FNameString = FName.stringRef ();
889
-
890
- // For function in the current module, keep its farthest ancestor
891
- // context. This can be used to load itself and its child and
892
- // sibling contexts.
893
- if ((useMD5 () && FuncGuidsToUse.count (FName.getHashCode ())) ||
894
- (!useMD5 () && (FuncsToUse.count (FNameString) ||
895
- (Remapper && Remapper->exist (FNameString))))) {
896
- if (!CommonContext || !CommonContext->isPrefixOf (FContext))
897
- CommonContext = &FContext;
898
- }
899
-
900
- if (CommonContext == &FContext ||
901
- (CommonContext && CommonContext->isPrefixOf (FContext))) {
902
- // Load profile for the current context which originated from
903
- // the common ancestor.
904
- const uint8_t *FuncProfileAddr = Start + NameOffset.second ;
905
- if (std::error_code EC = readFuncProfile (FuncProfileAddr))
906
- return EC;
907
- }
908
- }
909
- } else if (useMD5 ()) {
910
- assert (!useFuncOffsetList ());
911
- for (auto Name : FuncsToUse) {
912
- auto GUID = MD5Hash (Name);
913
- auto iter = FuncOffsetTable.find (GUID);
914
- if (iter == FuncOffsetTable.end ())
915
- continue ;
916
- const uint8_t *FuncProfileAddr = Start + iter->second ;
917
- if (std::error_code EC = readFuncProfile (FuncProfileAddr))
918
- return EC;
919
- }
920
- } else if (Remapper) {
921
- assert (useFuncOffsetList ());
922
- for (auto NameOffset : FuncOffsetList) {
923
- SampleContext FContext (NameOffset.first );
924
- auto FuncName = FContext.getFunction ();
925
- StringRef FuncNameStr = FuncName.stringRef ();
926
- if (!FuncsToUse.count (FuncNameStr) && !Remapper->exist (FuncNameStr))
927
- continue ;
928
- const uint8_t *FuncProfileAddr = Start + NameOffset.second ;
929
- if (std::error_code EC = readFuncProfile (FuncProfileAddr))
930
- return EC;
931
- }
932
- } else {
933
- assert (!useFuncOffsetList ());
934
- for (auto Name : FuncsToUse) {
935
- auto iter = FuncOffsetTable.find (MD5Hash (Name));
936
- if (iter == FuncOffsetTable.end ())
937
- continue ;
938
- const uint8_t *FuncProfileAddr = Start + iter->second ;
939
- if (std::error_code EC = readFuncProfile (FuncProfileAddr))
940
- return EC;
941
- }
942
- }
971
+ if (std::error_code EC = readFuncProfiles (FuncsToUse, Profiles))
972
+ return EC;
943
973
Data = End;
944
974
}
945
975
assert ((CSProfileCount == 0 || CSProfileCount == Profiles.size ()) &&
@@ -1245,6 +1275,27 @@ SampleProfileReaderExtBinaryBase::readFuncMetadata(bool ProfileHasAttribute,
1245
1275
return sampleprof_error::success;
1246
1276
}
1247
1277
1278
+ std::error_code
1279
+ SampleProfileReaderExtBinaryBase::readFuncMetadata (bool ProfileHasAttribute,
1280
+ SampleProfileMap &Profiles) {
1281
+ if (FuncMetadataIndex.empty ())
1282
+ return sampleprof_error::success;
1283
+
1284
+ for (auto &I : Profiles) {
1285
+ FunctionSamples *FProfile = &I.second ;
1286
+ auto R = FuncMetadataIndex.find (FProfile->getContext ().getHashCode ());
1287
+ if (R == FuncMetadataIndex.end ())
1288
+ continue ;
1289
+
1290
+ Data = R->second .first ;
1291
+ End = R->second .second ;
1292
+ if (std::error_code EC = readFuncMetadata (ProfileHasAttribute, FProfile))
1293
+ return EC;
1294
+ assert (Data == End && " More data is read than expected" );
1295
+ }
1296
+ return sampleprof_error::success;
1297
+ }
1298
+
1248
1299
std::error_code
1249
1300
SampleProfileReaderExtBinaryBase::readFuncMetadata (bool ProfileHasAttribute) {
1250
1301
while (Data < End) {
@@ -1257,8 +1308,11 @@ SampleProfileReaderExtBinaryBase::readFuncMetadata(bool ProfileHasAttribute) {
1257
1308
if (It != Profiles.end ())
1258
1309
FProfile = &It->second ;
1259
1310
1311
+ const uint8_t *Start = Data;
1260
1312
if (std::error_code EC = readFuncMetadata (ProfileHasAttribute, FProfile))
1261
1313
return EC;
1314
+
1315
+ FuncMetadataIndex[FContext.getHashCode ()] = {Start, Data};
1262
1316
}
1263
1317
1264
1318
assert (Data == End && " More data is read than expected" );
0 commit comments