LLVM 23.0.0git
BranchProbability.h
Go to the documentation of this file.
1//===- BranchProbability.h - Branch Probability Wrapper ---------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Definition of BranchProbability shared by IR and Machine Instructions.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_SUPPORT_BRANCHPROBABILITY_H
14#define LLVM_SUPPORT_BRANCHPROBABILITY_H
15
16#include "llvm/ADT/ADL.h"
19#include <algorithm>
20#include <cassert>
21#include <iterator>
22#include <numeric>
23
24namespace llvm {
25
26class raw_ostream;
27
28// This class represents Branch Probability as a non-negative fraction that is
29// no greater than 1. It uses a fixed-point-like implementation, in which the
30// denominator is always a constant value (here we use 1<<31 for maximum
31// precision).
32class BranchProbability {
33 // Numerator
34 uint32_t N;
35
36 // Denominator, which is a constant value.
37 static constexpr uint32_t D = 1u << 31;
38 static constexpr uint32_t UnknownN = UINT32_MAX;
39
40 // Construct a BranchProbability with only numerator assuming the denominator
41 // is 1<<31. For internal use only.
42 explicit constexpr BranchProbability(uint32_t n) : N(n) {}
43
44public:
45 constexpr BranchProbability() : N(UnknownN) {}
46 constexpr BranchProbability(uint32_t Numerator, uint32_t Denominator)
47 : N(Numerator) {
48 assert(Denominator > 0 && "Denominator cannot be 0!");
49 assert(Numerator <= Denominator && "Probability cannot be bigger than 1!");
50 if (Denominator != D) {
51 uint64_t Prob64 =
52 (Numerator * static_cast<uint64_t>(D) + Denominator / 2) /
53 Denominator;
54 N = static_cast<uint32_t>(Prob64);
55 }
56 }
57
58 bool isZero() const { return N == 0; }
59 bool isOne() const { return N == D; }
60 bool isUnknown() const { return N == UnknownN; }
61
62 static constexpr BranchProbability getZero() { return BranchProbability(0); }
63 static constexpr BranchProbability getOne() { return BranchProbability(D); }
64 static constexpr BranchProbability getUnknown() {
65 return BranchProbability(UnknownN);
66 }
67 // Create a BranchProbability object with the given numerator and 1<<31
68 // as denominator.
69 static constexpr BranchProbability getRaw(uint32_t N) {
70 return BranchProbability(N);
71 }
72 // Create a BranchProbability object from 64-bit integers.
74 uint64_t Denominator);
75 // Create a BranchProbability from a double, which must be from 0 to 1.
77
78 // Normalize given probabilties so that the sum of them becomes approximate
79 // one.
80 template <class ProbabilityIter>
81 static void normalizeProbabilities(ProbabilityIter Begin,
82 ProbabilityIter End);
83
84 template <class ProbabilityContainer>
85 static void normalizeProbabilities(ProbabilityContainer &&R) {
87 }
88
89 uint32_t getNumerator() const { return N; }
90 static uint32_t getDenominator() { return D; }
91 double toDouble() const { return static_cast<double>(N) / D; }
92
93 // Return (1 - Probability).
94 BranchProbability getCompl() const { return BranchProbability(D - N); }
95
97
98#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
99 LLVM_DUMP_METHOD void dump() const;
100#endif
101
102 /// Scale a large integer.
103 ///
104 /// Scales \c Num. Guarantees full precision. Returns the floor of the
105 /// result.
106 ///
107 /// \return \c Num times \c this.
108 LLVM_ABI uint64_t scale(uint64_t Num) const;
109
110 /// Scale a large integer by the inverse.
111 ///
112 /// Scales \c Num by the inverse of \c this. Guarantees full precision.
113 /// Returns the floor of the result.
114 ///
115 /// \return \c Num divided by \c this.
117
118 /// Compute pow(Probability, N).
119 LLVM_ABI BranchProbability pow(unsigned N) const;
120
121 BranchProbability &operator+=(BranchProbability RHS) {
122 assert(N != UnknownN && RHS.N != UnknownN &&
123 "Unknown probability cannot participate in arithmetics.");
124 // Saturate the result in case of overflow.
125 N = (uint64_t(N) + RHS.N > D) ? D : N + RHS.N;
126 return *this;
127 }
128
129 BranchProbability &operator-=(BranchProbability RHS) {
130 assert(N != UnknownN && RHS.N != UnknownN &&
131 "Unknown probability cannot participate in arithmetics.");
132 // Saturate the result in case of underflow.
133 N = N < RHS.N ? 0 : N - RHS.N;
134 return *this;
135 }
136
137 BranchProbability &operator*=(BranchProbability RHS) {
138 assert(N != UnknownN && RHS.N != UnknownN &&
139 "Unknown probability cannot participate in arithmetics.");
140 N = (static_cast<uint64_t>(N) * RHS.N + D / 2) / D;
141 return *this;
142 }
143
144 BranchProbability &operator*=(uint32_t RHS) {
145 assert(N != UnknownN &&
146 "Unknown probability cannot participate in arithmetics.");
147 N = (uint64_t(N) * RHS > D) ? D : N * RHS;
148 return *this;
149 }
150
151 BranchProbability &operator/=(BranchProbability RHS) {
152 assert(N != UnknownN && RHS.N != UnknownN &&
153 "Unknown probability cannot participate in arithmetics.");
154 N = (static_cast<uint64_t>(N) * D + RHS.N / 2) / RHS.N;
155 return *this;
156 }
157
158 BranchProbability &operator/=(uint32_t RHS) {
159 assert(N != UnknownN &&
160 "Unknown probability cannot participate in arithmetics.");
161 assert(RHS > 0 && "The divider cannot be zero.");
162 N /= RHS;
163 return *this;
164 }
165
166 BranchProbability operator+(BranchProbability RHS) const {
167 BranchProbability Prob(*this);
168 Prob += RHS;
169 return Prob;
170 }
171
172 BranchProbability operator-(BranchProbability RHS) const {
173 BranchProbability Prob(*this);
174 Prob -= RHS;
175 return Prob;
176 }
177
178 BranchProbability operator*(BranchProbability RHS) const {
179 BranchProbability Prob(*this);
180 Prob *= RHS;
181 return Prob;
182 }
183
184 BranchProbability operator*(uint32_t RHS) const {
185 BranchProbability Prob(*this);
186 Prob *= RHS;
187 return Prob;
188 }
189
190 BranchProbability operator/(BranchProbability RHS) const {
191 BranchProbability Prob(*this);
192 Prob /= RHS;
193 return Prob;
194 }
195
196 BranchProbability operator/(uint32_t RHS) const {
197 BranchProbability Prob(*this);
198 Prob /= RHS;
199 return Prob;
200 }
201
202 bool operator==(BranchProbability RHS) const { return N == RHS.N; }
203 bool operator!=(BranchProbability RHS) const { return !(*this == RHS); }
204
205 bool operator<(BranchProbability RHS) const {
206 assert(N != UnknownN && RHS.N != UnknownN &&
207 "Unknown probability cannot participate in comparisons.");
208 return N < RHS.N;
209 }
210
211 bool operator>(BranchProbability RHS) const {
212 assert(N != UnknownN && RHS.N != UnknownN &&
213 "Unknown probability cannot participate in comparisons.");
214 return RHS < *this;
215 }
216
217 bool operator<=(BranchProbability RHS) const {
218 assert(N != UnknownN && RHS.N != UnknownN &&
219 "Unknown probability cannot participate in comparisons.");
220 return !(RHS < *this);
221 }
222
223 bool operator>=(BranchProbability RHS) const {
224 assert(N != UnknownN && RHS.N != UnknownN &&
225 "Unknown probability cannot participate in comparisons.");
226 return !(*this < RHS);
227 }
228};
229
231 return Prob.print(OS);
232}
233
234template <class ProbabilityIter>
236 ProbabilityIter End) {
237 if (Begin == End)
238 return;
239
240 unsigned UnknownProbCount = 0;
241 uint64_t Sum = std::accumulate(Begin, End, uint64_t(0),
242 [&](uint64_t S, const BranchProbability &BP) {
243 if (!BP.isUnknown())
244 return S + BP.N;
245 UnknownProbCount++;
246 return S;
247 });
248
249 if (UnknownProbCount > 0) {
250 BranchProbability ProbForUnknown = BranchProbability::getZero();
251 // If the sum of all known probabilities is less than one, evenly distribute
252 // the complement of sum to unknown probabilities. Otherwise, set unknown
253 // probabilities to zeros and continue to normalize known probabilities.
255 ProbForUnknown = BranchProbability::getRaw(
256 (BranchProbability::getDenominator() - Sum) / UnknownProbCount);
257
258 std::replace_if(Begin, End,
259 [](const BranchProbability &BP) { return BP.isUnknown(); },
260 ProbForUnknown);
261
263 return;
264 }
265
266 if (Sum == 0) {
267 BranchProbability BP(1, std::distance(Begin, End));
268 std::fill(Begin, End, BP);
269 return;
270 }
271
272 for (auto I = Begin; I != End; ++I)
273 I->N = (I->N * uint64_t(D) + Sum / 2) / Sum;
274}
275
276}
277
278#endif
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
#define LLVM_ABI
Definition Compiler.h:215
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Definition Compiler.h:672
#define I(x, y, z)
Definition MD5.cpp:57
Value * RHS
LLVM_DUMP_METHOD void dump() const
static LLVM_ABI BranchProbability getBranchProbability(uint64_t Numerator, uint64_t Denominator)
static constexpr BranchProbability getOne()
BranchProbability operator-(BranchProbability RHS) const
BranchProbability & operator-=(BranchProbability RHS)
constexpr BranchProbability(uint32_t Numerator, uint32_t Denominator)
static uint32_t getDenominator()
bool operator<(BranchProbability RHS) const
bool operator!=(BranchProbability RHS) const
bool operator==(BranchProbability RHS) const
BranchProbability operator/(uint32_t RHS) const
BranchProbability & operator/=(BranchProbability RHS)
LLVM_ABI BranchProbability pow(unsigned N) const
Compute pow(Probability, N).
bool operator<=(BranchProbability RHS) const
LLVM_ABI raw_ostream & print(raw_ostream &OS) const
BranchProbability & operator*=(BranchProbability RHS)
static constexpr BranchProbability getUnknown()
LLVM_ABI uint64_t scaleByInverse(uint64_t Num) const
Scale a large integer by the inverse.
static constexpr BranchProbability getZero()
BranchProbability operator*(BranchProbability RHS) const
BranchProbability operator/(BranchProbability RHS) const
uint32_t getNumerator() const
LLVM_ABI uint64_t scale(uint64_t Num) const
Scale a large integer.
static void normalizeProbabilities(ProbabilityContainer &&R)
BranchProbability operator+(BranchProbability RHS) const
bool operator>=(BranchProbability RHS) const
BranchProbability operator*(uint32_t RHS) const
BranchProbability & operator*=(uint32_t RHS)
BranchProbability getCompl() const
BranchProbability & operator+=(BranchProbability RHS)
BranchProbability & operator/=(uint32_t RHS)
static constexpr BranchProbability getRaw(uint32_t N)
bool operator>(BranchProbability RHS) const
static void normalizeProbabilities(ProbabilityIter Begin, ProbabilityIter End)
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
This is an optimization pass for GlobalISel generic memory operations.
constexpr auto adl_begin(RangeT &&range) -> decltype(adl_detail::begin_impl(std::forward< RangeT >(range)))
Returns the begin iterator to range using std::begin and function found through Argument-Dependent Lo...
Definition ADL.h:78
constexpr auto adl_end(RangeT &&range) -> decltype(adl_detail::end_impl(std::forward< RangeT >(range)))
Returns the end iterator to range using std::end and functions found through Argument-Dependent Looku...
Definition ADL.h:86
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
#define N