| //===- 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 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()) { | |
| const DILocation *DIL = DLoc; | |
| 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; | |
| return Probe; | |
| } | |
| } | |
| 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; | |
| 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); | |
| // 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); | |
| DIL = DIL->cloneWithDiscriminator(V); | |
| Inst.setDebugLoc(DIL); | |
| } | |
| } | |
| } | |
| } | |
| } // namespace llvm |