blob: 39a16586f4678ecf2fd4a798f7fdae8812c544ab [file] [log] [blame]
// Copyright 2013 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// The ApplicationProfile class is used to hold metrics taken by instrumenting
// and running the application. Profile guided optimisations use this class to
// retrieve information about runtime metrics.
//
// Example:
// ApplicationProfile profile(&image_layout);
// profile.ImportFrequencies(frequencies);
// profile.ComputeGlobalProfile();
//
// foreach block in block_graph {
// ApplicationProfile::BlockProfile* bp = profile.GetBlockProfile();
// if (bp->percentile() < 0.05)
// LOG(INFO) << "This function is probably hot: " << block->name();
// }
//
// Transformations are responsible for updating metrics when possible.
#ifndef SYZYGY_OPTIMIZE_APPLICATION_PROFILE_H_
#define SYZYGY_OPTIMIZE_APPLICATION_PROFILE_H_
#include <map>
#include "syzygy/block_graph/basic_block.h"
#include "syzygy/block_graph/basic_block_subgraph.h"
#include "syzygy/grinder/basic_block_util.h"
#include "syzygy/pe/image_layout.h"
namespace optimize {
// Forward declaration.
class SubGraphProfile;
// This class holds profile information for a block_graph.
class ApplicationProfile {
public:
typedef block_graph::BasicBlockSubGraph BasicBlockSubGraph;
typedef block_graph::BlockGraph BlockGraph;
typedef grinder::basic_block_util::IndexedFrequencyMap IndexedFrequencyMap;
typedef grinder::basic_block_util::EntryCountType EntryCountType;
typedef pe::ImageLayout ImageLayout;
// Forward declaration.
class BlockProfile;
typedef std::map<BlockGraph::BlockId, BlockProfile> ProfileMap;
// Constructor.
// @param image_layout The image layout.
// @note |image_layout| must remains alive until this class get destroyed.
explicit ApplicationProfile(const ImageLayout* image_layout);
// Retrieve the profile for a given block.
// @param block the block to find profile information.
// @returns the profile of the block or singleton empty profile when there is
// no information available.
const BlockProfile* GetBlockProfile(const BlockGraph::Block* block) const;
// @returns the global temperature of the basic block;
// @note Invalid until the call to ComputeGlobalProfile.
double global_temperature() const { return global_temperature_; }
// Compute global profile and update block profiles contribution.
// @returns true on success, false otherwise.
// @note BlockProfile.percentile() and GetGlobalTemperature() aren't valid
// before this function is called.
bool ComputeGlobalProfile();
// Compute profile information for basic blocks of a subgraph.
// @param subgraph subgraph for which to calculate profiler information.
// @param profile receives the profile information.
void ComputeSubGraphProfile(const BasicBlockSubGraph* subgraph,
std::unique_ptr<SubGraphProfile>* profile);
// Import the frequency information of an application.
// @param frequencies the branches frequencies.
// @returns true on success, false otherwise.
// @note This function should only be called once.
// TODO(etienneb): Support multiple importation.
bool ImportFrequencies(const IndexedFrequencyMap& frequencies);
protected:
// These are protected so that they can be accessed by unittests.
// Frequency information for the whole block graph (includes basic block
// information).
IndexedFrequencyMap frequencies_;
// The image layout to which the profile data applies.
const ImageLayout* image_layout_;
// The global temperature of the block graph.
double global_temperature_;
// The profiles for blocks of the block_graph.
ProfileMap profiles_;
// A empty profile used for all block never executed.
std::unique_ptr<BlockProfile> empty_profile_;
private:
DISALLOW_COPY_AND_ASSIGN(ApplicationProfile);
};
// This class contains profile information for a block (function).
class ApplicationProfile::BlockProfile {
public:
// Default constructor. Produce information for a block never executed.
BlockProfile()
: count_(0), temperature_(0), percentile_(0) {
}
// Constructor.
// @param count the block entry count.
// @param temperature the temperature of a block is the sum of the basic
// blocks entry counts.
BlockProfile(EntryCountType count, double temperature)
: count_(count), temperature_(temperature), percentile_(0) {
}
// Accessors.
// @{
EntryCountType count() const { return count_; }
double temperature() const { return temperature_; }
double percentile() const { return percentile_; }
void set_percentile(double p) { percentile_ = p; }
// @}
protected:
// The entry count of the block.
EntryCountType count_;
// The temperature of the whole block.
double temperature_;
// The rank of this block's temperature as compared to all blocks in the block
// graph. The value is between 0 and 1.
double percentile_;
};
// This class contains profile information for a subgraph.
class SubGraphProfile {
public:
// Forward declaration.
class BasicBlockProfile;
typedef block_graph::BasicCodeBlock BasicCodeBlock;
typedef grinder::basic_block_util::EntryCountType EntryCountType;
typedef std::map<const BasicCodeBlock*, BasicBlockProfile>
BasicBlockProfileMap;
// Constructor
SubGraphProfile();
// Retrieve the profile for a given basic block.
// @param block the basic block to find profile information.
// @returns the profile of the basic block or singleton empty profile when
// there is no information available.
const BasicBlockProfile* GetBasicBlockProfile(
const BasicCodeBlock* block) const;
protected:
// These are protected so that they can be accessed by unittests.
// Allow ApplicationProfile to create and modify instances of this class.
friend class ApplicationProfile;
// Map basic blocks to their profile.
BasicBlockProfileMap basic_blocks_;
// An empty profile used for all basic blocks never executed.
std::unique_ptr<BasicBlockProfile> empty_profile_;
};
// This class contains profile information for a basic-block.
class SubGraphProfile::BasicBlockProfile {
public:
typedef block_graph::BasicCodeBlock BasicCodeBlock;
typedef std::map<const BasicCodeBlock*, EntryCountType> SuccessorsCountMap;
BasicBlockProfile() : count_(0), mispredicted_(0) {
}
// Returns the entry count of a basic block.
// @returns the basic block entry count.
EntryCountType count() const { return count_; }
// Returns the ratio of misprediction to jumps to successors.
// @returns the basic block entry count ratio.
double GetMispredictedRatio() const;
// Returns the number of times a given successor was taken from this basic
// block.
// @param successor the successor to retrieve the corresponding count.
// @returns the arc count between this block and the successor.
EntryCountType GetSuccessorCount(const BasicCodeBlock* successor) const;
// Returns the ratio of branch taken from the basic block to |successor|.
// @returns the successors ratio for @successor.
double GetSuccessorRatio(const BasicCodeBlock* successor) const;
protected:
// These are protected so that they can be accessed by unittests.
// Allow ApplicationProfile to modify private fields.
friend class ApplicationProfile;
// The entry count of the basic block.
EntryCountType count_;
// The count of mispredictions to jumps to successors.
EntryCountType mispredicted_;
// Maps successors to the taken count.
SuccessorsCountMap successors_;
};
} // namespace optimize
#endif // SYZYGY_OPTIMIZE_APPLICATION_PROFILE_H_