mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-30 08:56:06 +00:00

This is the first change for FS-AFDO integration with CSSPGO. There are more patches coming. With pseudo probes, we do not assign FS discriminators to any other instructions since we will be using only probes for profile correlation. Also call instructions are excluded since their dwarf discriminators are used for other purposes, i.e, storing probe ids. Since they are not getting a FS discriminator, they will also be excluded from MIR profile loading. The corresponding changes will be in the subsequent patches. Reviewed By: wenlei Differential Revision: https://reviews.llvm.org/D147286
197 lines
7.4 KiB
C++
197 lines
7.4 KiB
C++
//===-------- MIRFSDiscriminator.cpp: Flow Sensitive Discriminator --------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file provides the implementation of a machine pass that adds the flow
|
|
// sensitive discriminator to the instruction debug information.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/CodeGen/MIRFSDiscriminator.h"
|
|
#include "llvm/ADT/DenseMap.h"
|
|
#include "llvm/ADT/DenseSet.h"
|
|
#include "llvm/Analysis/BlockFrequencyInfoImpl.h"
|
|
#include "llvm/CodeGen/Passes.h"
|
|
#include "llvm/IR/DebugInfoMetadata.h"
|
|
#include "llvm/IR/Function.h"
|
|
#include "llvm/IR/Module.h"
|
|
#include "llvm/IR/PseudoProbe.h"
|
|
#include "llvm/InitializePasses.h"
|
|
#include "llvm/Support/CommandLine.h"
|
|
#include "llvm/Support/Debug.h"
|
|
#include "llvm/Support/raw_ostream.h"
|
|
#include "llvm/Support/xxhash.h"
|
|
#include "llvm/Transforms/Utils/SampleProfileLoaderBaseUtil.h"
|
|
|
|
using namespace llvm;
|
|
using namespace sampleprof;
|
|
using namespace sampleprofutil;
|
|
|
|
#define DEBUG_TYPE "mirfs-discriminators"
|
|
|
|
// TODO(xur): Remove this option and related code once we make true as the
|
|
// default.
|
|
cl::opt<bool> ImprovedFSDiscriminator(
|
|
"improved-fs-discriminator", cl::Hidden, cl::init(false),
|
|
cl::desc("New FS discriminators encoding (incompatible with the original "
|
|
"encoding)"));
|
|
|
|
char MIRAddFSDiscriminators::ID = 0;
|
|
|
|
INITIALIZE_PASS(MIRAddFSDiscriminators, DEBUG_TYPE,
|
|
"Add MIR Flow Sensitive Discriminators",
|
|
/* cfg = */ false, /* is_analysis = */ false)
|
|
|
|
char &llvm::MIRAddFSDiscriminatorsID = MIRAddFSDiscriminators::ID;
|
|
|
|
FunctionPass *llvm::createMIRAddFSDiscriminatorsPass(FSDiscriminatorPass P) {
|
|
return new MIRAddFSDiscriminators(P);
|
|
}
|
|
|
|
// TODO(xur): Remove this once we switch to ImprovedFSDiscriminator.
|
|
// Compute a hash value using debug line number, and the line numbers from the
|
|
// inline stack.
|
|
static uint64_t getCallStackHashV0(const MachineBasicBlock &BB,
|
|
const MachineInstr &MI,
|
|
const DILocation *DIL) {
|
|
auto updateHash = [](const StringRef &Str) -> uint64_t {
|
|
if (Str.empty())
|
|
return 0;
|
|
return MD5Hash(Str);
|
|
};
|
|
uint64_t Ret = updateHash(std::to_string(DIL->getLine()));
|
|
Ret ^= updateHash(BB.getName());
|
|
Ret ^= updateHash(DIL->getScope()->getSubprogram()->getLinkageName());
|
|
for (DIL = DIL->getInlinedAt(); DIL; DIL = DIL->getInlinedAt()) {
|
|
Ret ^= updateHash(std::to_string(DIL->getLine()));
|
|
Ret ^= updateHash(DIL->getScope()->getSubprogram()->getLinkageName());
|
|
}
|
|
return Ret;
|
|
}
|
|
|
|
static uint64_t getCallStackHash(const DILocation *DIL) {
|
|
auto hashCombine = [](const uint64_t Seed, const uint64_t Val) {
|
|
std::hash<uint64_t> Hasher;
|
|
return Seed ^ (Hasher(Val) + 0x9e3779b9 + (Seed << 6) + (Seed >> 2));
|
|
};
|
|
uint64_t Ret = 0;
|
|
for (DIL = DIL->getInlinedAt(); DIL; DIL = DIL->getInlinedAt()) {
|
|
Ret = hashCombine(Ret, xxHash64(ArrayRef<uint8_t>(DIL->getLine())));
|
|
Ret = hashCombine(Ret, xxHash64(DIL->getSubprogramLinkageName()));
|
|
}
|
|
return Ret;
|
|
}
|
|
|
|
// Traverse the CFG and assign FD discriminators. If two instructions
|
|
// have the same lineno and discriminator, but residing in different BBs,
|
|
// the latter instruction will get a new discriminator value. The new
|
|
// discriminator keeps the existing discriminator value but sets new bits
|
|
// b/w LowBit and HighBit.
|
|
bool MIRAddFSDiscriminators::runOnMachineFunction(MachineFunction &MF) {
|
|
if (!EnableFSDiscriminator)
|
|
return false;
|
|
|
|
bool HasPseudoProbe = MF.getFunction().getParent()->getNamedMetadata(
|
|
PseudoProbeDescMetadataName);
|
|
|
|
if (!HasPseudoProbe && !MF.getFunction().shouldEmitDebugInfoForProfiling())
|
|
return false;
|
|
|
|
bool Changed = false;
|
|
using LocationDiscriminator =
|
|
std::tuple<StringRef, unsigned, unsigned, uint64_t>;
|
|
using BBSet = DenseSet<const MachineBasicBlock *>;
|
|
using LocationDiscriminatorBBMap = DenseMap<LocationDiscriminator, BBSet>;
|
|
using LocationDiscriminatorCurrPassMap =
|
|
DenseMap<LocationDiscriminator, unsigned>;
|
|
|
|
LocationDiscriminatorBBMap LDBM;
|
|
LocationDiscriminatorCurrPassMap LDCM;
|
|
|
|
// Mask of discriminators before this pass.
|
|
// TODO(xur): simplify this once we switch to ImprovedFSDiscriminator.
|
|
unsigned LowBitTemp = LowBit;
|
|
assert(LowBit > 0 && "LowBit in FSDiscriminator cannot be 0");
|
|
if (ImprovedFSDiscriminator)
|
|
LowBitTemp -= 1;
|
|
unsigned BitMaskBefore = getN1Bits(LowBitTemp);
|
|
// Mask of discriminators including this pass.
|
|
unsigned BitMaskNow = getN1Bits(HighBit);
|
|
// Mask of discriminators for bits specific to this pass.
|
|
unsigned BitMaskThisPass = BitMaskNow ^ BitMaskBefore;
|
|
unsigned NumNewD = 0;
|
|
|
|
LLVM_DEBUG(dbgs() << "MIRAddFSDiscriminators working on Func: "
|
|
<< MF.getFunction().getName() << " Highbit=" << HighBit
|
|
<< "\n");
|
|
|
|
for (MachineBasicBlock &BB : MF) {
|
|
for (MachineInstr &I : BB) {
|
|
if (HasPseudoProbe) {
|
|
// Only assign discriminators to pseudo probe instructions. Call
|
|
// instructions are excluded since their dwarf discriminators are used
|
|
// for other purposes, i.e, storing probe ids.
|
|
if (!I.isPseudoProbe())
|
|
continue;
|
|
} else if (ImprovedFSDiscriminator && I.isMetaInstruction()) {
|
|
continue;
|
|
}
|
|
const DILocation *DIL = I.getDebugLoc().get();
|
|
if (!DIL)
|
|
continue;
|
|
|
|
// Use the id of pseudo probe to compute the discriminator.
|
|
unsigned LineNo =
|
|
I.isPseudoProbe() ? I.getOperand(1).getImm() : DIL->getLine();
|
|
if (LineNo == 0)
|
|
continue;
|
|
unsigned Discriminator = DIL->getDiscriminator();
|
|
uint64_t CallStackHashVal = 0;
|
|
if (ImprovedFSDiscriminator)
|
|
CallStackHashVal = getCallStackHash(DIL);
|
|
|
|
LocationDiscriminator LD{DIL->getFilename(), LineNo, Discriminator,
|
|
CallStackHashVal};
|
|
auto &BBMap = LDBM[LD];
|
|
auto R = BBMap.insert(&BB);
|
|
if (BBMap.size() == 1)
|
|
continue;
|
|
|
|
unsigned DiscriminatorCurrPass;
|
|
DiscriminatorCurrPass = R.second ? ++LDCM[LD] : LDCM[LD];
|
|
DiscriminatorCurrPass = DiscriminatorCurrPass << LowBit;
|
|
if (!ImprovedFSDiscriminator)
|
|
DiscriminatorCurrPass += getCallStackHashV0(BB, I, DIL);
|
|
DiscriminatorCurrPass &= BitMaskThisPass;
|
|
unsigned NewD = Discriminator | DiscriminatorCurrPass;
|
|
const auto *const NewDIL = DIL->cloneWithDiscriminator(NewD);
|
|
if (!NewDIL) {
|
|
LLVM_DEBUG(dbgs() << "Could not encode discriminator: "
|
|
<< DIL->getFilename() << ":" << DIL->getLine() << ":"
|
|
<< DIL->getColumn() << ":" << Discriminator << " "
|
|
<< I << "\n");
|
|
continue;
|
|
}
|
|
|
|
I.setDebugLoc(NewDIL);
|
|
NumNewD++;
|
|
LLVM_DEBUG(dbgs() << DIL->getFilename() << ":" << DIL->getLine() << ":"
|
|
<< DIL->getColumn() << ": add FS discriminator, from "
|
|
<< Discriminator << " -> " << NewD << "\n");
|
|
Changed = true;
|
|
}
|
|
}
|
|
|
|
if (Changed) {
|
|
createFSDiscriminatorVariable(MF.getFunction().getParent());
|
|
LLVM_DEBUG(dbgs() << "Num of FS Discriminators: " << NumNewD << "\n");
|
|
(void) NumNewD;
|
|
}
|
|
|
|
return Changed;
|
|
}
|