1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-24 19:52:54 +01:00
llvm-mirror/lib/Support/BranchProbability.cpp
Chandler Carruth ae65e281f3 Update the file headers across all of the LLVM projects in the monorepo
to reflect the new license.

We understand that people may be surprised that we're moving the header
entirely to discuss the new license. We checked this carefully with the
Foundation's lawyer and we believe this is the correct approach.

Essentially, all code in the project is now made available by the LLVM
project under our new license, so you will see that the license headers
include that license only. Some of our contributors have contributed
code under our old license, and accordingly, we have retained a copy of
our old license notice in the top-level files in each project and
repository.

llvm-svn: 351636
2019-01-19 08:50:56 +00:00

117 lines
3.5 KiB
C++

//===-------------- lib/Support/BranchProbability.cpp -----------*- 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
//
//===----------------------------------------------------------------------===//
//
// This file implements Branch Probability class.
//
//===----------------------------------------------------------------------===//
#include "llvm/Support/BranchProbability.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.h"
#include <cassert>
using namespace llvm;
const uint32_t BranchProbability::D;
raw_ostream &BranchProbability::print(raw_ostream &OS) const {
if (isUnknown())
return OS << "?%";
// Get a percentage rounded to two decimal digits. This avoids
// implementation-defined rounding inside printf.
double Percent = rint(((double)N / D) * 100.0 * 100.0) / 100.0;
return OS << format("0x%08" PRIx32 " / 0x%08" PRIx32 " = %.2f%%", N, D,
Percent);
}
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
LLVM_DUMP_METHOD void BranchProbability::dump() const { print(dbgs()) << '\n'; }
#endif
BranchProbability::BranchProbability(uint32_t Numerator, uint32_t Denominator) {
assert(Denominator > 0 && "Denominator cannot be 0!");
assert(Numerator <= Denominator && "Probability cannot be bigger than 1!");
if (Denominator == D)
N = Numerator;
else {
uint64_t Prob64 =
(Numerator * static_cast<uint64_t>(D) + Denominator / 2) / Denominator;
N = static_cast<uint32_t>(Prob64);
}
}
BranchProbability
BranchProbability::getBranchProbability(uint64_t Numerator,
uint64_t Denominator) {
assert(Numerator <= Denominator && "Probability cannot be bigger than 1!");
// Scale down Denominator to fit in a 32-bit integer.
int Scale = 0;
while (Denominator > UINT32_MAX) {
Denominator >>= 1;
Scale++;
}
return BranchProbability(Numerator >> Scale, Denominator);
}
// If ConstD is not zero, then replace D by ConstD so that division and modulo
// operations by D can be optimized, in case this function is not inlined by the
// compiler.
template <uint32_t ConstD>
static uint64_t scale(uint64_t Num, uint32_t N, uint32_t D) {
if (ConstD > 0)
D = ConstD;
assert(D && "divide by 0");
// Fast path for multiplying by 1.0.
if (!Num || D == N)
return Num;
// Split Num into upper and lower parts to multiply, then recombine.
uint64_t ProductHigh = (Num >> 32) * N;
uint64_t ProductLow = (Num & UINT32_MAX) * N;
// Split into 32-bit digits.
uint32_t Upper32 = ProductHigh >> 32;
uint32_t Lower32 = ProductLow & UINT32_MAX;
uint32_t Mid32Partial = ProductHigh & UINT32_MAX;
uint32_t Mid32 = Mid32Partial + (ProductLow >> 32);
// Carry.
Upper32 += Mid32 < Mid32Partial;
// Check for overflow.
if (Upper32 >= D)
return UINT64_MAX;
uint64_t Rem = (uint64_t(Upper32) << 32) | Mid32;
uint64_t UpperQ = Rem / D;
// Check for overflow.
if (UpperQ > UINT32_MAX)
return UINT64_MAX;
Rem = ((Rem % D) << 32) | Lower32;
uint64_t LowerQ = Rem / D;
uint64_t Q = (UpperQ << 32) + LowerQ;
// Check for overflow.
return Q < LowerQ ? UINT64_MAX : Q;
}
uint64_t BranchProbability::scale(uint64_t Num) const {
return ::scale<D>(Num, N, D);
}
uint64_t BranchProbability::scaleByInverse(uint64_t Num) const {
return ::scale<0>(Num, D, N);
}