aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/CodeGen/BasicBlockSections.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/CodeGen/BasicBlockSections.cpp')
-rw-r--r--llvm/lib/CodeGen/BasicBlockSections.cpp38
1 files changed, 38 insertions, 0 deletions
diff --git a/llvm/lib/CodeGen/BasicBlockSections.cpp b/llvm/lib/CodeGen/BasicBlockSections.cpp
index 7499ea8..307bfae 100644
--- a/llvm/lib/CodeGen/BasicBlockSections.cpp
+++ b/llvm/lib/CodeGen/BasicBlockSections.cpp
@@ -88,6 +88,12 @@ cl::opt<std::string> llvm::BBSectionsColdTextPrefix(
cl::desc("The text prefix to use for cold basic block clusters"),
cl::init(".text.split."), cl::Hidden);
+cl::opt<bool> BBSectionsDetectSourceDrift(
+ "bbsections-detect-source-drift",
+ cl::desc("This checks if there is a fdo instr. profile hash "
+ "mismatch for this function"),
+ cl::init(true), cl::Hidden);
+
namespace {
// This struct represents the cluster information for a machine basic block.
@@ -313,10 +319,42 @@ static bool avoidZeroOffsetLandingPad(MachineFunction &MF) {
return true;
}
+// This checks if the source of this function has drifted since this binary was
+// profiled previously. For now, we are piggy backing on what PGO does to
+// detect this with instrumented profiles. PGO emits an hash of the IR and
+// checks if the hash has changed. Advanced basic block layout is usually done
+// on top of PGO optimized binaries and hence this check works well in practice.
+static bool hasInstrProfHashMismatch(MachineFunction &MF) {
+ if (!BBSectionsDetectSourceDrift)
+ return false;
+
+ const char MetadataName[] = "instr_prof_hash_mismatch";
+ auto *Existing = MF.getFunction().getMetadata(LLVMContext::MD_annotation);
+ if (Existing) {
+ MDTuple *Tuple = cast<MDTuple>(Existing);
+ for (auto &N : Tuple->operands())
+ if (cast<MDString>(N.get())->getString() == MetadataName)
+ return true;
+ }
+
+ return false;
+}
+
bool BasicBlockSections::runOnMachineFunction(MachineFunction &MF) {
auto BBSectionsType = MF.getTarget().getBBSectionsType();
assert(BBSectionsType != BasicBlockSection::None &&
"BB Sections not enabled!");
+
+ // Check for source drift. If the source has changed since the profiles
+ // were obtained, optimizing basic blocks might be sub-optimal.
+ // This only applies to BasicBlockSection::List as it creates
+ // clusters of basic blocks using basic block ids. Source drift can
+ // invalidate these groupings leading to sub-optimal code generation with
+ // regards to performance.
+ if (BBSectionsType == BasicBlockSection::List &&
+ hasInstrProfHashMismatch(MF))
+ return true;
+
// Renumber blocks before sorting them for basic block sections. This is
// useful during sorting, basic blocks in the same section will retain the
// default order. This renumbering should also be done for basic block