Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Deprecated][SampleFDO] Stale profile call-graph matching #92151

Closed
wants to merge 12 commits into from
86 changes: 77 additions & 9 deletions llvm/include/llvm/Transforms/IPO/SampleProfileMatcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ namespace llvm {

using AnchorList = std::vector<std::pair<LineLocation, FunctionId>>;
using AnchorMap = std::map<LineLocation, FunctionId>;
using FunctionMap = HashKeyMap<std::unordered_map, FunctionId, Function *>;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This type is used elsewhere too (SampleProfileLoader). Either use the type alias everywhere or spell out the full type everywhere. Maybe it's better to just spell out the type name to be explicit?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good to spell out to be explicit.


// Sample profile matching - fuzzy match.
class SampleProfileMatcher {
Expand All @@ -34,7 +35,7 @@ class SampleProfileMatcher {
// in the profile.
StringMap<LocToLocMap> FuncMappings;

// Match state for an anchor/callsite.
// Match state for an anchor/callsite or function.
enum class MatchState {
Unknown = 0,
// Initial match between input profile and current IR.
Expand All @@ -58,6 +59,20 @@ class SampleProfileMatcher {
StringMap<std::unordered_map<LineLocation, MatchState, LineLocationHash>>
FuncCallsiteMatchStates;

struct FuncProfNameMapHash {
uint64_t
operator()(const std::pair<const Function *, FunctionId> &P) const {
return hash_combine(P.first, P.second);
}
};
std::unordered_map<std::pair<const Function *, FunctionId>, bool,
FuncProfNameMapHash>
FunctionProfileNameMap;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I was suggesting

FunctionProfileNameMap -> FuncToProfileNameMap
OldProfToNewSymbolMap -> ProfileNameToFuncMap

because symmetric naming helps readability. I saw you changed the other one, but not this one.


FunctionMap *SymbolMap;
wlei-llvm marked this conversation as resolved.
Show resolved Hide resolved

std::shared_ptr<ProfileSymbolList> PSL;

// Profile mismatch statstics:
uint64_t TotalProfiledFunc = 0;
// Num of checksum-mismatched function.
Expand All @@ -80,26 +95,37 @@ class SampleProfileMatcher {
public:
SampleProfileMatcher(Module &M, SampleProfileReader &Reader,
const PseudoProbeManager *ProbeManager,
ThinOrFullLTOPhase LTOPhase)
: M(M), Reader(Reader), ProbeManager(ProbeManager), LTOPhase(LTOPhase){};
void runOnModule();
ThinOrFullLTOPhase LTOPhase,
std::shared_ptr<ProfileSymbolList> PSL)
: M(M), Reader(Reader), ProbeManager(ProbeManager), LTOPhase(LTOPhase),
PSL(PSL) {};
void runOnModule(FunctionMap &SymbolMap);
void clearMatchingData() {
// Do not clear FuncMappings, it stores IRLoc to ProfLoc remappings which
// will be used for sample loader.
FuncCallsiteMatchStates.clear();
}

private:
FunctionSamples *getFlattenedSamplesFor(const Function &F) {
StringRef CanonFName = FunctionSamples::getCanonicalFnName(F);
auto It = FlattenedProfiles.find(FunctionId(CanonFName));
FunctionSamples *getFlattenedSamplesFor(const FunctionId &Fname) {
auto It = FlattenedProfiles.find(Fname);
if (It != FlattenedProfiles.end())
return &It->second;
return nullptr;
}
FunctionSamples *getFlattenedSamplesFor(const Function &F) {
StringRef CanonFName = FunctionSamples::getCanonicalFnName(F);
return getFlattenedSamplesFor(FunctionId(CanonFName));
}
void getFilteredAnchorList(const AnchorMap &IRAnchors,
const AnchorMap &ProfileAnchors,
AnchorList &FilteredIRAnchorsList,
AnchorList &FilteredProfileAnchorList);
void runCFGMatching(Function &F);
void runOnFunction(Function &F);
void findIRAnchors(const Function &F, AnchorMap &IRAnchors);
void findProfileAnchors(const FunctionSamples &FS, AnchorMap &ProfileAnchors);
void findIRAnchors(const Function &F, AnchorMap &IRAnchors) const;
void findProfileAnchors(const FunctionSamples &FS,
AnchorMap &ProfileAnchors) const;
// Record the callsite match states for profile staleness report, the result
// is saved in FuncCallsiteMatchStates.
void recordCallsiteMatchStates(const Function &F, const AnchorMap &IRAnchors,
Expand Down Expand Up @@ -160,6 +186,48 @@ class SampleProfileMatcher {
void runStaleProfileMatching(const Function &F, const AnchorMap &IRAnchors,
const AnchorMap &ProfileAnchors,
LocToLocMap &IRToProfileLocationMap);
/// Find the existing or new matched function using the profile name.
///
/// \returns The function and a match state.
std::pair<Function *, MatchState>
findFunction(const FunctionId &ProfFunc,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe more clear if we name it findFuncByProfileName

const FunctionMap &OldProfToNewSymbolMap) const;
/// Find the function using the profile name. If the function is not found but
/// the \p NewIRCallees is provided, try to match the function profile with
/// all functions in \p NewIRCallees and return the matched function.
///
/// \param ProfFunc The function profile name.
/// \param OldProfToNewSymbolMap The map from old profile name to new symbol.
/// \param NewIRCallees The new candidate callees in the same scope to match.
///
/// \returns The matched function and a match state.
std::pair<Function *, MatchState>
findOrMatchFunction(const FunctionId &ProfFunc,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

similarly findOrMatchFuncByProfileName?

FunctionMap &OldProfToNewSymbolMap,
const std::vector<Function *> &NewIRCallees);
std::vector<FunctionSamples *> sortFuncProfiles(SampleProfileMap &ProfileMap);
void findNewIRCallees(Function &Caller,
const StringMap<Function *> &NewIRFunctions,
std::vector<Function *> &NewIRCallees);
bool functionMatchesProfileHelper(const Function &IRFunc,
const FunctionId &ProfFunc);
/// Determine if the function matches profile by computing a similarity ratio
/// between two callsite anchors extracted from function and profile. If it's
/// above the threshold, the function matches the profile.
///
/// \returns True if the function matches profile.
bool functionMatchesProfile(const Function &IRFunc,
wlei-llvm marked this conversation as resolved.
Show resolved Hide resolved
const FunctionId &ProfFunc);
void matchProfileForNewFunctions(const StringMap<Function *> &NewIRFunctions,
FunctionSamples &FS,
FunctionMap &OldProfToNewSymbolMap);
/// Find functions that don't show in the profile or profile symbol list,
/// which are supposed to be new functions. We use them as the targets for
/// renaming matching.
///
/// \param NewIRFunctions The map from function name to the IR function.
void findNewIRFunctions(StringMap<Function *> &NewIRFunctions);
void runCallGraphMatching();
void reportOrPersistProfileStats();
};
} // end namespace llvm
Expand Down
6 changes: 3 additions & 3 deletions llvm/lib/Transforms/IPO/SampleProfile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -544,7 +544,7 @@ class SampleProfileLoader final : public SampleProfileLoaderBaseImpl<Function> {

/// Profle Symbol list tells whether a function name appears in the binary
/// used to generate the current profile.
std::unique_ptr<ProfileSymbolList> PSL;
std::shared_ptr<ProfileSymbolList> PSL;

/// Total number of samples collected in this profile.
///
Expand Down Expand Up @@ -2077,7 +2077,7 @@ bool SampleProfileLoader::doInitialization(Module &M,
if (ReportProfileStaleness || PersistProfileStaleness ||
SalvageStaleProfile) {
MatchingManager = std::make_unique<SampleProfileMatcher>(
M, *Reader, ProbeManager.get(), LTOPhase);
M, *Reader, ProbeManager.get(), LTOPhase, PSL);
}

return true;
Expand Down Expand Up @@ -2198,7 +2198,7 @@ bool SampleProfileLoader::runOnModule(Module &M, ModuleAnalysisManager *AM,

if (ReportProfileStaleness || PersistProfileStaleness ||
SalvageStaleProfile) {
MatchingManager->runOnModule();
MatchingManager->runOnModule(SymbolMap);
MatchingManager->clearMatchingData();
}

Expand Down
Loading
Loading