| //===- 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 <unordered_set> |
| |
| using namespace llvm; |
| |
| namespace llvm { |
| |
| 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 None; |
| } |
| |
| 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 None; |
| } |
| |
| 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 |