aboutsummaryrefslogtreecommitdiff
path: root/llvm/include/llvm/IR/PseudoProbe.h
blob: 5c652b14650d572d68672df91a271abaf2a769d7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
//===- PseudoProbe.h - Pseudo Probe IR Helpers ------------------*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// Pseudo probe IR intrinsic and dwarf discriminator manipulation routines.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_IR_PSEUDOPROBE_H
#define LLVM_IR_PSEUDOPROBE_H

#include "llvm/Support/Compiler.h"
#include <cassert>
#include <cstdint>
#include <limits>
#include <optional>

namespace llvm {

class Instruction;

constexpr const char *PseudoProbeDescMetadataName = "llvm.pseudo_probe_desc";

enum class PseudoProbeReservedId { Invalid = 0, Last = Invalid };

enum class PseudoProbeType { Block = 0, IndirectCall, DirectCall };

enum class PseudoProbeAttributes {
  Reserved = 0x1,
  Sentinel = 0x2,         // A place holder for split function entry address.
  HasDiscriminator = 0x4, // for probes with a discriminator
};

// The saturated distrution factor representing 100% for block probes.
constexpr static uint64_t PseudoProbeFullDistributionFactor =
    std::numeric_limits<uint64_t>::max();

struct PseudoProbeDwarfDiscriminator {
public:
  // The following APIs encodes/decodes per-probe information to/from a
  // 32-bit integer which is organized as:
  //  [2:0] - 0x7, this is reserved for regular discriminator,
  //          see DWARF discriminator encoding rule
  //  if the [28:28] bit is zero:
  //    [18:3] for probe id.
  //  else:
  //    [15:3] for probe id, [18:16] for dwarf base discriminator.
  //  [25:19] - probe distribution factor
  //  [27:26] - probe type, see PseudoProbeType
  //  [28:28] - indicates whether dwarf base discriminator is encoded.
  //  [30:29] - reserved for probe attributes
  static uint32_t
  packProbeData(uint32_t Index, uint32_t Type, uint32_t Flags, uint32_t Factor,
                std::optional<uint32_t> DwarfBaseDiscriminator) {
    assert(Index <= 0xFFFF && "Probe index too big to encode, exceeding 2^16");
    assert(Type <= 0x3 && "Probe type too big to encode, exceeding 3");
    assert(Flags <= 0x7);
    assert(Factor <= 100 &&
           "Probe distribution factor too big to encode, exceeding 100");
    uint32_t V = (Index << 3) | (Factor << 19) | (Type << 26) | 0x7;
    // If both the probe id and dwarf base discriminator is small, the probe id
    // space is shared with the dwarf base discriminator, this is to make the
    // probe-based build compatible with the dwarf-based profile.
    // Pack the dwarf base discriminator into [18:16] and set the [28:28] bit.
    if (Index <= 0x1FFF && DwarfBaseDiscriminator &&
        *DwarfBaseDiscriminator <= 0x7)
      V |= (1 << 28) | (*DwarfBaseDiscriminator << 16);
    return V;
  }

  static uint32_t extractProbeIndex(uint32_t Value) {
    if (isDwarfBaseDiscriminatorEncoded(Value))
      return (Value >> 3) & 0x1FFF;
    return (Value >> 3) & 0xFFFF;
  }

  static std::optional<uint32_t> extractDwarfBaseDiscriminator(uint32_t Value) {
    if (isDwarfBaseDiscriminatorEncoded(Value))
      return (Value >> 16) & 0x7;
    return std::nullopt;
  }

  static bool isDwarfBaseDiscriminatorEncoded(uint32_t Value) {
    return Value & 0x10000000;
  }

  static uint32_t extractProbeType(uint32_t Value) {
    return (Value >> 26) & 0x3;
  }

  static uint32_t extractProbeAttributes(uint32_t Value) {
    return (Value >> 29) & 0x7;
  }

  static uint32_t extractProbeFactor(uint32_t Value) {
    return (Value >> 19) & 0x7F;
  }

  // The saturated distrution factor representing 100% for callsites.
  constexpr static uint8_t FullDistributionFactor = 100;
};

class PseudoProbeDescriptor {
  uint64_t FunctionGUID;
  uint64_t FunctionHash;

public:
  PseudoProbeDescriptor(uint64_t GUID, uint64_t Hash)
      : FunctionGUID(GUID), FunctionHash(Hash) {}
  uint64_t getFunctionGUID() const { return FunctionGUID; }
  uint64_t getFunctionHash() const { return FunctionHash; }
};

struct PseudoProbe {
  uint32_t Id;
  uint32_t Type;
  uint32_t Attr;
  uint32_t Discriminator;
  // Distribution factor that estimates the portion of the real execution count.
  // A saturated distribution factor stands for 1.0 or 100%. A pesudo probe has
  // a factor with the value ranged from 0.0 to 1.0.
  float Factor;
};

static inline bool isSentinelProbe(uint32_t Flags) {
  return Flags & (uint32_t)PseudoProbeAttributes::Sentinel;
}

static inline bool hasDiscriminator(uint32_t Flags) {
  return Flags & (uint32_t)PseudoProbeAttributes::HasDiscriminator;
}

LLVM_ABI std::optional<PseudoProbe> extractProbe(const Instruction &Inst);

LLVM_ABI void setProbeDistributionFactor(Instruction &Inst, float Factor);
} // end namespace llvm

#endif // LLVM_IR_PSEUDOPROBE_H