13d4e64b0SAndrew Trick //===-------------- lib/Support/BranchProbability.cpp -----------*- C++ -*-===//
23d4e64b0SAndrew Trick //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
63d4e64b0SAndrew Trick //
73d4e64b0SAndrew Trick //===----------------------------------------------------------------------===//
83d4e64b0SAndrew Trick //
93d4e64b0SAndrew Trick // This file implements Branch Probability class.
103d4e64b0SAndrew Trick //
113d4e64b0SAndrew Trick //===----------------------------------------------------------------------===//
123d4e64b0SAndrew Trick
133d4e64b0SAndrew Trick #include "llvm/Support/BranchProbability.h"
14432a3883SNico Weber #include "llvm/Config/llvm-config.h"
153d4e64b0SAndrew Trick #include "llvm/Support/Debug.h"
16cc0ed6baSBenjamin Kramer #include "llvm/Support/Format.h"
173d4e64b0SAndrew Trick #include "llvm/Support/raw_ostream.h"
1815ea0163SCong Hou #include <cassert>
19*e8423dbfSSimon Pilgrim #include <cmath>
203d4e64b0SAndrew Trick
213d4e64b0SAndrew Trick using namespace llvm;
223d4e64b0SAndrew Trick
23b198f1f8SBenjamin Kramer constexpr uint32_t BranchProbability::D;
242a63631aSBenjamin Kramer
print(raw_ostream & OS) const25bdc1e2abSDuncan P. N. Exon Smith raw_ostream &BranchProbability::print(raw_ostream &OS) const {
26d97c100dSCong Hou if (isUnknown())
27d97c100dSCong Hou return OS << "?%";
28d97c100dSCong Hou
292a63631aSBenjamin Kramer // Get a percentage rounded to two decimal digits. This avoids
302a63631aSBenjamin Kramer // implementation-defined rounding inside printf.
312a63631aSBenjamin Kramer double Percent = rint(((double)N / D) * 100.0 * 100.0) / 100.0;
32d97c100dSCong Hou return OS << format("0x%08" PRIx32 " / 0x%08" PRIx32 " = %.2f%%", N, D,
33d97c100dSCong Hou Percent);
343d4e64b0SAndrew Trick }
353d4e64b0SAndrew Trick
36615eb470SAaron Ballman #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const37eb2a2546SYaron Keren LLVM_DUMP_METHOD void BranchProbability::dump() const { print(dbgs()) << '\n'; }
388c209aa8SMatthias Braun #endif
393d4e64b0SAndrew Trick
BranchProbability(uint32_t Numerator,uint32_t Denominator)4015ea0163SCong Hou BranchProbability::BranchProbability(uint32_t Numerator, uint32_t Denominator) {
4115ea0163SCong Hou assert(Denominator > 0 && "Denominator cannot be 0!");
4215ea0163SCong Hou assert(Numerator <= Denominator && "Probability cannot be bigger than 1!");
4315ea0163SCong Hou if (Denominator == D)
4415ea0163SCong Hou N = Numerator;
4515ea0163SCong Hou else {
4615ea0163SCong Hou uint64_t Prob64 =
4715ea0163SCong Hou (Numerator * static_cast<uint64_t>(D) + Denominator / 2) / Denominator;
4815ea0163SCong Hou N = static_cast<uint32_t>(Prob64);
4915ea0163SCong Hou }
5015ea0163SCong Hou }
5115ea0163SCong Hou
52d97c100dSCong Hou BranchProbability
getBranchProbability(uint64_t Numerator,uint64_t Denominator)53d97c100dSCong Hou BranchProbability::getBranchProbability(uint64_t Numerator,
54d97c100dSCong Hou uint64_t Denominator) {
55d97c100dSCong Hou assert(Numerator <= Denominator && "Probability cannot be bigger than 1!");
56d97c100dSCong Hou // Scale down Denominator to fit in a 32-bit integer.
57d97c100dSCong Hou int Scale = 0;
58d97c100dSCong Hou while (Denominator > UINT32_MAX) {
59d97c100dSCong Hou Denominator >>= 1;
60d97c100dSCong Hou Scale++;
61d97c100dSCong Hou }
62d97c100dSCong Hou return BranchProbability(Numerator >> Scale, Denominator);
63d97c100dSCong Hou }
64d97c100dSCong Hou
6515ea0163SCong Hou // If ConstD is not zero, then replace D by ConstD so that division and modulo
6615ea0163SCong Hou // operations by D can be optimized, in case this function is not inlined by the
6715ea0163SCong Hou // compiler.
6815ea0163SCong Hou template <uint32_t ConstD>
scale(uint64_t Num,uint32_t N,uint32_t D)692a63631aSBenjamin Kramer static uint64_t scale(uint64_t Num, uint32_t N, uint32_t D) {
7015ea0163SCong Hou if (ConstD > 0)
7115ea0163SCong Hou D = ConstD;
7215ea0163SCong Hou
73415e7656SDuncan P. N. Exon Smith assert(D && "divide by 0");
74415e7656SDuncan P. N. Exon Smith
75415e7656SDuncan P. N. Exon Smith // Fast path for multiplying by 1.0.
76415e7656SDuncan P. N. Exon Smith if (!Num || D == N)
77415e7656SDuncan P. N. Exon Smith return Num;
78415e7656SDuncan P. N. Exon Smith
79415e7656SDuncan P. N. Exon Smith // Split Num into upper and lower parts to multiply, then recombine.
80415e7656SDuncan P. N. Exon Smith uint64_t ProductHigh = (Num >> 32) * N;
81415e7656SDuncan P. N. Exon Smith uint64_t ProductLow = (Num & UINT32_MAX) * N;
82415e7656SDuncan P. N. Exon Smith
83415e7656SDuncan P. N. Exon Smith // Split into 32-bit digits.
84415e7656SDuncan P. N. Exon Smith uint32_t Upper32 = ProductHigh >> 32;
85415e7656SDuncan P. N. Exon Smith uint32_t Lower32 = ProductLow & UINT32_MAX;
86415e7656SDuncan P. N. Exon Smith uint32_t Mid32Partial = ProductHigh & UINT32_MAX;
87415e7656SDuncan P. N. Exon Smith uint32_t Mid32 = Mid32Partial + (ProductLow >> 32);
88415e7656SDuncan P. N. Exon Smith
89415e7656SDuncan P. N. Exon Smith // Carry.
90415e7656SDuncan P. N. Exon Smith Upper32 += Mid32 < Mid32Partial;
91415e7656SDuncan P. N. Exon Smith
92415e7656SDuncan P. N. Exon Smith uint64_t Rem = (uint64_t(Upper32) << 32) | Mid32;
93415e7656SDuncan P. N. Exon Smith uint64_t UpperQ = Rem / D;
94415e7656SDuncan P. N. Exon Smith
95415e7656SDuncan P. N. Exon Smith // Check for overflow.
96415e7656SDuncan P. N. Exon Smith if (UpperQ > UINT32_MAX)
97415e7656SDuncan P. N. Exon Smith return UINT64_MAX;
98415e7656SDuncan P. N. Exon Smith
99415e7656SDuncan P. N. Exon Smith Rem = ((Rem % D) << 32) | Lower32;
100415e7656SDuncan P. N. Exon Smith uint64_t LowerQ = Rem / D;
101415e7656SDuncan P. N. Exon Smith uint64_t Q = (UpperQ << 32) + LowerQ;
102415e7656SDuncan P. N. Exon Smith
103415e7656SDuncan P. N. Exon Smith // Check for overflow.
104415e7656SDuncan P. N. Exon Smith return Q < LowerQ ? UINT64_MAX : Q;
105415e7656SDuncan P. N. Exon Smith }
106415e7656SDuncan P. N. Exon Smith
scale(uint64_t Num) const107415e7656SDuncan P. N. Exon Smith uint64_t BranchProbability::scale(uint64_t Num) const {
10815ea0163SCong Hou return ::scale<D>(Num, N, D);
109415e7656SDuncan P. N. Exon Smith }
110415e7656SDuncan P. N. Exon Smith
scaleByInverse(uint64_t Num) const111415e7656SDuncan P. N. Exon Smith uint64_t BranchProbability::scaleByInverse(uint64_t Num) const {
11215ea0163SCong Hou return ::scale<0>(Num, D, N);
113415e7656SDuncan P. N. Exon Smith }
114