#ifndef LLVM_ANALYSIS_BRANCHPROBABILITYINFO_H
#define LLVM_ANALYSIS_BRANCHPROBABILITYINFO_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/CFG.h"
#include "llvm/IR/PassManager.h"
#include "llvm/IR/ValueHandle.h"
#include "llvm/Pass.h"
#include "llvm/Support/BranchProbability.h"
#include "llvm/Support/Casting.h"
#include <algorithm>
#include <cassert>
#include <cstdint>
#include <utility>
namespace llvm {
class Function;
class LoopInfo;
class raw_ostream;
class TargetLibraryInfo;
class Value;
class BranchProbabilityInfo {
public:
BranchProbabilityInfo() = default;
BranchProbabilityInfo(const Function &F, const LoopInfo &LI,
const TargetLibraryInfo *TLI = nullptr) {
calculate(F, LI, TLI);
}
BranchProbabilityInfo(BranchProbabilityInfo &&Arg)
: Probs(std::move(Arg.Probs)), LastF(Arg.LastF),
PostDominatedByUnreachable(std::move(Arg.PostDominatedByUnreachable)),
PostDominatedByColdCall(std::move(Arg.PostDominatedByColdCall)) {}
BranchProbabilityInfo(const BranchProbabilityInfo &) = delete;
BranchProbabilityInfo &operator=(const BranchProbabilityInfo &) = delete;
BranchProbabilityInfo &operator=(BranchProbabilityInfo &&RHS) {
releaseMemory();
Probs = std::move(RHS.Probs);
PostDominatedByColdCall = std::move(RHS.PostDominatedByColdCall);
PostDominatedByUnreachable = std::move(RHS.PostDominatedByUnreachable);
return *this;
}
void releaseMemory();
void print(raw_ostream &OS) const;
BranchProbability getEdgeProbability(const BasicBlock *Src,
unsigned IndexInSuccessors) const;
BranchProbability getEdgeProbability(const BasicBlock *Src,
const BasicBlock *Dst) const;
BranchProbability getEdgeProbability(const BasicBlock *Src,
succ_const_iterator Dst) const;
bool isEdgeHot(const BasicBlock *Src, const BasicBlock *Dst) const;
const BasicBlock *getHotSucc(const BasicBlock *BB) const;
raw_ostream &printEdgeProbability(raw_ostream &OS, const BasicBlock *Src,
const BasicBlock *Dst) const;
void setEdgeProbability(const BasicBlock *Src, unsigned IndexInSuccessors,
BranchProbability Prob);
static BranchProbability getBranchProbStackProtector(bool IsLikely) {
static const BranchProbability LikelyProb((1u << 20) - 1, 1u << 20);
return IsLikely ? LikelyProb : LikelyProb.getCompl();
}
void calculate(const Function &F, const LoopInfo &LI,
const TargetLibraryInfo *TLI = nullptr);
void eraseBlock(const BasicBlock *BB);
using SccMap = DenseMap<const BasicBlock *, int>;
using SccHeaderMap = DenseMap<const BasicBlock *, bool>;
using SccHeaderMaps = std::vector<SccHeaderMap>;
struct SccInfo {
SccMap SccNums;
SccHeaderMaps SccHeaders;
};
private:
class BasicBlockCallbackVH final : public CallbackVH {
BranchProbabilityInfo *BPI;
void deleted() override {
assert(BPI != nullptr);
BPI->eraseBlock(cast<BasicBlock>(getValPtr()));
BPI->Handles.erase(*this);
}
public:
BasicBlockCallbackVH(const Value *V, BranchProbabilityInfo *BPI = nullptr)
: CallbackVH(const_cast<Value *>(V)), BPI(BPI) {}
};
DenseSet<BasicBlockCallbackVH, DenseMapInfo<Value*>> Handles;
using Edge = std::pair<const BasicBlock *, unsigned>;
static const uint32_t DEFAULT_WEIGHT = 16;
DenseMap<Edge, BranchProbability> Probs;
const Function *LastF;
SmallPtrSet<const BasicBlock *, 16> PostDominatedByUnreachable;
SmallPtrSet<const BasicBlock *, 16> PostDominatedByColdCall;
void updatePostDominatedByUnreachable(const BasicBlock *BB);
void updatePostDominatedByColdCall(const BasicBlock *BB);
bool calcUnreachableHeuristics(const BasicBlock *BB);
bool calcMetadataWeights(const BasicBlock *BB);
bool calcColdCallHeuristics(const BasicBlock *BB);
bool calcPointerHeuristics(const BasicBlock *BB);
bool calcLoopBranchHeuristics(const BasicBlock *BB, const LoopInfo &LI,
SccInfo &SccI);
bool calcZeroHeuristics(const BasicBlock *BB, const TargetLibraryInfo *TLI);
bool calcFloatingPointHeuristics(const BasicBlock *BB);
bool calcInvokeHeuristics(const BasicBlock *BB);
};
class BranchProbabilityAnalysis
: public AnalysisInfoMixin<BranchProbabilityAnalysis> {
friend AnalysisInfoMixin<BranchProbabilityAnalysis>;
static AnalysisKey Key;
public:
using Result = BranchProbabilityInfo;
BranchProbabilityInfo run(Function &F, FunctionAnalysisManager &AM);
};
class BranchProbabilityPrinterPass
: public PassInfoMixin<BranchProbabilityPrinterPass> {
raw_ostream &OS;
public:
explicit BranchProbabilityPrinterPass(raw_ostream &OS) : OS(OS) {}
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
};
class BranchProbabilityInfoWrapperPass : public FunctionPass {
BranchProbabilityInfo BPI;
public:
static char ID;
BranchProbabilityInfoWrapperPass() : FunctionPass(ID) {
initializeBranchProbabilityInfoWrapperPassPass(
*PassRegistry::getPassRegistry());
}
BranchProbabilityInfo &getBPI() { return BPI; }
const BranchProbabilityInfo &getBPI() const { return BPI; }
void getAnalysisUsage(AnalysisUsage &AU) const override;
bool runOnFunction(Function &F) override;
void releaseMemory() override;
void print(raw_ostream &OS, const Module *M = nullptr) const override;
};
}
#endif