|
12 | 12 | //===----------------------------------------------------------------------===// |
13 | 13 |
|
14 | 14 | #include "llvm/Analysis/CtxProfAnalysis.h" |
| 15 | +#include "llvm/ADT/APInt.h" |
15 | 16 | #include "llvm/ADT/STLExtras.h" |
16 | 17 | #include "llvm/IR/Analysis.h" |
17 | 18 | #include "llvm/IR/IntrinsicInst.h" |
|
20 | 21 | #include "llvm/ProfileData/PGOCtxProfReader.h" |
21 | 22 | #include "llvm/Support/CommandLine.h" |
22 | 23 | #include "llvm/Support/MemoryBuffer.h" |
| 24 | +#include "llvm/Support/Path.h" |
23 | 25 |
|
24 | 26 | #define DEBUG_TYPE "ctx_prof" |
25 | 27 |
|
@@ -95,26 +97,42 @@ PGOContextualProfile CtxProfAnalysis::run(Module &M, |
95 | 97 | return {}; |
96 | 98 | } |
97 | 99 |
|
98 | | - DenseSet<GlobalValue::GUID> ProfileRootsInModule; |
99 | | - for (const auto &F : M) |
100 | | - if (!F.isDeclaration()) |
101 | | - if (auto GUID = AssignGUIDPass::getGUID(F); |
102 | | - MaybeProfiles->Contexts.find(GUID) != MaybeProfiles->Contexts.end()) |
103 | | - ProfileRootsInModule.insert(GUID); |
104 | | - |
105 | | - // Trim first the roots that aren't in this module. |
106 | | - for (auto &[RootGuid, _] : |
107 | | - llvm::make_early_inc_range(MaybeProfiles->Contexts)) |
108 | | - if (!ProfileRootsInModule.contains(RootGuid)) |
109 | | - MaybeProfiles->Contexts.erase(RootGuid); |
110 | | - // If none of the roots are in the module, we have no profile (for this |
111 | | - // module) |
112 | | - if (MaybeProfiles->Contexts.empty()) |
113 | | - return {}; |
114 | | - |
115 | | - // OK, so we have a valid profile and it's applicable to roots in this module. |
| 100 | + // FIXME: We should drive this from ThinLTO, but for the time being, use the |
| 101 | + // module name as indicator. |
| 102 | + // We want to *only* keep the contextual profiles in modules that capture |
| 103 | + // context trees. That allows us to compute specific PSIs, for example. |
| 104 | + auto DetermineRootsInModule = [&M]() -> const DenseSet<GlobalValue::GUID> { |
| 105 | + DenseSet<GlobalValue::GUID> ProfileRootsInModule; |
| 106 | + auto ModName = M.getName(); |
| 107 | + auto Filename = sys::path::filename(ModName); |
| 108 | + // Drop the file extension. |
| 109 | + Filename = Filename.substr(0, Filename.find_last_of('.')); |
| 110 | + // See if it parses |
| 111 | + APInt Guid; |
| 112 | + // getAsInteger returns true if there are more chars to read other than the |
| 113 | + // integer. So the "false" test is what we want. |
| 114 | + if (!Filename.getAsInteger(0, Guid)) |
| 115 | + ProfileRootsInModule.insert(Guid.getZExtValue()); |
| 116 | + return ProfileRootsInModule; |
| 117 | + }; |
| 118 | + const auto ProfileRootsInModule = DetermineRootsInModule(); |
116 | 119 | PGOContextualProfile Result; |
117 | 120 |
|
| 121 | + // the logic from here on allows for modules that contain - by design - more |
| 122 | + // than one root. We currently don't support that, because the determination |
| 123 | + // happens based on the module name matching the root guid, but the logic can |
| 124 | + // avoid assuming that. |
| 125 | + if (!ProfileRootsInModule.empty()) { |
| 126 | + Result.IsInSpecializedModule = true; |
| 127 | + // Trim first the roots that aren't in this module. |
| 128 | + for (auto &[RootGuid, _] : |
| 129 | + llvm::make_early_inc_range(MaybeProfiles->Contexts)) |
| 130 | + if (!ProfileRootsInModule.contains(RootGuid)) |
| 131 | + MaybeProfiles->Contexts.erase(RootGuid); |
| 132 | + // we can also drop the flat profiles |
| 133 | + MaybeProfiles->FlatProfiles.clear(); |
| 134 | + } |
| 135 | + |
118 | 136 | for (const auto &F : M) { |
119 | 137 | if (F.isDeclaration()) |
120 | 138 | continue; |
|
0 commit comments