#include "llvm/CodeGen/SelectOptimize.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/BlockFrequencyInfo.h"
#include "llvm/Analysis/BranchProbabilityInfo.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/OptimizationRemarkEmitter.h"
#include "llvm/Analysis/ProfileSummaryInfo.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/TargetLowering.h"
#include "llvm/CodeGen/TargetPassConfig.h"
#include "llvm/CodeGen/TargetSchedule.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/PatternMatch.h"
#include "llvm/IR/ProfDataUtils.h"
#include "llvm/InitializePasses.h"
#include "llvm/Pass.h"
#include "llvm/Support/ScaledNumber.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Transforms/Utils/SizeOpts.h"
#include <algorithm>
#include <memory>
#include <queue>
#include <stack>
usingnamespacellvm;
usingnamespacellvm::PatternMatch;
#define DEBUG_TYPE …
STATISTIC(NumSelectOptAnalyzed,
"Number of select groups considered for conversion to branch");
STATISTIC(NumSelectConvertedExpColdOperand,
"Number of select groups converted due to expensive cold operand");
STATISTIC(NumSelectConvertedHighPred,
"Number of select groups converted due to high-predictability");
STATISTIC(NumSelectUnPred,
"Number of select groups not converted due to unpredictability");
STATISTIC(NumSelectColdBB,
"Number of select groups not converted due to cold basic block");
STATISTIC(NumSelectConvertedLoop,
"Number of select groups converted due to loop-level analysis");
STATISTIC(NumSelectsConverted, "Number of selects converted");
static cl::opt<unsigned> ColdOperandThreshold(
"cold-operand-threshold",
cl::desc("Maximum frequency of path for an operand to be considered cold."),
cl::init(20), cl::Hidden);
static cl::opt<unsigned> ColdOperandMaxCostMultiplier(
"cold-operand-max-cost-multiplier",
cl::desc("Maximum cost multiplier of TCC_expensive for the dependence "
"slice of a cold operand to be considered inexpensive."),
cl::init(1), cl::Hidden);
static cl::opt<unsigned>
GainGradientThreshold("select-opti-loop-gradient-gain-threshold",
cl::desc("Gradient gain threshold (%)."),
cl::init(25), cl::Hidden);
static cl::opt<unsigned>
GainCycleThreshold("select-opti-loop-cycle-gain-threshold",
cl::desc("Minimum gain per loop (in cycles) threshold."),
cl::init(4), cl::Hidden);
static cl::opt<unsigned> GainRelativeThreshold(
"select-opti-loop-relative-gain-threshold",
cl::desc(
"Minimum relative gain per loop threshold (1/X). Defaults to 12.5%"),
cl::init(8), cl::Hidden);
static cl::opt<unsigned> MispredictDefaultRate(
"mispredict-default-rate", cl::Hidden, cl::init(25),
cl::desc("Default mispredict rate (initialized to 25%)."));
static cl::opt<bool>
DisableLoopLevelHeuristics("disable-loop-level-heuristics", cl::Hidden,
cl::init(false),
cl::desc("Disable loop-level heuristics."));
namespace {
class SelectOptimizeImpl { … };
class SelectOptimize : public FunctionPass { … };
}
PreservedAnalyses SelectOptimizePass::run(Function &F,
FunctionAnalysisManager &FAM) { … }
char SelectOptimize::ID = …;
INITIALIZE_PASS_BEGIN(SelectOptimize, DEBUG_TYPE, "Optimize selects", false,
false)
INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
INITIALIZE_PASS_DEPENDENCY(ProfileSummaryInfoWrapperPass)
INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass)
INITIALIZE_PASS_DEPENDENCY(BlockFrequencyInfoWrapperPass)
INITIALIZE_PASS_DEPENDENCY(OptimizationRemarkEmitterWrapperPass)
INITIALIZE_PASS_END(SelectOptimize, DEBUG_TYPE, "Optimize selects", false,
false)
FunctionPass *llvm::createSelectOptimizePass() { … }
PreservedAnalyses SelectOptimizeImpl::run(Function &F,
FunctionAnalysisManager &FAM) { … }
bool SelectOptimizeImpl::runOnFunction(Function &F, Pass &P) { … }
bool SelectOptimizeImpl::optimizeSelects(Function &F) { … }
void SelectOptimizeImpl::optimizeSelectsBase(Function &F,
SelectGroups &ProfSIGroups) { … }
void SelectOptimizeImpl::optimizeSelectsInnerLoops(Function &F,
SelectGroups &ProfSIGroups) { … }
static Value *
getTrueOrFalseValue(SelectOptimizeImpl::SelectLike SI, bool isTrue,
const SmallPtrSet<const Instruction *, 2> &Selects,
IRBuilder<> &IB) { … }
void SelectOptimizeImpl::convertProfitableSIGroups(SelectGroups &ProfSIGroups) { … }
void SelectOptimizeImpl::collectSelectGroups(BasicBlock &BB,
SelectGroups &SIGroups) { … }
void SelectOptimizeImpl::findProfitableSIGroupsBase(
SelectGroups &SIGroups, SelectGroups &ProfSIGroups) { … }
static void EmitAndPrintRemark(OptimizationRemarkEmitter *ORE,
DiagnosticInfoOptimizationBase &Rem) { … }
void SelectOptimizeImpl::findProfitableSIGroupsInnerLoops(
const Loop *L, SelectGroups &SIGroups, SelectGroups &ProfSIGroups) { … }
bool SelectOptimizeImpl::isConvertToBranchProfitableBase(
const SelectGroup &ASI) { … }
static InstructionCost divideNearest(InstructionCost Numerator,
uint64_t Denominator) { … }
static bool extractBranchWeights(const SelectOptimizeImpl::SelectLike SI,
uint64_t &TrueVal, uint64_t &FalseVal) { … }
bool SelectOptimizeImpl::hasExpensiveColdOperand(const SelectGroup &ASI) { … }
static bool isSafeToSinkLoad(Instruction *LoadI, Instruction *SI) { … }
void SelectOptimizeImpl::getExclBackwardsSlice(Instruction *I,
std::stack<Instruction *> &Slice,
Instruction *SI,
bool ForSinking) { … }
bool SelectOptimizeImpl::isSelectHighlyPredictable(const SelectLike SI) { … }
bool SelectOptimizeImpl::checkLoopHeuristics(const Loop *L,
const CostInfo LoopCost[2]) { … }
bool SelectOptimizeImpl::computeLoopCosts(
const Loop *L, const SelectGroups &SIGroups,
DenseMap<const Instruction *, CostInfo> &InstCostMap, CostInfo *LoopCost) { … }
SmallDenseMap<const Instruction *, SelectOptimizeImpl::SelectLike, 2>
SelectOptimizeImpl::getSImap(const SelectGroups &SIGroups) { … }
std::optional<uint64_t>
SelectOptimizeImpl::computeInstCost(const Instruction *I) { … }
ScaledNumber<uint64_t>
SelectOptimizeImpl::getMispredictionCost(const SelectLike SI,
const Scaled64 CondCost) { … }
ScaledNumber<uint64_t>
SelectOptimizeImpl::getPredictedPathCost(Scaled64 TrueCost, Scaled64 FalseCost,
const SelectLike SI) { … }
bool SelectOptimizeImpl::isSelectKindSupported(const SelectLike SI) { … }