forked from OSchip/llvm-project
[BOLT] Towards FunctionLayout const-correctness
A const-qualified reference to function layout allows accessing non-const qualified basic blocks on a const-qualified function. This patch adds or removes const-qualifiers where necessary to indicate where basic blocks are used in a non-const manner. Reviewed By: rafauler Differential Revision: https://reviews.llvm.org/D132049
This commit is contained in:
parent
13cb085ca1
commit
587d265342
|
@ -424,6 +424,9 @@ public:
|
||||||
/// Return branch info corresponding to an edge going to \p Succ basic block.
|
/// Return branch info corresponding to an edge going to \p Succ basic block.
|
||||||
BinaryBranchInfo &getBranchInfo(const BinaryBasicBlock &Succ);
|
BinaryBranchInfo &getBranchInfo(const BinaryBasicBlock &Succ);
|
||||||
|
|
||||||
|
/// Return branch info corresponding to an edge going to \p Succ basic block.
|
||||||
|
const BinaryBranchInfo &getBranchInfo(const BinaryBasicBlock &Succ) const;
|
||||||
|
|
||||||
/// Return branch info corresponding to an edge going to a basic block with
|
/// Return branch info corresponding to an edge going to a basic block with
|
||||||
/// label \p Label.
|
/// label \p Label.
|
||||||
BinaryBranchInfo &getBranchInfo(const MCSymbol *Label);
|
BinaryBranchInfo &getBranchInfo(const MCSymbol *Label);
|
||||||
|
|
|
@ -1599,7 +1599,7 @@ public:
|
||||||
|
|
||||||
/// Print function information to the \p OS stream.
|
/// Print function information to the \p OS stream.
|
||||||
void print(raw_ostream &OS, std::string Annotation = "",
|
void print(raw_ostream &OS, std::string Annotation = "",
|
||||||
bool PrintInstructions = true) const;
|
bool PrintInstructions = true);
|
||||||
|
|
||||||
/// Print all relocations between \p Offset and \p Offset + \p Size in
|
/// Print all relocations between \p Offset and \p Offset + \p Size in
|
||||||
/// this function.
|
/// this function.
|
||||||
|
|
|
@ -142,11 +142,11 @@ DynoStats operator+(const DynoStats &A, const DynoStats &B);
|
||||||
/// The function relies on branch instructions being in-sync with CFG for
|
/// The function relies on branch instructions being in-sync with CFG for
|
||||||
/// branch instructions stats. Thus it is better to call it after
|
/// branch instructions stats. Thus it is better to call it after
|
||||||
/// fixBranches().
|
/// fixBranches().
|
||||||
DynoStats getDynoStats(const BinaryFunction &BF);
|
DynoStats getDynoStats(BinaryFunction &BF);
|
||||||
|
|
||||||
/// Return program-wide dynostats.
|
/// Return program-wide dynostats.
|
||||||
template <typename FuncsType>
|
template <typename FuncsType>
|
||||||
inline DynoStats getDynoStats(const FuncsType &Funcs, bool IsAArch64) {
|
inline DynoStats getDynoStats(FuncsType &Funcs, bool IsAArch64) {
|
||||||
DynoStats dynoStats(IsAArch64);
|
DynoStats dynoStats(IsAArch64);
|
||||||
for (auto &BFI : Funcs) {
|
for (auto &BFI : Funcs) {
|
||||||
auto &BF = BFI.second;
|
auto &BF = BFI.second;
|
||||||
|
@ -158,9 +158,8 @@ inline DynoStats getDynoStats(const FuncsType &Funcs, bool IsAArch64) {
|
||||||
|
|
||||||
/// Call a function with optional before and after dynostats printing.
|
/// Call a function with optional before and after dynostats printing.
|
||||||
template <typename FnType, typename FuncsType>
|
template <typename FnType, typename FuncsType>
|
||||||
inline void callWithDynoStats(FnType &&Func, const FuncsType &Funcs,
|
inline void callWithDynoStats(FnType &&Func, FuncsType &Funcs, StringRef Phase,
|
||||||
StringRef Phase, const bool Flag,
|
const bool Flag, bool IsAArch64) {
|
||||||
bool IsAArch64) {
|
|
||||||
DynoStats DynoStatsBefore(IsAArch64);
|
DynoStats DynoStatsBefore(IsAArch64);
|
||||||
if (Flag)
|
if (Flag)
|
||||||
DynoStatsBefore = getDynoStats(Funcs, IsAArch64);
|
DynoStatsBefore = getDynoStats(Funcs, IsAArch64);
|
||||||
|
|
|
@ -39,7 +39,7 @@ public:
|
||||||
/// Clusters vector. Also encode relative weights between two clusters in
|
/// Clusters vector. Also encode relative weights between two clusters in
|
||||||
/// the ClusterEdges vector if requested. This vector is indexed by
|
/// the ClusterEdges vector if requested. This vector is indexed by
|
||||||
/// the clusters indices in the Clusters vector.
|
/// the clusters indices in the Clusters vector.
|
||||||
virtual void clusterBasicBlocks(const BinaryFunction &BF,
|
virtual void clusterBasicBlocks(BinaryFunction &BF,
|
||||||
bool ComputeEdges = false) = 0;
|
bool ComputeEdges = false) = 0;
|
||||||
|
|
||||||
/// Compute for each cluster its averagae execution frequency, that is
|
/// Compute for each cluster its averagae execution frequency, that is
|
||||||
|
@ -98,7 +98,7 @@ protected:
|
||||||
BBToClusterMapTy BBToClusterMap;
|
BBToClusterMapTy BBToClusterMap;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void clusterBasicBlocks(const BinaryFunction &BF,
|
void clusterBasicBlocks(BinaryFunction &BF,
|
||||||
bool ComputeEdges = false) override;
|
bool ComputeEdges = false) override;
|
||||||
void reset() override;
|
void reset() override;
|
||||||
};
|
};
|
||||||
|
@ -167,7 +167,7 @@ public:
|
||||||
|
|
||||||
/// Reorder the basic blocks of the given function and store the new order in
|
/// Reorder the basic blocks of the given function and store the new order in
|
||||||
/// the new Clusters vector.
|
/// the new Clusters vector.
|
||||||
virtual void reorderBasicBlocks(const BinaryFunction &BF,
|
virtual void reorderBasicBlocks(BinaryFunction &BF,
|
||||||
BasicBlockOrder &Order) const = 0;
|
BasicBlockOrder &Order) const = 0;
|
||||||
|
|
||||||
void setClusterAlgorithm(ClusterAlgorithm *CAlgo) {
|
void setClusterAlgorithm(ClusterAlgorithm *CAlgo) {
|
||||||
|
@ -185,7 +185,7 @@ public:
|
||||||
/// only be used for small functions.
|
/// only be used for small functions.
|
||||||
class TSPReorderAlgorithm : public ReorderAlgorithm {
|
class TSPReorderAlgorithm : public ReorderAlgorithm {
|
||||||
public:
|
public:
|
||||||
void reorderBasicBlocks(const BinaryFunction &BF,
|
void reorderBasicBlocks(BinaryFunction &BF,
|
||||||
BasicBlockOrder &Order) const override;
|
BasicBlockOrder &Order) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -196,7 +196,7 @@ public:
|
||||||
explicit OptimizeReorderAlgorithm(std::unique_ptr<ClusterAlgorithm> CAlgo)
|
explicit OptimizeReorderAlgorithm(std::unique_ptr<ClusterAlgorithm> CAlgo)
|
||||||
: ReorderAlgorithm(std::move(CAlgo)) {}
|
: ReorderAlgorithm(std::move(CAlgo)) {}
|
||||||
|
|
||||||
void reorderBasicBlocks(const BinaryFunction &BF,
|
void reorderBasicBlocks(BinaryFunction &BF,
|
||||||
BasicBlockOrder &Order) const override;
|
BasicBlockOrder &Order) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -209,7 +209,7 @@ public:
|
||||||
std::unique_ptr<ClusterAlgorithm> CAlgo)
|
std::unique_ptr<ClusterAlgorithm> CAlgo)
|
||||||
: ReorderAlgorithm(std::move(CAlgo)) {}
|
: ReorderAlgorithm(std::move(CAlgo)) {}
|
||||||
|
|
||||||
void reorderBasicBlocks(const BinaryFunction &BF,
|
void reorderBasicBlocks(BinaryFunction &BF,
|
||||||
BasicBlockOrder &Order) const override;
|
BasicBlockOrder &Order) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -222,21 +222,21 @@ public:
|
||||||
std::unique_ptr<ClusterAlgorithm> CAlgo)
|
std::unique_ptr<ClusterAlgorithm> CAlgo)
|
||||||
: ReorderAlgorithm(std::move(CAlgo)) {}
|
: ReorderAlgorithm(std::move(CAlgo)) {}
|
||||||
|
|
||||||
void reorderBasicBlocks(const BinaryFunction &BF,
|
void reorderBasicBlocks(BinaryFunction &BF,
|
||||||
BasicBlockOrder &Order) const override;
|
BasicBlockOrder &Order) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A new reordering algorithm for basic blocks, ext-tsp
|
/// A new reordering algorithm for basic blocks, ext-tsp
|
||||||
class ExtTSPReorderAlgorithm : public ReorderAlgorithm {
|
class ExtTSPReorderAlgorithm : public ReorderAlgorithm {
|
||||||
public:
|
public:
|
||||||
void reorderBasicBlocks(const BinaryFunction &BF,
|
void reorderBasicBlocks(BinaryFunction &BF,
|
||||||
BasicBlockOrder &Order) const override;
|
BasicBlockOrder &Order) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Toy example that simply reverses the original basic block order.
|
/// Toy example that simply reverses the original basic block order.
|
||||||
class ReverseReorderAlgorithm : public ReorderAlgorithm {
|
class ReverseReorderAlgorithm : public ReorderAlgorithm {
|
||||||
public:
|
public:
|
||||||
void reorderBasicBlocks(const BinaryFunction &BF,
|
void reorderBasicBlocks(BinaryFunction &BF,
|
||||||
BasicBlockOrder &Order) const override;
|
BasicBlockOrder &Order) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -247,7 +247,7 @@ public:
|
||||||
std::unique_ptr<ClusterAlgorithm> CAlgo)
|
std::unique_ptr<ClusterAlgorithm> CAlgo)
|
||||||
: ReorderAlgorithm(std::move(CAlgo)) {}
|
: ReorderAlgorithm(std::move(CAlgo)) {}
|
||||||
|
|
||||||
void reorderBasicBlocks(const BinaryFunction &BF,
|
void reorderBasicBlocks(BinaryFunction &BF,
|
||||||
BasicBlockOrder &Order) const override;
|
BasicBlockOrder &Order) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -581,15 +581,17 @@ uint64_t BinaryBasicBlock::estimateSize(const MCCodeEmitter *Emitter) const {
|
||||||
|
|
||||||
BinaryBasicBlock::BinaryBranchInfo &
|
BinaryBasicBlock::BinaryBranchInfo &
|
||||||
BinaryBasicBlock::getBranchInfo(const BinaryBasicBlock &Succ) {
|
BinaryBasicBlock::getBranchInfo(const BinaryBasicBlock &Succ) {
|
||||||
auto BI = branch_info_begin();
|
return const_cast<BinaryBranchInfo &>(
|
||||||
for (BinaryBasicBlock *BB : successors()) {
|
static_cast<const BinaryBasicBlock &>(*this).getBranchInfo(Succ));
|
||||||
if (&Succ == BB)
|
}
|
||||||
return *BI;
|
|
||||||
++BI;
|
|
||||||
}
|
|
||||||
|
|
||||||
llvm_unreachable("Invalid successor");
|
const BinaryBasicBlock::BinaryBranchInfo &
|
||||||
return *BI;
|
BinaryBasicBlock::getBranchInfo(const BinaryBasicBlock &Succ) const {
|
||||||
|
const auto Zip = llvm::zip(successors(), branch_info());
|
||||||
|
const auto Result = llvm::find_if(
|
||||||
|
Zip, [&](const auto &Tuple) { return std::get<0>(Tuple) == &Succ; });
|
||||||
|
assert(Result != Zip.end() && "Cannot find target in successors");
|
||||||
|
return std::get<1>(*Result);
|
||||||
}
|
}
|
||||||
|
|
||||||
BinaryBasicBlock::BinaryBranchInfo &
|
BinaryBasicBlock::BinaryBranchInfo &
|
||||||
|
|
|
@ -396,11 +396,20 @@ bool BinaryFunction::isForwardCall(const MCSymbol *CalleeSymbol) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void BinaryFunction::dump(bool PrintInstructions) const {
|
void BinaryFunction::dump(bool PrintInstructions) const {
|
||||||
print(dbgs(), "", PrintInstructions);
|
// getDynoStats calls FunctionLayout::updateLayoutIndices and
|
||||||
|
// BasicBlock::analyzeBranch. The former cannot be const, but should be
|
||||||
|
// removed, the latter should be made const, but seems to require refactoring.
|
||||||
|
// Forcing all callers to have a non-const reference to BinaryFunction to call
|
||||||
|
// dump non-const however is not ideal either. Adding this const_cast is right
|
||||||
|
// now the best solution. It is safe, because BinaryFunction itself is not
|
||||||
|
// modified. Only BinaryBasicBlocks are actually modified (if it all) and we
|
||||||
|
// have mutable pointers to those regardless whether this function is
|
||||||
|
// const-qualified or not.
|
||||||
|
const_cast<BinaryFunction &>(*this).print(dbgs(), "", PrintInstructions);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BinaryFunction::print(raw_ostream &OS, std::string Annotation,
|
void BinaryFunction::print(raw_ostream &OS, std::string Annotation,
|
||||||
bool PrintInstructions) const {
|
bool PrintInstructions) {
|
||||||
if (!opts::shouldPrint(*this))
|
if (!opts::shouldPrint(*this))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -3558,9 +3567,9 @@ size_t BinaryFunction::computeHash(bool UseDFS,
|
||||||
|
|
||||||
assert(hasCFG() && "function is expected to have CFG");
|
assert(hasCFG() && "function is expected to have CFG");
|
||||||
|
|
||||||
BasicBlockListType Order;
|
SmallVector<const BinaryBasicBlock *, 0> Order;
|
||||||
if (UseDFS)
|
if (UseDFS)
|
||||||
Order = dfs();
|
llvm::copy(dfs(), std::back_inserter(Order));
|
||||||
else
|
else
|
||||||
llvm::copy(Layout.blocks(), std::back_inserter(Order));
|
llvm::copy(Layout.blocks(), std::back_inserter(Order));
|
||||||
|
|
||||||
|
|
|
@ -158,7 +158,7 @@ void DynoStats::operator+=(const DynoStats &Other) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DynoStats getDynoStats(const BinaryFunction &BF) {
|
DynoStats getDynoStats(BinaryFunction &BF) {
|
||||||
auto &BC = BF.getBinaryContext();
|
auto &BC = BF.getBinaryContext();
|
||||||
|
|
||||||
DynoStats Stats(/*PrintAArch64Stats*/ BC.isAArch64());
|
DynoStats Stats(/*PrintAArch64Stats*/ BC.isAArch64());
|
||||||
|
|
|
@ -195,7 +195,7 @@ void dumpFunction(const BinaryFunction &BF) {
|
||||||
std::unordered_set<const MCSymbol *> CallReferences;
|
std::unordered_set<const MCSymbol *> CallReferences;
|
||||||
|
|
||||||
MAP->OutStreamer->emitCFIStartProc(/*IsSimple=*/false);
|
MAP->OutStreamer->emitCFIStartProc(/*IsSimple=*/false);
|
||||||
for (BinaryBasicBlock *BB : BF.getLayout().blocks()) {
|
for (const BinaryBasicBlock *BB : BF.getLayout().blocks()) {
|
||||||
OS << BB->getName() << ": \n";
|
OS << BB->getName() << ": \n";
|
||||||
|
|
||||||
const std::string BranchLabel = Twine(BB->getName(), "_br").str();
|
const std::string BranchLabel = Twine(BB->getName(), "_br").str();
|
||||||
|
|
|
@ -1450,11 +1450,11 @@ void PrintProgramStats::runOnFunctions(BinaryContext &BC) {
|
||||||
if (!opts::PrintSortedBy.empty() &&
|
if (!opts::PrintSortedBy.empty() &&
|
||||||
!llvm::is_contained(opts::PrintSortedBy, DynoStats::FIRST_DYNO_STAT)) {
|
!llvm::is_contained(opts::PrintSortedBy, DynoStats::FIRST_DYNO_STAT)) {
|
||||||
|
|
||||||
std::vector<const BinaryFunction *> Functions;
|
std::vector<BinaryFunction *> Functions;
|
||||||
std::map<const BinaryFunction *, DynoStats> Stats;
|
std::map<const BinaryFunction *, DynoStats> Stats;
|
||||||
|
|
||||||
for (const auto &BFI : BC.getBinaryFunctions()) {
|
for (auto &BFI : BC.getBinaryFunctions()) {
|
||||||
const BinaryFunction &BF = BFI.second;
|
BinaryFunction &BF = BFI.second;
|
||||||
if (shouldOptimize(BF) && BF.hasValidProfile()) {
|
if (shouldOptimize(BF) && BF.hasValidProfile()) {
|
||||||
Functions.push_back(&BF);
|
Functions.push_back(&BF);
|
||||||
Stats.emplace(&BF, getDynoStats(BF));
|
Stats.emplace(&BF, getDynoStats(BF));
|
||||||
|
@ -1554,9 +1554,9 @@ void PrintProgramStats::runOnFunctions(BinaryContext &BC) {
|
||||||
|
|
||||||
// Collect and print information about suboptimal code layout on input.
|
// Collect and print information about suboptimal code layout on input.
|
||||||
if (opts::ReportBadLayout) {
|
if (opts::ReportBadLayout) {
|
||||||
std::vector<const BinaryFunction *> SuboptimalFuncs;
|
std::vector<BinaryFunction *> SuboptimalFuncs;
|
||||||
for (auto &BFI : BC.getBinaryFunctions()) {
|
for (auto &BFI : BC.getBinaryFunctions()) {
|
||||||
const BinaryFunction &BF = BFI.second;
|
BinaryFunction &BF = BFI.second;
|
||||||
if (!BF.hasValidProfile())
|
if (!BF.hasValidProfile())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
|
@ -117,9 +117,9 @@ extractFunctionCalls(const std::vector<BinaryFunction *> &BinaryFunctions) {
|
||||||
|
|
||||||
for (BinaryFunction *SrcFunction : BinaryFunctions) {
|
for (BinaryFunction *SrcFunction : BinaryFunctions) {
|
||||||
const BinaryContext &BC = SrcFunction->getBinaryContext();
|
const BinaryContext &BC = SrcFunction->getBinaryContext();
|
||||||
for (BinaryBasicBlock *BB : SrcFunction->getLayout().blocks()) {
|
for (const BinaryBasicBlock *BB : SrcFunction->getLayout().blocks()) {
|
||||||
// Find call instructions and extract target symbols from each one
|
// Find call instructions and extract target symbols from each one
|
||||||
for (MCInst &Inst : *BB) {
|
for (const MCInst &Inst : *BB) {
|
||||||
if (!BC.MIB->isCall(Inst))
|
if (!BC.MIB->isCall(Inst))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
|
@ -441,7 +441,7 @@ bool compareChainPairs(const Chain *A1, const Chain *B1, const Chain *A2,
|
||||||
}
|
}
|
||||||
class ExtTSP {
|
class ExtTSP {
|
||||||
public:
|
public:
|
||||||
ExtTSP(const BinaryFunction &BF) : BF(BF) { initialize(); }
|
ExtTSP(BinaryFunction &BF) : BF(BF) { initialize(); }
|
||||||
|
|
||||||
/// Run the algorithm and return an ordering of basic block
|
/// Run the algorithm and return an ordering of basic block
|
||||||
void run(BinaryFunction::BasicBlockOrderType &Order) {
|
void run(BinaryFunction::BasicBlockOrderType &Order) {
|
||||||
|
@ -849,7 +849,7 @@ private:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// The binary function
|
// The binary function
|
||||||
const BinaryFunction &BF;
|
BinaryFunction &BF;
|
||||||
|
|
||||||
// All CFG nodes (basic blocks)
|
// All CFG nodes (basic blocks)
|
||||||
std::vector<Block> AllBlocks;
|
std::vector<Block> AllBlocks;
|
||||||
|
@ -864,7 +864,7 @@ private:
|
||||||
std::vector<Edge> AllEdges;
|
std::vector<Edge> AllEdges;
|
||||||
};
|
};
|
||||||
|
|
||||||
void ExtTSPReorderAlgorithm::reorderBasicBlocks(const BinaryFunction &BF,
|
void ExtTSPReorderAlgorithm::reorderBasicBlocks(BinaryFunction &BF,
|
||||||
BasicBlockOrder &Order) const {
|
BasicBlockOrder &Order) const {
|
||||||
if (BF.getLayout().block_empty())
|
if (BF.getLayout().block_empty())
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -12,10 +12,12 @@
|
||||||
|
|
||||||
#include "bolt/Passes/IdenticalCodeFolding.h"
|
#include "bolt/Passes/IdenticalCodeFolding.h"
|
||||||
#include "bolt/Core/ParallelUtilities.h"
|
#include "bolt/Core/ParallelUtilities.h"
|
||||||
|
#include "llvm/ADT/SmallVector.h"
|
||||||
#include "llvm/Support/CommandLine.h"
|
#include "llvm/Support/CommandLine.h"
|
||||||
#include "llvm/Support/ThreadPool.h"
|
#include "llvm/Support/ThreadPool.h"
|
||||||
#include "llvm/Support/Timer.h"
|
#include "llvm/Support/Timer.h"
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
#include <iterator>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
@ -166,16 +168,15 @@ bool isIdenticalWith(const BinaryFunction &A, const BinaryFunction &B,
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Process both functions in either DFS or existing order.
|
// Process both functions in either DFS or existing order.
|
||||||
const BinaryFunction::BasicBlockOrderType OrderA =
|
SmallVector<const BinaryBasicBlock *, 0> OrderA;
|
||||||
opts::UseDFS
|
SmallVector<const BinaryBasicBlock *, 0> OrderB;
|
||||||
? A.dfs()
|
if (opts::UseDFS) {
|
||||||
: BinaryFunction::BasicBlockOrderType(A.getLayout().block_begin(),
|
copy(A.dfs(), std::back_inserter(OrderA));
|
||||||
A.getLayout().block_end());
|
copy(B.dfs(), std::back_inserter(OrderB));
|
||||||
const BinaryFunction::BasicBlockOrderType OrderB =
|
} else {
|
||||||
opts::UseDFS
|
copy(A.getLayout().blocks(), std::back_inserter(OrderA));
|
||||||
? B.dfs()
|
copy(B.getLayout().blocks(), std::back_inserter(OrderB));
|
||||||
: BinaryFunction::BasicBlockOrderType(B.getLayout().block_begin(),
|
}
|
||||||
B.getLayout().block_end());
|
|
||||||
|
|
||||||
const BinaryContext &BC = A.getBinaryContext();
|
const BinaryContext &BC = A.getBinaryContext();
|
||||||
|
|
||||||
|
|
|
@ -75,7 +75,7 @@ void ClusterAlgorithm::computeClusterAverageFrequency(const BinaryContext &BC) {
|
||||||
for (uint32_t I = 0, E = Clusters.size(); I < E; ++I) {
|
for (uint32_t I = 0, E = Clusters.size(); I < E; ++I) {
|
||||||
double Freq = 0.0;
|
double Freq = 0.0;
|
||||||
uint64_t ClusterSize = 0;
|
uint64_t ClusterSize = 0;
|
||||||
for (BinaryBasicBlock *BB : Clusters[I]) {
|
for (const BinaryBasicBlock *BB : Clusters[I]) {
|
||||||
if (BB->getNumNonPseudos() > 0) {
|
if (BB->getNumNonPseudos() > 0) {
|
||||||
Freq += BB->getExecutionCount();
|
Freq += BB->getExecutionCount();
|
||||||
// Estimate the size of a block in bytes at run time
|
// Estimate the size of a block in bytes at run time
|
||||||
|
@ -94,7 +94,7 @@ void ClusterAlgorithm::printClusters() const {
|
||||||
errs() << " (frequency: " << AvgFreq[I] << ")";
|
errs() << " (frequency: " << AvgFreq[I] << ")";
|
||||||
errs() << " : ";
|
errs() << " : ";
|
||||||
const char *Sep = "";
|
const char *Sep = "";
|
||||||
for (BinaryBasicBlock *BB : Clusters[I]) {
|
for (const BinaryBasicBlock *BB : Clusters[I]) {
|
||||||
errs() << Sep << BB->getName();
|
errs() << Sep << BB->getName();
|
||||||
Sep = ", ";
|
Sep = ", ";
|
||||||
}
|
}
|
||||||
|
@ -122,7 +122,7 @@ bool GreedyClusterAlgorithm::EdgeEqual::operator()(const EdgeTy &A,
|
||||||
return A.Src == B.Src && A.Dst == B.Dst;
|
return A.Src == B.Src && A.Dst == B.Dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GreedyClusterAlgorithm::clusterBasicBlocks(const BinaryFunction &BF,
|
void GreedyClusterAlgorithm::clusterBasicBlocks(BinaryFunction &BF,
|
||||||
bool ComputeEdges) {
|
bool ComputeEdges) {
|
||||||
reset();
|
reset();
|
||||||
|
|
||||||
|
@ -148,7 +148,7 @@ void GreedyClusterAlgorithm::clusterBasicBlocks(const BinaryFunction &BF,
|
||||||
BBToClusterMap[BB] = I;
|
BBToClusterMap[BB] = I;
|
||||||
// Populate priority queue with edges.
|
// Populate priority queue with edges.
|
||||||
auto BI = BB->branch_info_begin();
|
auto BI = BB->branch_info_begin();
|
||||||
for (BinaryBasicBlock *&I : BB->successors()) {
|
for (const BinaryBasicBlock *I : BB->successors()) {
|
||||||
assert(BI->Count != BinaryBasicBlock::COUNT_NO_PROFILE &&
|
assert(BI->Count != BinaryBasicBlock::COUNT_NO_PROFILE &&
|
||||||
"attempted reordering blocks of function with no profile data");
|
"attempted reordering blocks of function with no profile data");
|
||||||
Queue.emplace_back(EdgeTy(BB, I, BI->Count));
|
Queue.emplace_back(EdgeTy(BB, I, BI->Count));
|
||||||
|
@ -191,7 +191,7 @@ void GreedyClusterAlgorithm::clusterBasicBlocks(const BinaryFunction &BF,
|
||||||
if (areClustersCompatible(ClusterA, ClusterB, E)) {
|
if (areClustersCompatible(ClusterA, ClusterB, E)) {
|
||||||
// Case 3: SrcBB is at the end of a cluster and DstBB is at the start,
|
// Case 3: SrcBB is at the end of a cluster and DstBB is at the start,
|
||||||
// allowing us to merge two clusters.
|
// allowing us to merge two clusters.
|
||||||
for (BinaryBasicBlock *BB : ClusterB)
|
for (const BinaryBasicBlock *BB : ClusterB)
|
||||||
BBToClusterMap[BB] = I;
|
BBToClusterMap[BB] = I;
|
||||||
ClusterA.insert(ClusterA.end(), ClusterB.begin(), ClusterB.end());
|
ClusterA.insert(ClusterA.end(), ClusterB.begin(), ClusterB.end());
|
||||||
ClusterB.clear();
|
ClusterB.clear();
|
||||||
|
@ -398,7 +398,7 @@ void MinBranchGreedyClusterAlgorithm::reset() {
|
||||||
Weight.clear();
|
Weight.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TSPReorderAlgorithm::reorderBasicBlocks(const BinaryFunction &BF,
|
void TSPReorderAlgorithm::reorderBasicBlocks(BinaryFunction &BF,
|
||||||
BasicBlockOrder &Order) const {
|
BasicBlockOrder &Order) const {
|
||||||
std::vector<std::vector<uint64_t>> Weight;
|
std::vector<std::vector<uint64_t>> Weight;
|
||||||
std::vector<BinaryBasicBlock *> IndexToBB;
|
std::vector<BinaryBasicBlock *> IndexToBB;
|
||||||
|
@ -413,7 +413,7 @@ void TSPReorderAlgorithm::reorderBasicBlocks(const BinaryFunction &BF,
|
||||||
IndexToBB.push_back(BB);
|
IndexToBB.push_back(BB);
|
||||||
}
|
}
|
||||||
Weight.resize(N);
|
Weight.resize(N);
|
||||||
for (BinaryBasicBlock *BB : BF.getLayout().blocks()) {
|
for (const BinaryBasicBlock *BB : BF.getLayout().blocks()) {
|
||||||
auto BI = BB->branch_info_begin();
|
auto BI = BB->branch_info_begin();
|
||||||
Weight[BB->getLayoutIndex()].resize(N);
|
Weight[BB->getLayoutIndex()].resize(N);
|
||||||
for (BinaryBasicBlock *SuccBB : BB->successors()) {
|
for (BinaryBasicBlock *SuccBB : BB->successors()) {
|
||||||
|
@ -501,7 +501,7 @@ void TSPReorderAlgorithm::reorderBasicBlocks(const BinaryFunction &BF,
|
||||||
}
|
}
|
||||||
|
|
||||||
void OptimizeReorderAlgorithm::reorderBasicBlocks(
|
void OptimizeReorderAlgorithm::reorderBasicBlocks(
|
||||||
const BinaryFunction &BF, BasicBlockOrder &Order) const {
|
BinaryFunction &BF, BasicBlockOrder &Order) const {
|
||||||
if (BF.getLayout().block_empty())
|
if (BF.getLayout().block_empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -517,7 +517,7 @@ void OptimizeReorderAlgorithm::reorderBasicBlocks(
|
||||||
}
|
}
|
||||||
|
|
||||||
void OptimizeBranchReorderAlgorithm::reorderBasicBlocks(
|
void OptimizeBranchReorderAlgorithm::reorderBasicBlocks(
|
||||||
const BinaryFunction &BF, BasicBlockOrder &Order) const {
|
BinaryFunction &BF, BasicBlockOrder &Order) const {
|
||||||
if (BF.getLayout().block_empty())
|
if (BF.getLayout().block_empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -622,7 +622,7 @@ void OptimizeBranchReorderAlgorithm::reorderBasicBlocks(
|
||||||
}
|
}
|
||||||
|
|
||||||
void OptimizeCacheReorderAlgorithm::reorderBasicBlocks(
|
void OptimizeCacheReorderAlgorithm::reorderBasicBlocks(
|
||||||
const BinaryFunction &BF, BasicBlockOrder &Order) const {
|
BinaryFunction &BF, BasicBlockOrder &Order) const {
|
||||||
if (BF.getLayout().block_empty())
|
if (BF.getLayout().block_empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -675,7 +675,7 @@ void OptimizeCacheReorderAlgorithm::reorderBasicBlocks(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReverseReorderAlgorithm::reorderBasicBlocks(const BinaryFunction &BF,
|
void ReverseReorderAlgorithm::reorderBasicBlocks(BinaryFunction &BF,
|
||||||
BasicBlockOrder &Order) const {
|
BasicBlockOrder &Order) const {
|
||||||
if (BF.getLayout().block_empty())
|
if (BF.getLayout().block_empty())
|
||||||
return;
|
return;
|
||||||
|
@ -687,7 +687,7 @@ void ReverseReorderAlgorithm::reorderBasicBlocks(const BinaryFunction &BF,
|
||||||
}
|
}
|
||||||
|
|
||||||
void RandomClusterReorderAlgorithm::reorderBasicBlocks(
|
void RandomClusterReorderAlgorithm::reorderBasicBlocks(
|
||||||
const BinaryFunction &BF, BasicBlockOrder &Order) const {
|
BinaryFunction &BF, BasicBlockOrder &Order) const {
|
||||||
if (BF.getLayout().block_empty())
|
if (BF.getLayout().block_empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -46,11 +46,11 @@ void getRegNameFromBitVec(const BinaryContext &BC, const BitVector &RegV,
|
||||||
void StokeInfo::checkInstr(const BinaryFunction &BF, StokeFuncInfo &FuncInfo) {
|
void StokeInfo::checkInstr(const BinaryFunction &BF, StokeFuncInfo &FuncInfo) {
|
||||||
MCPlusBuilder *MIB = BF.getBinaryContext().MIB.get();
|
MCPlusBuilder *MIB = BF.getBinaryContext().MIB.get();
|
||||||
BitVector RegV(NumRegs, false);
|
BitVector RegV(NumRegs, false);
|
||||||
for (BinaryBasicBlock *BB : BF.getLayout().blocks()) {
|
for (const BinaryBasicBlock *BB : BF.getLayout().blocks()) {
|
||||||
if (BB->empty())
|
if (BB->empty())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (MCInst &It : *BB) {
|
for (const MCInst &It : *BB) {
|
||||||
if (MIB->isPseudo(It))
|
if (MIB->isPseudo(It))
|
||||||
continue;
|
continue;
|
||||||
// skip function with exception handling yet
|
// skip function with exception handling yet
|
||||||
|
|
|
@ -865,8 +865,8 @@ bool DataAggregator::recordTrace(
|
||||||
if (From > To)
|
if (From > To)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
BinaryBasicBlock *FromBB = BF.getBasicBlockContainingOffset(From);
|
const BinaryBasicBlock *FromBB = BF.getBasicBlockContainingOffset(From);
|
||||||
BinaryBasicBlock *ToBB = BF.getBasicBlockContainingOffset(To);
|
const BinaryBasicBlock *ToBB = BF.getBasicBlockContainingOffset(To);
|
||||||
|
|
||||||
if (!FromBB || !ToBB)
|
if (!FromBB || !ToBB)
|
||||||
return false;
|
return false;
|
||||||
|
@ -875,7 +875,8 @@ bool DataAggregator::recordTrace(
|
||||||
// the previous block (that instruction should be a call).
|
// the previous block (that instruction should be a call).
|
||||||
if (From == FromBB->getOffset() && !BF.containsAddress(FirstLBR.From) &&
|
if (From == FromBB->getOffset() && !BF.containsAddress(FirstLBR.From) &&
|
||||||
!FromBB->isEntryPoint() && !FromBB->isLandingPad()) {
|
!FromBB->isEntryPoint() && !FromBB->isLandingPad()) {
|
||||||
BinaryBasicBlock *PrevBB = BF.getLayout().getBlock(FromBB->getIndex() - 1);
|
const BinaryBasicBlock *PrevBB =
|
||||||
|
BF.getLayout().getBlock(FromBB->getIndex() - 1);
|
||||||
if (PrevBB->getSuccessor(FromBB->getLabel())) {
|
if (PrevBB->getSuccessor(FromBB->getLabel())) {
|
||||||
const MCInst *Instr = PrevBB->getLastNonPseudoInstr();
|
const MCInst *Instr = PrevBB->getLastNonPseudoInstr();
|
||||||
if (Instr && BC.MIB->isCall(*Instr))
|
if (Instr && BC.MIB->isCall(*Instr))
|
||||||
|
|
|
@ -674,7 +674,7 @@ bool DataReader::recordBranch(BinaryFunction &BF, uint64_t From, uint64_t To,
|
||||||
BinaryContext &BC = BF.getBinaryContext();
|
BinaryContext &BC = BF.getBinaryContext();
|
||||||
|
|
||||||
BinaryBasicBlock *FromBB = BF.getBasicBlockContainingOffset(From);
|
BinaryBasicBlock *FromBB = BF.getBasicBlockContainingOffset(From);
|
||||||
BinaryBasicBlock *ToBB = BF.getBasicBlockContainingOffset(To);
|
const BinaryBasicBlock *ToBB = BF.getBasicBlockContainingOffset(To);
|
||||||
|
|
||||||
if (!FromBB || !ToBB) {
|
if (!FromBB || !ToBB) {
|
||||||
LLVM_DEBUG(dbgs() << "failed to get block for recorded branch\n");
|
LLVM_DEBUG(dbgs() << "failed to get block for recorded branch\n");
|
||||||
|
@ -703,7 +703,7 @@ bool DataReader::recordBranch(BinaryFunction &BF, uint64_t From, uint64_t To,
|
||||||
if (!OffsetMatches) {
|
if (!OffsetMatches) {
|
||||||
// Skip the nops to support old .fdata
|
// Skip the nops to support old .fdata
|
||||||
uint64_t Offset = ToBB->getOffset();
|
uint64_t Offset = ToBB->getOffset();
|
||||||
for (MCInst &Instr : *ToBB) {
|
for (const MCInst &Instr : *ToBB) {
|
||||||
if (!BC.MIB->isNoop(Instr))
|
if (!BC.MIB->isNoop(Instr))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -739,7 +739,8 @@ bool DataReader::recordBranch(BinaryFunction &BF, uint64_t From, uint64_t To,
|
||||||
// The real destination is the layout successor of the detected ToBB.
|
// The real destination is the layout successor of the detected ToBB.
|
||||||
if (ToBB == BF.getLayout().block_back())
|
if (ToBB == BF.getLayout().block_back())
|
||||||
return false;
|
return false;
|
||||||
BinaryBasicBlock *NextBB = BF.getLayout().getBlock(ToBB->getIndex() + 1);
|
const BinaryBasicBlock *NextBB =
|
||||||
|
BF.getLayout().getBlock(ToBB->getIndex() + 1);
|
||||||
assert((NextBB && NextBB->getOffset() > ToBB->getOffset()) && "bad layout");
|
assert((NextBB && NextBB->getOffset() > ToBB->getOffset()) && "bad layout");
|
||||||
ToBB = NextBB;
|
ToBB = NextBB;
|
||||||
}
|
}
|
||||||
|
|
|
@ -183,7 +183,7 @@ class RewriteInstanceDiff {
|
||||||
RI1.getTotalScore();
|
RI1.getTotalScore();
|
||||||
}
|
}
|
||||||
|
|
||||||
double getNormalizedScore(BinaryBasicBlock::branch_info_iterator BIIter,
|
double getNormalizedScore(BinaryBasicBlock::const_branch_info_iterator BIIter,
|
||||||
const RewriteInstance &Ctx) {
|
const RewriteInstance &Ctx) {
|
||||||
double Score =
|
double Score =
|
||||||
BIIter->Count == BinaryBasicBlock::COUNT_NO_PROFILE ? 0 : BIIter->Count;
|
BIIter->Count == BinaryBasicBlock::COUNT_NO_PROFILE ? 0 : BIIter->Count;
|
||||||
|
|
Loading…
Reference in New Issue