1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-18 10:32:48 +02:00
llvm-mirror/lib/CodeGen/MIRFSDiscriminator.cpp
Rong Xu 022ca8be28 [SampleFDO] Place the discriminator flag variable into the used list.
We create flag variable "__llvm_fs_discriminator__" in the binary
to indicate that FSAFDO hierarchical discriminators are used.

This variable might be GC'ed by the linker since it is not explicitly
reference. I initially added the var to the use list in pass
MIRFSDiscriminator but it did not work. It turned out the used global
list is collected in lowering (before MIR pass) and then emitted in
the end of pass pipeline.

Here I add the variable to the use list in IR level's AddDiscriminators
pass. The machine level code is still keep in the case IR's
AddDiscriminators is not invoked. If this is the case, this just use
-Wl,--export-dynamic-symbol=__llvm_fs_discriminator__
to force the emit.

Differential Revision: https://reviews.llvm.org/D103988
2021-06-15 21:51:04 -07:00

138 lines
5.1 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/IR/Function.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Utils/SampleProfileLoaderBaseUtil.h"
#include <unordered_map>
using namespace llvm;
using namespace sampleprof;
using namespace sampleprofutil;
#define DEBUG_TYPE "mirfs-discriminators"
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);
}
// Compute a hash value using debug line number, and the line numbers from the
// inline stack.
static uint64_t getCallStackHash(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;
}
// 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 Changed = false;
using LocationDiscriminator = std::tuple<StringRef, unsigned, unsigned>;
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.
unsigned BitMaskBefore = getN1Bits(LowBit);
// 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() << "\n");
for (MachineBasicBlock &BB : MF) {
for (MachineInstr &I : BB) {
const DILocation *DIL = I.getDebugLoc().get();
if (!DIL)
continue;
unsigned LineNo = DIL->getLine();
if (LineNo == 0)
continue;
unsigned Discriminator = DIL->getDiscriminator();
LocationDiscriminator LD{DIL->getFilename(), LineNo, Discriminator};
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;
DiscriminatorCurrPass += getCallStackHash(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");
}
return Changed;
}