47#define DEBUG_TYPE "select-optimize"
50 "Number of select groups considered for conversion to branch");
52 "Number of select groups converted due to expensive cold operand");
54 "Number of select groups converted due to high-predictability");
56 "Number of select groups not converted due to unpredictability");
58 "Number of select groups not converted due to cold basic block");
60 "Number of select groups converted due to loop-level analysis");
61STATISTIC(NumSelectsConverted,
"Number of selects converted");
68 "cold-operand-threshold",
69 cl::desc(
"Maximum frequency of path for an operand to be considered cold."),
73 "cold-operand-max-cost-multiplier",
74 cl::desc(
"Maximum cost multiplier of TCC_expensive for the dependence "
75 "slice of a cold operand to be considered inexpensive."),
80 cl::desc(
"Gradient gain threshold (%)."),
85 cl::desc(
"Minimum gain per loop (in cycles) threshold."),
89 "select-opti-loop-relative-gain-threshold",
91 "Minimum relative gain per loop threshold (1/X). Defaults to 12.5%"),
96 cl::desc(
"Default mispredict rate (initialized to 25%)."));
101 cl::desc(
"Disable loop-level heuristics."));
105class SelectOptimizeImpl {
117 SelectOptimizeImpl() =
default;
122 using Scaled64 = ScaledNumber<uint64_t>;
128 Scaled64 NonPredCost;
139 bool Inverted =
false;
146 SelectLike(Instruction *I,
bool Inverted =
false,
unsigned CondIdx = 0)
147 : I(I), Inverted(Inverted), CondIdx(CondIdx) {}
154 unsigned getConditionOpIndex() {
return CondIdx; };
160 Value *getTrueValue(
bool HonorInverts =
true)
const {
161 if (Inverted && HonorInverts)
162 return getFalseValue(
false);
164 return Sel->getTrueValue();
176 Value *getFalseValue(
bool HonorInverts =
true)
const {
177 if (Inverted && HonorInverts)
178 return getTrueValue(
false);
180 return Sel->getFalseValue();
185 return BO->getOperand(1 - CondIdx);
193 Scaled64 getOpCostOnBranch(
194 bool IsTrue,
const DenseMap<const Instruction *, CostInfo> &InstCostMap,
195 const TargetTransformInfo *
TTI) {
196 auto *
V = IsTrue ? getTrueValue() : getFalseValue();
199 auto It = InstCostMap.
find(
IV);
200 return It != InstCostMap.
end() ? It->second.NonPredCost
211 {TargetTransformInfo::OK_AnyValue, TargetTransformInfo::OP_None},
212 {TTI::OK_UniformConstantValue, TTI::OP_PowerOf2});
215 auto It = InstCostMap.find(OpI);
216 if (It != InstCostMap.end())
217 TotalCost += It->second.NonPredCost;
231 using SelectGroups = SmallVector<SelectGroup, 2>;
241 void optimizeSelectsBase(
Function &
F, SelectGroups &ProfSIGroups);
242 void optimizeSelectsInnerLoops(
Function &
F, SelectGroups &ProfSIGroups);
246 void convertProfitableSIGroups(SelectGroups &ProfSIGroups);
249 void collectSelectGroups(BasicBlock &BB, SelectGroups &SIGroups);
253 void findProfitableSIGroupsBase(SelectGroups &SIGroups,
254 SelectGroups &ProfSIGroups);
255 void findProfitableSIGroupsInnerLoops(
const Loop *L, SelectGroups &SIGroups,
256 SelectGroups &ProfSIGroups);
260 bool isConvertToBranchProfitableBase(
const SelectGroup &ASI);
265 bool hasExpensiveColdOperand(
const SelectGroup &ASI);
271 void getExclBackwardsSlice(Instruction *
I, std::stack<Instruction *> &Slice,
272 Instruction *SI,
bool ForSinking =
false,
273 const SelectGroup *Group =
nullptr);
276 bool isSelectHighlyPredictable(
const SelectLike SI);
280 bool checkLoopHeuristics(
const Loop *L,
const CostInfo LoopDepth[2]);
284 bool computeLoopCosts(
const Loop *L,
const SelectGroups &SIGroups,
285 DenseMap<const Instruction *, CostInfo> &InstCostMap,
289 SmallDenseMap<const Instruction *, SelectLike, 2>
290 getSImap(
const SelectGroups &SIGroups);
294 SmallDenseMap<const Instruction *, const SelectGroup *, 2>
295 getSGmap(
const SelectGroups &SIGroups);
298 std::optional<uint64_t> computeInstCost(
const Instruction *
I);
301 Scaled64 getMispredictionCost(
const SelectLike SI,
const Scaled64 CondCost);
304 Scaled64 getPredictedPathCost(Scaled64 TrueCost, Scaled64 FalseCost,
305 const SelectLike SI);
308 bool isSelectKindSupported(
const SelectLike SI);
312 SelectOptimizeImpl Impl;
317 SelectOptimize() : FunctionPass(ID) {}
323 return Impl.runOnFunction(
F, *
this);
326 void getAnalysisUsage(AnalysisUsage &AU)
const override {
332 AU.
addRequired<OptimizationRemarkEmitterWrapperPass>();
340 SelectOptimizeImpl Impl(TM);
341 return Impl.run(
F,
FAM);
344char SelectOptimize::ID = 0;
373 if (!
TTI->enableSelectOptimize())
377 .getCachedResult<ProfileSummaryAnalysis>(*
F.getParent());
380 "analysis to be available");
389 TSchedModel.
init(TSI);
410 if (!
TTI->enableSelectOptimize())
417 TSchedModel.
init(TSI);
423 return optimizeSelects(
F);
426bool SelectOptimizeImpl::optimizeSelects(
Function &
F) {
428 SelectGroups ProfSIGroups;
430 optimizeSelectsBase(
F, ProfSIGroups);
432 optimizeSelectsInnerLoops(
F, ProfSIGroups);
436 convertProfitableSIGroups(ProfSIGroups);
439 return !ProfSIGroups.empty();
442void SelectOptimizeImpl::optimizeSelectsBase(
Function &
F,
443 SelectGroups &ProfSIGroups) {
445 SelectGroups SIGroups;
449 if (L &&
L->isInnermost())
451 collectSelectGroups(BB, SIGroups);
455 findProfitableSIGroupsBase(SIGroups, ProfSIGroups);
458void SelectOptimizeImpl::optimizeSelectsInnerLoops(
Function &
F,
459 SelectGroups &ProfSIGroups) {
462 for (
unsigned long i = 0; i <
Loops.size(); ++i)
466 if (!
L->isInnermost())
469 SelectGroups SIGroups;
471 collectSelectGroups(*BB, SIGroups);
473 findProfitableSIGroupsInnerLoops(L, SIGroups, ProfSIGroups);
489 SelectOptimizeImpl::SelectLike &
SI,
bool isTrue,
492 Value *V = isTrue ?
SI.getTrueValue() :
SI.getFalseValue();
495 if (
auto It = OptSelects.find(
IV); It != OptSelects.end())
496 return isTrue ? It->second.first : It->second.second;
501 assert((BO->getOpcode() == Instruction::Add ||
502 BO->getOpcode() == Instruction::Or ||
503 BO->getOpcode() == Instruction::Sub) &&
504 "Only currently handling Add, Or and Sub binary operators.");
506 auto *CBO = BO->clone();
507 auto CondIdx =
SI.getConditionOpIndex();
510 CBO->setOperand(CondIdx, ConstantInt::get(CBO->getType(), 1));
513 "Unexpected opcode");
517 unsigned OtherIdx = 1 - CondIdx;
519 if (
auto It = OptSelects.find(
IV); It != OptSelects.end())
520 CBO->setOperand(OtherIdx, isTrue ? It->second.first : It->second.second);
522 CBO->insertBefore(
B->getTerminator()->getIterator());
526void SelectOptimizeImpl::convertProfitableSIGroups(SelectGroups &ProfSIGroups) {
527 for (SelectGroup &ASI : ProfSIGroups) {
567 typedef std::stack<Instruction *>::size_type StackSizeType;
568 StackSizeType maxTrueSliceLen = 0, maxFalseSliceLen = 0;
570 bool SelectWithProfileIsInverted =
false;
571 for (SelectLike &
SI : ASI.Selects) {
577 std::stack<Instruction *> TrueSlice;
578 getExclBackwardsSlice(TI, TrueSlice,
SI.getI(),
true, &ASI);
579 maxTrueSliceLen = std::max(maxTrueSliceLen, TrueSlice.size());
584 std::stack<Instruction *> FalseSlice;
585 getExclBackwardsSlice(FI, FalseSlice,
SI.getI(),
true, &ASI);
586 maxFalseSliceLen = std::max(maxFalseSliceLen, FalseSlice.size());
593 if (
hasProfMD(*
SI.getI()) && ASI.Condition == SelectCondition) {
594 SelectWithProfile =
SI.getI();
597 SelectWithProfile =
SI.getI();
598 SelectWithProfileIsInverted =
true;
612 for (StackSizeType IS = 0;
IS < maxTrueSliceLen; ++
IS) {
613 for (
auto &S : TrueSlices) {
615 TrueSlicesInterleaved.
push_back(S.top());
620 for (StackSizeType IS = 0;
IS < maxFalseSliceLen; ++
IS) {
621 for (
auto &S : FalseSlices) {
623 FalseSlicesInterleaved.
push_back(S.top());
630 SelectLike &
SI = ASI.Selects.front();
631 SelectLike &LastSI = ASI.Selects.back();
639 SplitPt.setHeadBit(
true);
648 auto DIt =
SI.getI()->getIterator();
649 auto NIt = ASI.Selects.begin();
650 while (&*DIt != LastSI.getI()) {
651 if (NIt != ASI.Selects.end() && &*DIt == NIt->getI())
657 for (
auto *HI : HoistInstrs)
658 HI->moveBefore(
SI.getI()->getIterator());
675 std::next(LastSI.getI()->getIterator()));
680 BasicBlock *TrueBlock =
nullptr, *FalseBlock =
nullptr;
681 UncondBrInst *TrueBranch =
nullptr, *FalseBranch =
nullptr;
683 auto HasSelectLike = [](SelectGroup &SG,
bool IsTrue) {
684 for (
auto &SL : SG.Selects) {
685 if ((IsTrue ? SL.getTrueValue() : SL.getFalseValue()) ==
nullptr)
690 if (!TrueSlicesInterleaved.
empty() || HasSelectLike(ASI,
true)) {
694 TrueBranch->
setDebugLoc(LastSI.getI()->getDebugLoc());
695 for (
Instruction *TrueInst : TrueSlicesInterleaved)
698 if (!FalseSlicesInterleaved.
empty() || HasSelectLike(ASI,
false)) {
703 FalseBranch->setDebugLoc(LastSI.getI()->getDebugLoc());
704 for (
Instruction *FalseInst : FalseSlicesInterleaved)
705 FalseInst->moveBefore(FalseBranch->getIterator());
709 if (TrueBlock == FalseBlock) {
710 assert(TrueBlock ==
nullptr &&
711 "Unexpected basic block transform while optimizing select");
716 FalseBranch->setDebugLoc(
SI.getI()->getDebugLoc());
725 if (TrueBlock ==
nullptr) {
728 TrueBlock = StartBlock;
729 }
else if (FalseBlock ==
nullptr) {
732 FalseBlock = StartBlock;
739 IB.CreateFreeze(ASI.Condition, ASI.Condition->getName() +
".frozen");
746 auto InsertionPoint = EndBlock->
begin();
747 for (SelectLike &
SI : ASI.Selects) {
755 for (
auto &SG : ProfSIGroups) {
756 if (SG.Condition ==
SI.getI())
760 SI.getI()->replaceAllUsesWith(PN);
767 ++NumSelectsConverted;
771 CondBr->
copyMetadata(*SelectWithProfile, {llvm::LLVMContext::MD_prof});
772 if (SelectWithProfileIsInverted)
779 for (SelectLike &
SI : ASI.Selects)
780 SI.getI()->eraseFromParent();
784void SelectOptimizeImpl::collectSelectGroups(
BasicBlock &BB,
785 SelectGroups &SIGroups) {
795 struct SelectLikeInfo {
799 unsigned ConditionIdx;
810 auto ProcessSelectInfo = [&SelectInfo, &SeenCmp](
Instruction *
I) {
813 return SelectInfo.
end();
818 Cond->getType()->isIntegerTy(1)) {
820 return SelectInfo.
insert({
I, {
Cond,
true, Inverted, 0}}).first;
824 return SelectInfo.
insert({
I, {
Cond,
true,
true, 0}}).first;
830 return SelectInfo.
insert({
I, {
Cond,
false, Inverted, 0}}).first;
835 I->getType()->getIntegerBitWidth() == Shift->
getZExtValue() + 1) {
836 for (
auto *CmpI : SeenCmp) {
837 auto Pred = CmpI->getPredicate();
838 if (Val != CmpI->getOperand(0))
850 return SelectInfo.
insert({
I, {CmpI,
true, Inverted, 0}}).first;
853 return SelectInfo.
end();
861 auto MatchZExtOrSExtPattern =
863 auto MatchShiftPattern =
868 if ((
match(
I, MatchZExtOrSExtPattern) &&
X->getType()->isIntegerTy(1)) ||
869 (
match(
I, MatchShiftPattern) &&
870 X->getType()->getIntegerBitWidth() == Shift->
getZExtValue() + 1)) {
871 if (
I->getOpcode() != Instruction::Add &&
872 I->getOpcode() != Instruction::Sub &&
873 I->getOpcode() != Instruction::Or)
874 return SelectInfo.
end();
876 if (
I->getOpcode() == Instruction::Or &&
I->getType()->isIntegerTy(1))
877 return SelectInfo.
end();
883 unsigned Idx =
I->getOpcode() == Instruction::Sub ? 1 : 0;
885 auto *
Op =
I->getOperand(Idx);
886 auto It = SelectInfo.
find(
Op);
887 if (It != SelectInfo.
end() && It->second.IsAuxiliary) {
888 Cond = It->second.Cond;
889 bool Inverted = It->second.IsInverted;
890 return SelectInfo.
insert({
I, {
Cond,
false, Inverted,
Idx}}).first;
894 return SelectInfo.
end();
897 bool AlreadyProcessed =
false;
900 while (BBIt != BB.
end()) {
905 if (!AlreadyProcessed)
906 It = ProcessSelectInfo(
I);
908 AlreadyProcessed =
false;
910 if (It == SelectInfo.
end() || It->second.IsAuxiliary)
913 if (!
TTI->shouldTreatInstructionLikeSelect(
I))
918 if (!
Cond->getType()->isIntegerTy(1))
921 SelectGroup SIGroup = {
Cond, {}};
922 SIGroup.Selects.emplace_back(
I, It->second.IsInverted,
923 It->second.ConditionIdx);
927 if (!isSelectKindSupported(SIGroup.Selects.front()))
930 while (BBIt != BB.
end()) {
939 It = ProcessSelectInfo(NI);
940 if (It == SelectInfo.
end()) {
941 AlreadyProcessed =
true;
946 auto [CurrCond, IsAux, IsRev, CondIdx] = It->second;
947 if (
Cond != CurrCond) {
948 AlreadyProcessed =
true;
953 SIGroup.Selects.emplace_back(NI, IsRev, CondIdx);
957 dbgs() <<
"New Select group (" << SIGroup.Selects.size() <<
") with\n";
958 for (
auto &
SI : SIGroup.Selects)
959 dbgs() <<
" " << *
SI.getI() <<
"\n";
962 SIGroups.push_back(SIGroup);
966void SelectOptimizeImpl::findProfitableSIGroupsBase(
967 SelectGroups &SIGroups, SelectGroups &ProfSIGroups) {
968 for (SelectGroup &ASI : SIGroups) {
969 ++NumSelectOptAnalyzed;
970 if (isConvertToBranchProfitableBase(ASI))
971 ProfSIGroups.push_back(ASI);
981void SelectOptimizeImpl::findProfitableSIGroupsInnerLoops(
982 const Loop *L, SelectGroups &SIGroups, SelectGroups &ProfSIGroups) {
983 NumSelectOptAnalyzed += SIGroups.size();
995 CostInfo LoopCost[2] = {{Scaled64::getZero(), Scaled64::getZero()},
996 {Scaled64::getZero(), Scaled64::getZero()}};
997 if (!computeLoopCosts(L, SIGroups, InstCostMap, LoopCost) ||
998 !checkLoopHeuristics(L, LoopCost)) {
1002 for (SelectGroup &ASI : SIGroups) {
1005 Scaled64 SelectCost = Scaled64::getZero(), BranchCost = Scaled64::getZero();
1006 for (SelectLike &
SI : ASI.Selects) {
1007 const auto &ICM = InstCostMap[
SI.getI()];
1008 SelectCost = std::max(SelectCost, ICM.PredCost);
1009 BranchCost = std::max(BranchCost, ICM.NonPredCost);
1011 if (BranchCost < SelectCost) {
1013 ASI.Selects.front().getI());
1014 OR <<
"Profitable to convert to branch (loop analysis). BranchCost="
1015 << BranchCost.toString() <<
", SelectCost=" << SelectCost.toString()
1018 ++NumSelectConvertedLoop;
1019 ProfSIGroups.push_back(ASI);
1022 ASI.Selects.front().getI());
1023 ORmiss <<
"Select is more profitable (loop analysis). BranchCost="
1024 << BranchCost.toString()
1025 <<
", SelectCost=" << SelectCost.toString() <<
". ";
1031bool SelectOptimizeImpl::isConvertToBranchProfitableBase(
1032 const SelectGroup &ASI) {
1033 const SelectLike &
SI = ASI.Selects.front();
1042 ORmiss <<
"Not converted to branch because of cold basic block. ";
1048 if (
SI.getI()->getMetadata(LLVMContext::MD_unpredictable)) {
1050 ORmiss <<
"Not converted to branch because of unpredictable branch. ";
1058 ++NumSelectConvertedHighPred;
1059 OR <<
"Converted to branch because of highly predictable branch. ";
1066 if (hasExpensiveColdOperand(ASI)) {
1067 ++NumSelectConvertedExpColdOperand;
1068 OR <<
"Converted to branch because of expensive cold operand.";
1076 auto *BB =
SI.getI()->getParent();
1078 if (L && !
L->isInnermost() &&
L->getLoopLatch() == BB &&
1079 ASI.Selects.size() >= 3) {
1080 OR <<
"Converted to branch because select group in the latch block is big.";
1085 ORmiss <<
"Not profitable to convert to branch (base heuristic).";
1092 return (Numerator + (Denominator / 2)) / Denominator;
1102bool SelectOptimizeImpl::hasExpensiveColdOperand(
const SelectGroup &ASI) {
1103 bool ColdOperand =
false;
1104 uint64_t TrueWeight, FalseWeight, TotalWeight;
1106 uint64_t MinWeight = std::min(TrueWeight, FalseWeight);
1107 TotalWeight = TrueWeight + FalseWeight;
1112 ASI.Selects.front().getI());
1113 ORmiss <<
"Profile data available but missing branch-weights metadata for "
1114 "select instruction. ";
1121 for (SelectLike
SI : ASI.Selects) {
1124 if (TrueWeight < FalseWeight) {
1126 HotWeight = FalseWeight;
1129 HotWeight = TrueWeight;
1132 std::stack<Instruction *> ColdSlice;
1133 getExclBackwardsSlice(ColdI, ColdSlice,
SI.getI());
1135 while (!ColdSlice.empty()) {
1136 SliceCost +=
TTI->getInstructionCost(ColdSlice.top(),
1162 while (&*It !=
SI) {
1163 if (It->mayWriteToMemory())
1176void SelectOptimizeImpl::getExclBackwardsSlice(
Instruction *
I,
1177 std::stack<Instruction *> &Slice,
1179 const SelectGroup *Group) {
1181 std::queue<Instruction *> Worklist;
1183 while (!Worklist.empty()) {
1191 if (!
II->hasOneUse())
1197 if (ForSinking && (
II->isTerminator() ||
II->mayHaveSideEffects() ||
1203 if (ForSinking && Group &&
1204 llvm::any_of(Group->Selects, [&](
auto &S) { return S.getI() == II; }))
1229bool SelectOptimizeImpl::isSelectHighlyPredictable(
const SelectLike
SI) {
1233 uint64_t Sum = TrueWeight + FalseWeight;
1236 if (Probability >
TTI->getPredictableBranchThreshold())
1243bool SelectOptimizeImpl::checkLoopHeuristics(
const Loop *L,
1244 const CostInfo LoopCost[2]) {
1252 &*
L->getHeader()->getFirstNonPHIIt());
1254 if (LoopCost[0].NonPredCost > LoopCost[0].PredCost ||
1255 LoopCost[1].NonPredCost >= LoopCost[1].PredCost) {
1256 ORmissL <<
"No select conversion in the loop due to no reduction of loop's "
1262 Scaled64 Gain[2] = {LoopCost[0].PredCost - LoopCost[0].NonPredCost,
1263 LoopCost[1].PredCost - LoopCost[1].NonPredCost};
1270 Scaled64 RelativeGain = Scaled64::get(100) * Gain[1] / LoopCost[1].PredCost;
1271 ORmissL <<
"No select conversion in the loop due to small reduction of "
1272 "loop's critical path. Gain="
1273 << Gain[1].toString()
1274 <<
", RelativeGain=" << RelativeGain.toString() <<
"%. ";
1284 if (Gain[1] > Gain[0]) {
1285 Scaled64 GradientGain = Scaled64::get(100) * (Gain[1] - Gain[0]) /
1286 (LoopCost[1].PredCost - LoopCost[0].PredCost);
1288 ORmissL <<
"No select conversion in the loop due to small gradient gain. "
1290 << GradientGain.toString() <<
"%. ";
1296 else if (Gain[1] < Gain[0]) {
1298 <<
"No select conversion in the loop due to negative gradient gain. ";
1312bool SelectOptimizeImpl::computeLoopCosts(
1313 const Loop *L,
const SelectGroups &SIGroups,
1315 LLVM_DEBUG(
dbgs() <<
"Calculating Latency / IPredCost / INonPredCost of loop "
1316 <<
L->getHeader()->getName() <<
"\n");
1317 const auto SImap = getSImap(SIGroups);
1318 const auto SGmap = getSGmap(SIGroups);
1321 const unsigned Iterations = 2;
1322 for (
unsigned Iter = 0; Iter < Iterations; ++Iter) {
1324 CostInfo &MaxCost = LoopCost[Iter];
1330 Scaled64 IPredCost = Scaled64::getZero(),
1331 INonPredCost = Scaled64::getZero();
1336 for (
const Use &U :
I.operands()) {
1340 if (
auto It = InstCostMap.
find(UI); It != InstCostMap.
end()) {
1341 IPredCost = std::max(IPredCost, It->second.PredCost);
1342 INonPredCost = std::max(INonPredCost, It->second.NonPredCost);
1345 auto ILatency = computeInstCost(&
I);
1348 ORmissL <<
"Invalid instruction cost preventing analysis and "
1349 "optimization of the inner-most loop containing this "
1354 IPredCost += Scaled64::get(*ILatency);
1355 INonPredCost += Scaled64::get(*ILatency);
1363 if (
auto It = SImap.find(&
I); It != SImap.end()) {
1364 auto SI = It->second;
1365 const auto *SG = SGmap.at(&
I);
1366 Scaled64 TrueOpCost =
SI.getOpCostOnBranch(
true, InstCostMap,
TTI);
1367 Scaled64 FalseOpCost =
SI.getOpCostOnBranch(
false, InstCostMap,
TTI);
1368 Scaled64 PredictedPathCost =
1369 getPredictedPathCost(TrueOpCost, FalseOpCost,
SI);
1371 Scaled64 CondCost = Scaled64::getZero();
1373 if (
auto It = InstCostMap.
find(CI); It != InstCostMap.
end())
1374 CondCost = It->second.NonPredCost;
1375 Scaled64 MispredictCost = getMispredictionCost(
SI, CondCost);
1377 INonPredCost = PredictedPathCost + MispredictCost;
1380 << INonPredCost <<
" for " <<
I <<
"\n");
1382 InstCostMap[&
I] = {IPredCost, INonPredCost};
1383 MaxCost.PredCost = std::max(MaxCost.PredCost, IPredCost);
1384 MaxCost.NonPredCost = std::max(MaxCost.NonPredCost, INonPredCost);
1388 <<
" MaxCost = " << MaxCost.PredCost <<
" "
1389 << MaxCost.NonPredCost <<
"\n");
1395SelectOptimizeImpl::getSImap(
const SelectGroups &SIGroups) {
1397 for (
const SelectGroup &ASI : SIGroups)
1398 for (
const SelectLike &
SI : ASI.Selects)
1404SelectOptimizeImpl::getSGmap(
const SelectGroups &SIGroups) {
1406 for (
const SelectGroup &ASI : SIGroups)
1407 for (
const SelectLike &
SI : ASI.Selects)
1412std::optional<uint64_t>
1413SelectOptimizeImpl::computeInstCost(
const Instruction *
I) {
1417 return std::optional<uint64_t>(ICost.
getValue());
1418 return std::nullopt;
1422SelectOptimizeImpl::getMispredictionCost(
const SelectLike
SI,
1423 const Scaled64 CondCost) {
1431 if (isSelectHighlyPredictable(
SI))
1437 Scaled64 MispredictCost =
1438 std::max(Scaled64::get(MispredictPenalty), CondCost) *
1439 Scaled64::get(MispredictRate);
1440 MispredictCost /= Scaled64::get(100);
1442 return MispredictCost;
1448SelectOptimizeImpl::getPredictedPathCost(Scaled64 TrueCost, Scaled64 FalseCost,
1449 const SelectLike
SI) {
1450 Scaled64 PredPathCost;
1453 uint64_t SumWeight = TrueWeight + FalseWeight;
1454 if (SumWeight != 0) {
1455 PredPathCost = TrueCost * Scaled64::get(TrueWeight) +
1456 FalseCost * Scaled64::get(FalseWeight);
1457 PredPathCost /= Scaled64::get(SumWeight);
1458 return PredPathCost;
1463 PredPathCost = std::max(TrueCost * Scaled64::get(3) + FalseCost,
1464 FalseCost * Scaled64::get(3) + TrueCost);
1465 PredPathCost /= Scaled64::get(4);
1466 return PredPathCost;
1469bool SelectOptimizeImpl::isSelectKindSupported(
const SelectLike
SI) {
1471 if (
SI.getType()->isVectorTy())
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static Value * getTrueOrFalseValue(SelectInst *SI, bool isTrue, const SmallPtrSet< const Instruction *, 2 > &Selects)
If isTrue is true, return the true value of SI, otherwise return false value of SI.
static bool runOnFunction(Function &F, bool PostInlining)
print mir2vec MIR2Vec Vocabulary Printer Pass
uint64_t IntrinsicInst * II
FunctionAnalysisManager FAM
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
This file contains the declarations for profiling metadata utility functions.
SmallVector< MachineOperand, 4 > Cond
const GCNTargetMachine & getTM(const GCNSubtarget *STI)
static bool isSafeToSinkLoad(Instruction *LoadI, Instruction *SI)
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 > 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< bool > DisableLoopLevelHeuristics("disable-loop-level-heuristics", cl::Hidden, cl::init(false), cl::desc("Disable loop-level heuristics."))
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 > MispredictDefaultRate("mispredict-default-rate", cl::Hidden, cl::init(25), cl::desc("Default mispredict rate (initialized to 25%)."))
static void EmitAndPrintRemark(OptimizationRemarkEmitter *ORE, DiagnosticInfoOptimizationBase &Rem)
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 > 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)
This file contains the declaration of the SelectOptimizePass class, its corresponding pass name is se...
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static SymbolRef::Type getType(const Symbol *Sym)
This file describes how to lower LLVM code to machine code.
Target-Independent Code Generator Pass Configuration Options pass.
static const uint32_t IV[8]
AnalysisUsage & addRequired()
LLVM Basic Block Representation.
iterator begin()
Instruction iterator methods.
LLVM_ABI const_iterator getFirstInsertionPt() const
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
LLVM_ABI BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="")
Split the basic block into two basic blocks at the specified instruction.
const Function * getParent() const
Return the enclosing method, or null if none.
LLVM_ABI void insertDbgRecordBefore(DbgRecord *DR, InstListType::iterator Here)
Insert a DbgRecord into a block at the position given by Here.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
InstListType::iterator iterator
Instruction iterators...
LLVM_ABI LLVMContext & getContext() const
Get the context in which this basic block lives.
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
Analysis pass which computes BlockFrequencyInfo.
Legacy analysis pass which computes BlockFrequencyInfo.
BlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to estimate IR basic block frequen...
LLVM_ABI void setBlockFreq(const BasicBlock *BB, BlockFrequency Freq)
LLVM_ABI BlockFrequency getBlockFreq(const BasicBlock *BB) const
getblockFreq - Return block frequency.
static LLVM_ABI BranchProbability getBranchProbability(uint64_t Numerator, uint64_t Denominator)
@ ICMP_SLT
signed less than
@ ICMP_SLE
signed less or equal
@ ICMP_SGT
signed greater than
@ ICMP_SGE
signed greater or equal
This is the shared class of boolean and integer constants.
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
static LLVM_ABI Constant * getAllOnesValue(Type *Ty)
Base class for non-instruction debug metadata records that have positions within IR.
LLVM_ABI void removeFromParent()
iterator find(const_arg_type_t< KeyT > Val)
DenseMapIterator< KeyT, ValueT, KeyInfoT, BucketT > iterator
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Common features for diagnostics dealing with optimization remarks that are used by both IR and MIR pa...
std::string getMsg() const
FunctionPass class - This class is used to implement most global optimizations.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
CostType getValue() const
This function is intended to be used as sparingly as possible, since the class provides the full rang...
LLVM_ABI void insertBefore(InstListType::iterator InsertPos)
Insert an unlinked instruction into a basic block immediately before the specified position.
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
LLVM_ABI void swapProfMetadata()
If the instruction has "branch_weights" MD_prof metadata and the MDNode has three operands (including...
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
LLVM_ABI void copyMetadata(const Instruction &SrcInst, ArrayRef< unsigned > WL=ArrayRef< unsigned >())
Copy metadata from SrcInst to this instruction.
Analysis pass that exposes the LoopInfo for a function.
LoopT * getLoopFor(const BlockT *BB) const
Return the inner most loop that BB lives in.
The legacy pass manager's analysis pass to compute loop information.
Represents a single loop in the control flow graph.
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
static PHINode * Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
Constructors - NumReservedValues is a hint for the number of incoming edges that this phi node will h...
Pass interface - Implemented by all 'passes'.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
An analysis pass based on legacy pass manager to deliver ProfileSummaryInfo.
Analysis providing profile information.
bool hasProfileSummary() const
Returns true if profile summary is available.
bool isColdBlock(const BBType *BB, BFIT *BFI) const
Returns true if BasicBlock BB is considered cold.
Simple representation of a scaled number.
static ScaledNumber get(uint64_t N)
static ScaledNumber getZero()
LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM)
bool insert(const value_type &X)
Insert a new element into the SetVector.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
A SetVector that performs no allocations if smaller than a certain size.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Analysis pass providing the TargetTransformInfo.
virtual bool isSelectSupported(SelectSupportKind) const
SelectSupportKind
Enum that describes what type of support for selects the target has.
bool isPredictableSelectExpensive() const
Return true if selects are only cheaper than branches if the branch is unlikely to be predicted right...
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
Primary interface to the complete machine description for the target machine.
virtual const TargetSubtargetInfo * getSubtargetImpl(const Function &) const
Virtual method implemented by subclasses that returns a reference to that target's TargetSubtargetInf...
Target-Independent Code Generator Pass Configuration Options.
Provide an instruction scheduling machine model to CodeGen passes.
LLVM_ABI void init(const TargetSubtargetInfo *TSInfo, bool EnableSModel=true, bool EnableSItins=true)
Initialize the machine model for instruction scheduling.
TargetSubtargetInfo - Generic base class for all target subtargets.
virtual unsigned getMispredictionPenalty() const
Return the number of extra cycles the processor takes to recover from a branch misprediction.
virtual const TargetLowering * getTargetLowering() const
bool isIntegerTy() const
True if this is an instance of IntegerType.
Unconditional Branch instruction.
static UncondBrInst * Create(BasicBlock *Target, InsertPosition InsertBefore=nullptr)
A Use represents the edge between a Value definition and its users.
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI void takeName(Value *V)
Transfer the name from V to this value.
const ParentTy * getParent() const
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
BinaryOp_match< SrcTy, SpecificConstantMatch, TargetOpcode::G_XOR, true > m_Not(const SrcTy &&Src)
Matches a register not-ed by a G_XOR.
OneUse_match< SubPat > m_OneUse(const SubPat &SP)
bool match(Val *V, const Pattern &P)
BinOpPred_match< LHS, RHS, is_right_shift_op > m_Shr(const LHS &L, const RHS &R)
Matches logical shift operations.
ThreeOps_match< Cond, LHS, RHS, Instruction::Select > m_Select(const Cond &C, const LHS &L, const RHS &R)
Matches SelectInst.
auto m_Value()
Match an arbitrary value and ignore it.
is_zero< true > m_Zero()
Match any null constant or a vector with all elements equal to 0.
AnyBinaryOp_match< LHS, RHS, true > m_c_BinOp(const LHS &L, const RHS &R)
Matches a BinaryOperator with LHS and RHS in either order.
match_combine_or< CastInst_match< OpTy, ZExtInst >, CastInst_match< OpTy, SExtInst > > m_ZExtOrSExt(const OpTy &Op)
auto m_ConstantInt()
Match an arbitrary ConstantInt and ignore it.
initializer< Ty > init(const Ty &Val)
PointerTypeMap run(const Module &M)
Compute the PointerTypeMap for the module M.
friend class Instruction
Iterator for Instructions in a `BasicBlock.
unsigned getOpcode(const VPValue *V)
Return the instruction opcode for the recipe defining V or 0 for unsupported recipes and VPValues not...
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI cl::opt< bool > ProfcheckDisableMetadataFixes
UnaryFunction for_each(R &&Range, UnaryFunction F)
Provide wrappers to std::for_each which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI void setExplicitlyUnknownBranchWeightsIfProfiled(Instruction &I, StringRef PassName, const Function *F=nullptr)
Like setExplicitlyUnknownBranchWeights(...), but only sets unknown branch weights in the new instruct...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
OuterAnalysisManagerProxy< ModuleAnalysisManager, Function > ModuleAnalysisManagerFunctionProxy
Provide the ModuleAnalysisManager to Function proxy.
LLVM_ABI FunctionPass * createSelectOptimizePass()
This pass converts conditional moves to conditional jumps when profitable.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
LLVM_ABI bool shouldOptimizeForSize(const MachineFunction *MF, ProfileSummaryInfo *PSI, const MachineBlockFrequencyInfo *BFI, PGSOQueryType QueryType=PGSOQueryType::Other)
Returns true if machine function MF is suggested to be size-optimized based on the profile.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
constexpr T divideNearest(U Numerator, V Denominator)
Returns (Numerator / Denominator) rounded by round-half-up.
auto dyn_cast_or_null(const Y &Val)
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ABI bool hasProfMD(const Instruction &I)
Checks if an Instruction has MD_prof Metadata.
DWARFExpression::Operation Op
LLVM_ABI bool extractBranchWeights(const MDNode *ProfileData, SmallVectorImpl< uint32_t > &Weights)
Extract branch weights from MD_prof metadata.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.