//===- 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 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 extractProbeFromDiscriminator(const Instruction &Inst) { assert(isa(&Inst) && !isa(&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 extractProbe(const Instruction &Inst) { if (const auto *II = dyn_cast(&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(&Inst) && !isa(&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(&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(&Inst) && !isa(&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