Path: blob/main/contrib/llvm-project/llvm/lib/Support/BranchProbability.cpp
35232 views
//===-------------- lib/Support/BranchProbability.cpp -----------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file implements Branch Probability class.9//10//===----------------------------------------------------------------------===//1112#include "llvm/Support/BranchProbability.h"13#include "llvm/Config/llvm-config.h"14#include "llvm/Support/Debug.h"15#include "llvm/Support/Format.h"16#include "llvm/Support/raw_ostream.h"17#include <cassert>18#include <cmath>1920using namespace llvm;2122constexpr uint32_t BranchProbability::D;2324raw_ostream &BranchProbability::print(raw_ostream &OS) const {25if (isUnknown())26return OS << "?%";2728// Get a percentage rounded to two decimal digits. This avoids29// implementation-defined rounding inside printf.30double Percent = rint(((double)N / D) * 100.0 * 100.0) / 100.0;31return OS << format("0x%08" PRIx32 " / 0x%08" PRIx32 " = %.2f%%", N, D,32Percent);33}3435#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)36LLVM_DUMP_METHOD void BranchProbability::dump() const { print(dbgs()) << '\n'; }37#endif3839BranchProbability::BranchProbability(uint32_t Numerator, uint32_t Denominator) {40assert(Denominator > 0 && "Denominator cannot be 0!");41assert(Numerator <= Denominator && "Probability cannot be bigger than 1!");42if (Denominator == D)43N = Numerator;44else {45uint64_t Prob64 =46(Numerator * static_cast<uint64_t>(D) + Denominator / 2) / Denominator;47N = static_cast<uint32_t>(Prob64);48}49}5051BranchProbability52BranchProbability::getBranchProbability(uint64_t Numerator,53uint64_t Denominator) {54assert(Numerator <= Denominator && "Probability cannot be bigger than 1!");55// Scale down Denominator to fit in a 32-bit integer.56int Scale = 0;57while (Denominator > UINT32_MAX) {58Denominator >>= 1;59Scale++;60}61return BranchProbability(Numerator >> Scale, Denominator);62}6364// If ConstD is not zero, then replace D by ConstD so that division and modulo65// operations by D can be optimized, in case this function is not inlined by the66// compiler.67template <uint32_t ConstD>68static uint64_t scale(uint64_t Num, uint32_t N, uint32_t D) {69if (ConstD > 0)70D = ConstD;7172assert(D && "divide by 0");7374// Fast path for multiplying by 1.0.75if (!Num || D == N)76return Num;7778// Split Num into upper and lower parts to multiply, then recombine.79uint64_t ProductHigh = (Num >> 32) * N;80uint64_t ProductLow = (Num & UINT32_MAX) * N;8182// Split into 32-bit digits.83uint32_t Upper32 = ProductHigh >> 32;84uint32_t Lower32 = ProductLow & UINT32_MAX;85uint32_t Mid32Partial = ProductHigh & UINT32_MAX;86uint32_t Mid32 = Mid32Partial + (ProductLow >> 32);8788// Carry.89Upper32 += Mid32 < Mid32Partial;9091uint64_t Rem = (uint64_t(Upper32) << 32) | Mid32;92uint64_t UpperQ = Rem / D;9394// Check for overflow.95if (UpperQ > UINT32_MAX)96return UINT64_MAX;9798Rem = ((Rem % D) << 32) | Lower32;99uint64_t LowerQ = Rem / D;100uint64_t Q = (UpperQ << 32) + LowerQ;101102// Check for overflow.103return Q < LowerQ ? UINT64_MAX : Q;104}105106uint64_t BranchProbability::scale(uint64_t Num) const {107return ::scale<D>(Num, N, D);108}109110uint64_t BranchProbability::scaleByInverse(uint64_t Num) const {111return ::scale<0>(Num, D, N);112}113114115