From a26ec886a3a4d9d317262861d7a3de4f64bad71c Mon Sep 17 00:00:00 2001 From: Jakub Staszak Date: Mon, 25 Jul 2011 22:24:51 +0000 Subject: [PATCH] Add BlockFrequency class. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@135992 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Support/BlockFrequency.h | 64 ++++++++++++++ lib/Support/BlockFrequency.cpp | 120 ++++++++++++++++++++++++++ lib/Support/CMakeLists.txt | 1 + 3 files changed, 185 insertions(+) create mode 100644 include/llvm/Support/BlockFrequency.h create mode 100644 lib/Support/BlockFrequency.cpp diff --git a/include/llvm/Support/BlockFrequency.h b/include/llvm/Support/BlockFrequency.h new file mode 100644 index 00000000000..b133c961f63 --- /dev/null +++ b/include/llvm/Support/BlockFrequency.h @@ -0,0 +1,64 @@ +//===-------- BlockFrequency.h - Block Frequency Wrapper --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements Block Frequency class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_BLOCKFREQUENCY_H +#define LLVM_SUPPORT_BLOCKFREQUENCY_H + +namespace llvm { + +class raw_ostream; +class BranchProbability; + +// This class represents Block Frequency as a 64-bit value. +class BlockFrequency { + + uint64_t Frequency; + + static void mult96bit(uint64_t freq, uint32_t N, uint64_t W[2]); + static uint64_t div96bit(uint64_t W[2], uint32_t D); + +public: + BlockFrequency(uint64_t Freq = 0) : Frequency(Freq) { } + + uint64_t getFrequency() const { return Frequency; } + + BlockFrequency &operator*=(const BranchProbability &Prob); + const BlockFrequency operator*(const BranchProbability &Prob) const; + + BlockFrequency &operator+=(const BlockFrequency &Freq); + const BlockFrequency operator+(const BlockFrequency &Freq) const; + + bool operator<(const BlockFrequency &RHS) const { + return Frequency < RHS.Frequency; + } + + bool operator<=(const BlockFrequency &RHS) const { + return Frequency <= RHS.Frequency; + } + + bool operator>(const BlockFrequency &RHS) const { + return Frequency > RHS.Frequency; + } + + bool operator>=(const BlockFrequency &RHS) const { + return Frequency >= RHS.Frequency; + } + + void print(raw_ostream &OS) const; +}; + +raw_ostream &operator<<(raw_ostream &OS, const BlockFrequency &Freq); + +} + +#endif diff --git a/lib/Support/BlockFrequency.cpp b/lib/Support/BlockFrequency.cpp new file mode 100644 index 00000000000..87e1b2dba06 --- /dev/null +++ b/lib/Support/BlockFrequency.cpp @@ -0,0 +1,120 @@ +//====--------------- lib/Support/BlockFrequency.cpp -----------*- C++ -*-====// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements Block Frequency class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/BranchProbability.h" +#include "llvm/Support/BlockFrequency.h" +#include "llvm/Support/raw_ostream.h" +#include + +using namespace llvm; + +/// mult96bit - Multiply FREQ by N and store result in W array. +void BlockFrequency::mult96bit(uint64_t freq, uint32_t N, uint64_t W[2]) { + uint64_t u0 = freq & UINT32_MAX; + uint64_t u1 = freq >> 32; + + // Represent 96-bit value as w[2]:w[1]:w[0]; + uint32_t w[3] = { 0, 0, 0 }; + + uint64_t t = u0 * N; + uint64_t k = t >> 32; + w[0] = t; + t = u1 * N + k; + w[1] = t; + w[2] = t >> 32; + + // W[1] - higher bits. + // W[0] - lower bits. + W[0] = w[0] + ((uint64_t) w[1] << 32); + W[1] = w[2]; +} + + +/// div96bit - Divide 96-bit value stored in W array by D. Return 64-bit frequency. +uint64_t BlockFrequency::div96bit(uint64_t W[2], uint32_t D) { + uint64_t y = W[0]; + uint64_t x = W[1]; + + for (int i = 1; i <= 64; ++i) { + uint32_t t = (int)x >> 31; + x = (x << 1) | (y >> 63); + y = y << 1; + if ((x | t) >= D) { + x -= D; + ++y; + } + } + + return y; +} + +BlockFrequency &BlockFrequency::operator*=(const BranchProbability &Prob) { + uint32_t n = Prob.getNumerator(); + uint32_t d = Prob.getDenominator(); + + assert(n <= d && "Probability must be less or equal to 1."); + + // If we can overflow use 96-bit operations. + if (n > 0 && Frequency > UINT64_MAX / n) { + // 96-bit value represented as W[1]:W[0]. + uint64_t W[2]; + + // Probability is less or equal to 1 which means that results must fit + // 64-bit. + mult96bit(Frequency, n, W); + Frequency = div96bit(W, d); + return *this; + } + + Frequency *= n; + Frequency /= d; + return *this; +} + +const BlockFrequency +BlockFrequency::operator*(const BranchProbability &Prob) const { + BlockFrequency Freq(Frequency); + Freq *= Prob; + return Freq; +} + +BlockFrequency &BlockFrequency::operator+=(const BlockFrequency &Freq) { + uint64_t Before = Freq.Frequency; + Frequency += Freq.Frequency; + + // If overflow, set frequency to the maximum value. + if (Frequency < Before) + Frequency = UINT64_MAX; + + return *this; +} + +const BlockFrequency +BlockFrequency::operator+(const BlockFrequency &Prob) const { + BlockFrequency Freq(Frequency); + Freq += Prob; + return Freq; +} + +void BlockFrequency::print(raw_ostream &OS) const { + OS << Frequency; +} + +namespace llvm { + +raw_ostream &operator<<(raw_ostream &OS, const BlockFrequency &Freq) { + Freq.print(OS); + return OS; +} + +} diff --git a/lib/Support/CMakeLists.txt b/lib/Support/CMakeLists.txt index 9ba0f7e87d9..64eeccac83e 100644 --- a/lib/Support/CMakeLists.txt +++ b/lib/Support/CMakeLists.txt @@ -9,6 +9,7 @@ add_llvm_library(LLVMSupport APInt.cpp APSInt.cpp Allocator.cpp + BlockFrequency.cpp BranchProbability.cpp circular_raw_ostream.cpp CommandLine.cpp