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

It's useful if the probe-based build can consume a dwarf based profile(e.g. the profile transition), before there is a conflict for the discriminator, this change tries to mitigate the issue by encoding the dwarf base discriminator into the probe discriminator. As the num of probe id(num of basic block and calls) starts from 1, there are some unused space. We try to reuse some bit of the probe id. The new encode rule is: - Use a bit to [28:28] to indicate whether dwarf base discriminator is encoded.(fortunately we can borrow this bit from the `PseudoProbeType`) - If the bit is set, use [15:3] for probe id, [18:16] for dwarf base discriminator. Otherwise, still use [18:3] for probe id. Note that these doesn't affect the original probe id capacity, we still prioritize probe id encoding, i.e. the base discriminator is not encoded when probe id is bigger than [15:3]. Then adjust `getBaseDiscriminatorFromDiscriminator` to use the base discriminator from the probe discriminator.
116 lines
4.2 KiB
C++
116 lines
4.2 KiB
C++
//===- PseudoProbe.cpp - Pseudo Probe Helpers -----------------------------===//
|
|
//
|
|
// 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 implements the helpers to manipulate pseudo probe IR intrinsic
|
|
// calls.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/IR/PseudoProbe.h"
|
|
#include "llvm/IR/DebugInfoMetadata.h"
|
|
#include "llvm/IR/IRBuilder.h"
|
|
#include "llvm/IR/Instruction.h"
|
|
#include "llvm/IR/IntrinsicInst.h"
|
|
|
|
using namespace llvm;
|
|
|
|
namespace llvm {
|
|
|
|
std::optional<PseudoProbe>
|
|
extractProbeFromDiscriminator(const DILocation *DIL) {
|
|
if (DIL) {
|
|
auto Discriminator = DIL->getDiscriminator();
|
|
if (DILocation::isPseudoProbeDiscriminator(Discriminator)) {
|
|
PseudoProbe Probe;
|
|
Probe.Id =
|
|
PseudoProbeDwarfDiscriminator::extractProbeIndex(Discriminator);
|
|
Probe.Type =
|
|
PseudoProbeDwarfDiscriminator::extractProbeType(Discriminator);
|
|
Probe.Attr =
|
|
PseudoProbeDwarfDiscriminator::extractProbeAttributes(Discriminator);
|
|
Probe.Factor =
|
|
PseudoProbeDwarfDiscriminator::extractProbeFactor(Discriminator) /
|
|
(float)PseudoProbeDwarfDiscriminator::FullDistributionFactor;
|
|
Probe.Discriminator = 0;
|
|
return Probe;
|
|
}
|
|
}
|
|
return std::nullopt;
|
|
}
|
|
|
|
std::optional<PseudoProbe>
|
|
extractProbeFromDiscriminator(const Instruction &Inst) {
|
|
assert(isa<CallBase>(&Inst) && !isa<IntrinsicInst>(&Inst) &&
|
|
"Only call instructions should have pseudo probe encodes as their "
|
|
"Dwarf discriminators");
|
|
if (const DebugLoc &DLoc = Inst.getDebugLoc())
|
|
return extractProbeFromDiscriminator(DLoc);
|
|
return std::nullopt;
|
|
}
|
|
|
|
std::optional<PseudoProbe> extractProbe(const Instruction &Inst) {
|
|
if (const auto *II = dyn_cast<PseudoProbeInst>(&Inst)) {
|
|
PseudoProbe Probe;
|
|
Probe.Id = II->getIndex()->getZExtValue();
|
|
Probe.Type = (uint32_t)PseudoProbeType::Block;
|
|
Probe.Attr = II->getAttributes()->getZExtValue();
|
|
Probe.Factor = II->getFactor()->getZExtValue() /
|
|
(float)PseudoProbeFullDistributionFactor;
|
|
Probe.Discriminator = 0;
|
|
if (const DebugLoc &DLoc = Inst.getDebugLoc())
|
|
Probe.Discriminator = DLoc->getDiscriminator();
|
|
return Probe;
|
|
}
|
|
|
|
if (isa<CallBase>(&Inst) && !isa<IntrinsicInst>(&Inst))
|
|
return extractProbeFromDiscriminator(Inst);
|
|
|
|
return std::nullopt;
|
|
}
|
|
|
|
void setProbeDistributionFactor(Instruction &Inst, float Factor) {
|
|
assert(Factor >= 0 && Factor <= 1 &&
|
|
"Distribution factor must be in [0, 1.0]");
|
|
if (auto *II = dyn_cast<PseudoProbeInst>(&Inst)) {
|
|
IRBuilder<> Builder(&Inst);
|
|
uint64_t IntFactor = PseudoProbeFullDistributionFactor;
|
|
if (Factor < 1)
|
|
IntFactor *= Factor;
|
|
auto OrigFactor = II->getFactor()->getZExtValue();
|
|
if (IntFactor != OrigFactor)
|
|
II->replaceUsesOfWith(II->getFactor(), Builder.getInt64(IntFactor));
|
|
} else if (isa<CallBase>(&Inst) && !isa<IntrinsicInst>(&Inst)) {
|
|
if (const DebugLoc &DLoc = Inst.getDebugLoc()) {
|
|
const DILocation *DIL = DLoc;
|
|
auto Discriminator = DIL->getDiscriminator();
|
|
if (DILocation::isPseudoProbeDiscriminator(Discriminator)) {
|
|
auto Index =
|
|
PseudoProbeDwarfDiscriminator::extractProbeIndex(Discriminator);
|
|
auto Type =
|
|
PseudoProbeDwarfDiscriminator::extractProbeType(Discriminator);
|
|
auto Attr = PseudoProbeDwarfDiscriminator::extractProbeAttributes(
|
|
Discriminator);
|
|
auto DwarfBaseDiscriminator =
|
|
PseudoProbeDwarfDiscriminator::extractDwarfBaseDiscriminator(
|
|
Discriminator);
|
|
// Round small factors to 0 to avoid over-counting.
|
|
uint32_t IntFactor =
|
|
PseudoProbeDwarfDiscriminator::FullDistributionFactor;
|
|
if (Factor < 1)
|
|
IntFactor *= Factor;
|
|
uint32_t V = PseudoProbeDwarfDiscriminator::packProbeData(
|
|
Index, Type, Attr, IntFactor, DwarfBaseDiscriminator);
|
|
DIL = DIL->cloneWithDiscriminator(V);
|
|
Inst.setDebugLoc(DIL);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
} // namespace llvm
|