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");
64 "cold-operand-threshold",
65 cl::desc(
"Maximum frequency of path for an operand to be considered cold."),
69 "cold-operand-max-cost-multiplier",
70 cl::desc(
"Maximum cost multiplier of TCC_expensive for the dependence "
71 "slice of a cold operand to be considered inexpensive."),
76 cl::desc(
"Gradient gain threshold (%)."),
81 cl::desc(
"Minimum gain per loop (in cycles) threshold."),
85 "select-opti-loop-relative-gain-threshold",
87 "Minimum relative gain per loop threshold (1/X). Defaults to 12.5%"),
92 cl::desc(
"Default mispredict rate (initialized to 25%)."));
97 cl::desc(
"Disable loop-level heuristics."));
101class SelectOptimizeImpl {
113 SelectOptimizeImpl() =
default;
118 using Scaled64 = ScaledNumber<uint64_t>;
124 Scaled64 NonPredCost;
135 bool Inverted =
false;
142 SelectLike(Instruction *I,
bool Inverted =
false,
unsigned CondIdx = 0)
143 : I(I), Inverted(Inverted), CondIdx(CondIdx) {}
150 unsigned getConditionOpIndex() {
return CondIdx; };
156 Value *getTrueValue(
bool HonorInverts =
true)
const {
157 if (Inverted && HonorInverts)
158 return getFalseValue(
false);
160 return Sel->getTrueValue();
172 Value *getFalseValue(
bool HonorInverts =
true)
const {
173 if (Inverted && HonorInverts)
174 return getTrueValue(
false);
176 return Sel->getFalseValue();
181 return BO->getOperand(1 - CondIdx);
189 Scaled64 getOpCostOnBranch(
190 bool IsTrue,
const DenseMap<const Instruction *, CostInfo> &InstCostMap,
191 const TargetTransformInfo *
TTI) {
192 auto *
V = IsTrue ? getTrueValue() : getFalseValue();
195 auto It = InstCostMap.
find(
IV);
196 return It != InstCostMap.
end() ? It->second.NonPredCost
207 {TargetTransformInfo::OK_AnyValue, TargetTransformInfo::OP_None},
208 {TTI::OK_UniformConstantValue, TTI::OP_PowerOf2});
211 auto It = InstCostMap.find(OpI);
212 if (It != InstCostMap.end())
213 TotalCost += It->second.NonPredCost;
227 using SelectGroups = SmallVector<SelectGroup, 2>;
231 bool optimizeSelects(Function &
F);
237 void optimizeSelectsBase(Function &
F, SelectGroups &ProfSIGroups);
238 void optimizeSelectsInnerLoops(Function &
F, SelectGroups &ProfSIGroups);
242 void convertProfitableSIGroups(SelectGroups &ProfSIGroups);
245 void collectSelectGroups(BasicBlock &BB, SelectGroups &SIGroups);
249 void findProfitableSIGroupsBase(SelectGroups &SIGroups,
250 SelectGroups &ProfSIGroups);
251 void findProfitableSIGroupsInnerLoops(
const Loop *L, SelectGroups &SIGroups,
252 SelectGroups &ProfSIGroups);
256 bool isConvertToBranchProfitableBase(
const SelectGroup &ASI);
261 bool hasExpensiveColdOperand(
const SelectGroup &ASI);
266 void getExclBackwardsSlice(Instruction *
I, std::stack<Instruction *> &Slice,
267 Instruction *SI,
bool ForSinking =
false);
270 bool isSelectHighlyPredictable(
const SelectLike SI);
274 bool checkLoopHeuristics(
const Loop *L,
const CostInfo LoopDepth[2]);
278 bool computeLoopCosts(
const Loop *L,
const SelectGroups &SIGroups,
279 DenseMap<const Instruction *, CostInfo> &InstCostMap,
283 SmallDenseMap<const Instruction *, SelectLike, 2>
284 getSImap(
const SelectGroups &SIGroups);
288 SmallDenseMap<const Instruction *, const SelectGroup *, 2>
289 getSGmap(
const SelectGroups &SIGroups);
292 std::optional<uint64_t> computeInstCost(
const Instruction *
I);
295 Scaled64 getMispredictionCost(
const SelectLike SI,
const Scaled64 CondCost);
298 Scaled64 getPredictedPathCost(Scaled64 TrueCost, Scaled64 FalseCost,
299 const SelectLike SI);
302 bool isSelectKindSupported(
const SelectLike SI);
306 SelectOptimizeImpl Impl;
311 SelectOptimize() : FunctionPass(ID) {}
317 return Impl.runOnFunction(
F, *
this);
320 void getAnalysisUsage(AnalysisUsage &AU)
const override {
326 AU.
addRequired<OptimizationRemarkEmitterWrapperPass>();
334 SelectOptimizeImpl Impl(TM);
335 return Impl.run(
F,
FAM);
338char SelectOptimize::ID = 0;
367 if (!
TTI->enableSelectOptimize())
371 .getCachedResult<ProfileSummaryAnalysis>(*
F.getParent());
372 assert(PSI &&
"This pass requires module analysis pass `profile-summary`!");
381 TSchedModel.
init(TSI);
402 if (!
TTI->enableSelectOptimize())
409 TSchedModel.
init(TSI);
415 return optimizeSelects(
F);
418bool SelectOptimizeImpl::optimizeSelects(
Function &
F) {
420 SelectGroups ProfSIGroups;
422 optimizeSelectsBase(
F, ProfSIGroups);
424 optimizeSelectsInnerLoops(
F, ProfSIGroups);
428 convertProfitableSIGroups(ProfSIGroups);
431 return !ProfSIGroups.empty();
434void SelectOptimizeImpl::optimizeSelectsBase(
Function &
F,
435 SelectGroups &ProfSIGroups) {
437 SelectGroups SIGroups;
441 if (L &&
L->isInnermost())
443 collectSelectGroups(BB, SIGroups);
447 findProfitableSIGroupsBase(SIGroups, ProfSIGroups);
450void SelectOptimizeImpl::optimizeSelectsInnerLoops(
Function &
F,
451 SelectGroups &ProfSIGroups) {
454 for (
unsigned long i = 0; i <
Loops.size(); ++i)
458 if (!
L->isInnermost())
461 SelectGroups SIGroups;
463 collectSelectGroups(*BB, SIGroups);
465 findProfitableSIGroupsInnerLoops(L, SIGroups, ProfSIGroups);
481 SelectOptimizeImpl::SelectLike &
SI,
bool isTrue,
484 Value *V = isTrue ?
SI.getTrueValue() :
SI.getFalseValue();
487 if (
auto It = OptSelects.find(
IV); It != OptSelects.end())
488 return isTrue ? It->second.first : It->second.second;
493 assert((BO->getOpcode() == Instruction::Add ||
494 BO->getOpcode() == Instruction::Or ||
495 BO->getOpcode() == Instruction::Sub) &&
496 "Only currently handling Add, Or and Sub binary operators.");
498 auto *CBO = BO->clone();
499 auto CondIdx =
SI.getConditionOpIndex();
502 CBO->setOperand(CondIdx, ConstantInt::get(CBO->getType(), 1));
505 "Unexpected opcode");
509 unsigned OtherIdx = 1 - CondIdx;
511 if (
auto It = OptSelects.find(
IV); It != OptSelects.end())
512 CBO->setOperand(OtherIdx, isTrue ? It->second.first : It->second.second);
514 CBO->insertBefore(
B->getTerminator()->getIterator());
518void SelectOptimizeImpl::convertProfitableSIGroups(SelectGroups &ProfSIGroups) {
519 for (SelectGroup &ASI : ProfSIGroups) {
559 typedef std::stack<Instruction *>::size_type StackSizeType;
560 StackSizeType maxTrueSliceLen = 0, maxFalseSliceLen = 0;
561 for (SelectLike &
SI : ASI.Selects) {
567 std::stack<Instruction *> TrueSlice;
568 getExclBackwardsSlice(TI, TrueSlice,
SI.getI(),
true);
569 maxTrueSliceLen = std::max(maxTrueSliceLen, TrueSlice.size());
574 std::stack<Instruction *> FalseSlice;
575 getExclBackwardsSlice(FI, FalseSlice,
SI.getI(),
true);
576 maxFalseSliceLen = std::max(maxFalseSliceLen, FalseSlice.size());
592 for (StackSizeType IS = 0; IS < maxTrueSliceLen; ++IS) {
593 for (
auto &S : TrueSlices) {
595 TrueSlicesInterleaved.
push_back(S.top());
600 for (StackSizeType IS = 0; IS < maxFalseSliceLen; ++IS) {
601 for (
auto &S : FalseSlices) {
603 FalseSlicesInterleaved.
push_back(S.top());
610 SelectLike &
SI = ASI.Selects.front();
611 SelectLike &LastSI = ASI.Selects.back();
619 SplitPt.setHeadBit(
true);
628 auto DIt =
SI.getI()->getIterator();
629 auto NIt = ASI.Selects.begin();
630 while (&*DIt != LastSI.getI()) {
631 if (NIt != ASI.Selects.end() && &*DIt == NIt->getI())
638 for (
auto *DI : SinkInstrs)
639 DI->moveBeforePreserving(InsertionPoint);
656 std::next(LastSI.getI()->getIterator()));
661 BasicBlock *TrueBlock =
nullptr, *FalseBlock =
nullptr;
662 BranchInst *TrueBranch =
nullptr, *FalseBranch =
nullptr;
664 auto HasSelectLike = [](SelectGroup &SG,
bool IsTrue) {
665 for (
auto &SL : SG.Selects) {
666 if ((IsTrue ? SL.getTrueValue() : SL.getFalseValue()) ==
nullptr)
671 if (!TrueSlicesInterleaved.
empty() || HasSelectLike(ASI,
true)) {
675 TrueBranch->
setDebugLoc(LastSI.getI()->getDebugLoc());
676 for (
Instruction *TrueInst : TrueSlicesInterleaved)
679 if (!FalseSlicesInterleaved.
empty() || HasSelectLike(ASI,
false)) {
684 FalseBranch->setDebugLoc(LastSI.getI()->getDebugLoc());
685 for (
Instruction *FalseInst : FalseSlicesInterleaved)
686 FalseInst->moveBefore(FalseBranch->getIterator());
690 if (TrueBlock == FalseBlock) {
691 assert(TrueBlock ==
nullptr &&
692 "Unexpected basic block transform while optimizing select");
697 FalseBranch->setDebugLoc(
SI.getI()->getDebugLoc());
706 if (TrueBlock ==
nullptr) {
709 TrueBlock = StartBlock;
710 }
else if (FalseBlock ==
nullptr) {
713 FalseBlock = StartBlock;
720 IB.CreateFreeze(ASI.Condition, ASI.Condition->getName() +
".frozen");
727 InsertionPoint = EndBlock->
begin();
728 for (SelectLike &
SI : ASI.Selects) {
736 for (
auto &SG : ProfSIGroups) {
737 if (SG.Condition ==
SI.getI())
741 SI.getI()->replaceAllUsesWith(PN);
748 ++NumSelectsConverted;
750 IB.CreateCondBr(CondFr, TT, FT,
SI.getI());
753 for (SelectLike &
SI : ASI.Selects)
754 SI.getI()->eraseFromParent();
758void SelectOptimizeImpl::collectSelectGroups(
BasicBlock &BB,
759 SelectGroups &SIGroups) {
769 struct SelectLikeInfo {
773 unsigned ConditionIdx;
784 auto ProcessSelectInfo = [&SelectInfo, &SeenCmp](
Instruction *
I) {
787 return SelectInfo.
end();
792 Cond->getType()->isIntegerTy(1)) {
794 return SelectInfo.
insert({
I, {
Cond,
true, Inverted, 0}}).first;
798 return SelectInfo.
insert({
I, {
Cond,
true,
true, 0}}).first;
804 return SelectInfo.
insert({
I, {
Cond,
false, Inverted, 0}}).first;
809 I->getType()->getIntegerBitWidth() == Shift->
getZExtValue() + 1) {
810 for (
auto *CmpI : SeenCmp) {
811 auto Pred = CmpI->getPredicate();
812 if (Val != CmpI->getOperand(0))
824 return SelectInfo.
insert({
I, {CmpI,
true, Inverted, 0}}).first;
827 return SelectInfo.
end();
835 auto MatchZExtOrSExtPattern =
837 auto MatchShiftPattern =
842 if ((
match(
I, MatchZExtOrSExtPattern) &&
X->getType()->isIntegerTy(1)) ||
843 (
match(
I, MatchShiftPattern) &&
844 X->getType()->getIntegerBitWidth() == Shift->
getZExtValue() + 1)) {
845 if (
I->getOpcode() != Instruction::Add &&
846 I->getOpcode() != Instruction::Sub &&
847 I->getOpcode() != Instruction::Or)
848 return SelectInfo.
end();
850 if (
I->getOpcode() == Instruction::Or &&
I->getType()->isIntegerTy(1))
851 return SelectInfo.
end();
857 unsigned Idx =
I->getOpcode() == Instruction::Sub ? 1 : 0;
858 for (; Idx < 2; Idx++) {
859 auto *
Op =
I->getOperand(Idx);
860 auto It = SelectInfo.
find(
Op);
861 if (It != SelectInfo.
end() && It->second.IsAuxiliary) {
862 Cond = It->second.Cond;
863 bool Inverted = It->second.IsInverted;
864 return SelectInfo.
insert({
I, {
Cond,
false, Inverted, Idx}}).first;
868 return SelectInfo.
end();
871 bool AlreadyProcessed =
false;
874 while (BBIt != BB.
end()) {
876 if (
I->isDebugOrPseudoInst())
879 if (!AlreadyProcessed)
880 It = ProcessSelectInfo(
I);
882 AlreadyProcessed =
false;
884 if (It == SelectInfo.
end() || It->second.IsAuxiliary)
887 if (!
TTI->shouldTreatInstructionLikeSelect(
I))
892 if (!
Cond->getType()->isIntegerTy(1))
895 SelectGroup SIGroup = {
Cond, {}};
896 SIGroup.Selects.emplace_back(
I, It->second.IsInverted,
897 It->second.ConditionIdx);
901 if (!isSelectKindSupported(SIGroup.Selects.front()))
904 while (BBIt != BB.
end()) {
913 It = ProcessSelectInfo(NI);
914 if (It == SelectInfo.
end()) {
915 AlreadyProcessed =
true;
920 auto [CurrCond, IsAux, IsRev, CondIdx] = It->second;
921 if (
Cond != CurrCond) {
922 AlreadyProcessed =
true;
927 SIGroup.Selects.emplace_back(NI, IsRev, CondIdx);
931 dbgs() <<
"New Select group (" << SIGroup.Selects.size() <<
") with\n";
932 for (
auto &
SI : SIGroup.Selects)
933 dbgs() <<
" " << *
SI.getI() <<
"\n";
936 SIGroups.push_back(SIGroup);
940void SelectOptimizeImpl::findProfitableSIGroupsBase(
941 SelectGroups &SIGroups, SelectGroups &ProfSIGroups) {
942 for (SelectGroup &ASI : SIGroups) {
943 ++NumSelectOptAnalyzed;
944 if (isConvertToBranchProfitableBase(ASI))
945 ProfSIGroups.push_back(ASI);
955void SelectOptimizeImpl::findProfitableSIGroupsInnerLoops(
956 const Loop *L, SelectGroups &SIGroups, SelectGroups &ProfSIGroups) {
957 NumSelectOptAnalyzed += SIGroups.size();
969 CostInfo LoopCost[2] = {{Scaled64::getZero(), Scaled64::getZero()},
970 {Scaled64::getZero(), Scaled64::getZero()}};
971 if (!computeLoopCosts(L, SIGroups, InstCostMap, LoopCost) ||
972 !checkLoopHeuristics(L, LoopCost)) {
976 for (SelectGroup &ASI : SIGroups) {
979 Scaled64 SelectCost = Scaled64::getZero(), BranchCost = Scaled64::getZero();
980 for (SelectLike &
SI : ASI.Selects) {
981 const auto &ICM = InstCostMap[
SI.getI()];
982 SelectCost = std::max(SelectCost, ICM.PredCost);
983 BranchCost = std::max(BranchCost, ICM.NonPredCost);
985 if (BranchCost < SelectCost) {
987 ASI.Selects.front().getI());
988 OR <<
"Profitable to convert to branch (loop analysis). BranchCost="
989 << BranchCost.toString() <<
", SelectCost=" << SelectCost.toString()
992 ++NumSelectConvertedLoop;
993 ProfSIGroups.push_back(ASI);
996 ASI.Selects.front().getI());
997 ORmiss <<
"Select is more profitable (loop analysis). BranchCost="
998 << BranchCost.toString()
999 <<
", SelectCost=" << SelectCost.toString() <<
". ";
1005bool SelectOptimizeImpl::isConvertToBranchProfitableBase(
1006 const SelectGroup &ASI) {
1007 const SelectLike &
SI = ASI.Selects.front();
1016 ORmiss <<
"Not converted to branch because of cold basic block. ";
1022 if (
SI.getI()->getMetadata(LLVMContext::MD_unpredictable)) {
1024 ORmiss <<
"Not converted to branch because of unpredictable branch. ";
1032 ++NumSelectConvertedHighPred;
1033 OR <<
"Converted to branch because of highly predictable branch. ";
1040 if (hasExpensiveColdOperand(ASI)) {
1041 ++NumSelectConvertedExpColdOperand;
1042 OR <<
"Converted to branch because of expensive cold operand.";
1050 auto *BB =
SI.getI()->getParent();
1052 if (L && !
L->isInnermost() &&
L->getLoopLatch() == BB &&
1053 ASI.Selects.size() >= 3) {
1054 OR <<
"Converted to branch because select group in the latch block is big.";
1059 ORmiss <<
"Not profitable to convert to branch (base heuristic).";
1066 return (Numerator + (Denominator / 2)) / Denominator;
1076bool SelectOptimizeImpl::hasExpensiveColdOperand(
const SelectGroup &ASI) {
1077 bool ColdOperand =
false;
1078 uint64_t TrueWeight, FalseWeight, TotalWeight;
1080 uint64_t MinWeight = std::min(TrueWeight, FalseWeight);
1081 TotalWeight = TrueWeight + FalseWeight;
1086 ASI.Selects.front().getI());
1087 ORmiss <<
"Profile data available but missing branch-weights metadata for "
1088 "select instruction. ";
1095 for (SelectLike
SI : ASI.Selects) {
1098 if (TrueWeight < FalseWeight) {
1100 HotWeight = FalseWeight;
1103 HotWeight = TrueWeight;
1106 std::stack<Instruction *> ColdSlice;
1107 getExclBackwardsSlice(ColdI, ColdSlice,
SI.getI());
1109 while (!ColdSlice.empty()) {
1110 SliceCost +=
TTI->getInstructionCost(ColdSlice.top(),
1136 while (&*It !=
SI) {
1137 if (It->mayWriteToMemory())
1150void SelectOptimizeImpl::getExclBackwardsSlice(
Instruction *
I,
1151 std::stack<Instruction *> &Slice,
1155 std::queue<Instruction *> Worklist;
1157 while (!Worklist.empty()) {
1165 if (!
II->hasOneUse())
1171 if (ForSinking && (
II->isTerminator() ||
II->mayHaveSideEffects() ||
1197bool SelectOptimizeImpl::isSelectHighlyPredictable(
const SelectLike
SI) {
1198 uint64_t TrueWeight, FalseWeight;
1200 uint64_t
Max = std::max(TrueWeight, FalseWeight);
1201 uint64_t Sum = TrueWeight + FalseWeight;
1204 if (Probability >
TTI->getPredictableBranchThreshold())
1211bool SelectOptimizeImpl::checkLoopHeuristics(
const Loop *L,
1212 const CostInfo LoopCost[2]) {
1220 &*
L->getHeader()->getFirstNonPHIIt());
1222 if (LoopCost[0].NonPredCost > LoopCost[0].PredCost ||
1223 LoopCost[1].NonPredCost >= LoopCost[1].PredCost) {
1224 ORmissL <<
"No select conversion in the loop due to no reduction of loop's "
1230 Scaled64 Gain[2] = {LoopCost[0].PredCost - LoopCost[0].NonPredCost,
1231 LoopCost[1].PredCost - LoopCost[1].NonPredCost};
1238 Scaled64 RelativeGain = Scaled64::get(100) * Gain[1] / LoopCost[1].PredCost;
1239 ORmissL <<
"No select conversion in the loop due to small reduction of "
1240 "loop's critical path. Gain="
1241 << Gain[1].toString()
1242 <<
", RelativeGain=" << RelativeGain.toString() <<
"%. ";
1252 if (Gain[1] > Gain[0]) {
1253 Scaled64 GradientGain = Scaled64::get(100) * (Gain[1] - Gain[0]) /
1254 (LoopCost[1].PredCost - LoopCost[0].PredCost);
1256 ORmissL <<
"No select conversion in the loop due to small gradient gain. "
1258 << GradientGain.toString() <<
"%. ";
1264 else if (Gain[1] < Gain[0]) {
1266 <<
"No select conversion in the loop due to negative gradient gain. ";
1280bool SelectOptimizeImpl::computeLoopCosts(
1281 const Loop *L,
const SelectGroups &SIGroups,
1283 LLVM_DEBUG(
dbgs() <<
"Calculating Latency / IPredCost / INonPredCost of loop "
1284 <<
L->getHeader()->getName() <<
"\n");
1285 const auto SImap = getSImap(SIGroups);
1286 const auto SGmap = getSGmap(SIGroups);
1289 const unsigned Iterations = 2;
1290 for (
unsigned Iter = 0; Iter < Iterations; ++Iter) {
1292 CostInfo &MaxCost = LoopCost[Iter];
1295 if (
I.isDebugOrPseudoInst())
1298 Scaled64 IPredCost = Scaled64::getZero(),
1299 INonPredCost = Scaled64::getZero();
1304 for (
const Use &U :
I.operands()) {
1308 if (
auto It = InstCostMap.
find(UI); It != InstCostMap.
end()) {
1309 IPredCost = std::max(IPredCost, It->second.PredCost);
1310 INonPredCost = std::max(INonPredCost, It->second.NonPredCost);
1313 auto ILatency = computeInstCost(&
I);
1316 ORmissL <<
"Invalid instruction cost preventing analysis and "
1317 "optimization of the inner-most loop containing this "
1322 IPredCost += Scaled64::get(*ILatency);
1323 INonPredCost += Scaled64::get(*ILatency);
1331 if (
auto It = SImap.find(&
I); It != SImap.end()) {
1332 auto SI = It->second;
1333 const auto *SG = SGmap.at(&
I);
1334 Scaled64 TrueOpCost =
SI.getOpCostOnBranch(
true, InstCostMap,
TTI);
1335 Scaled64 FalseOpCost =
SI.getOpCostOnBranch(
false, InstCostMap,
TTI);
1336 Scaled64 PredictedPathCost =
1337 getPredictedPathCost(TrueOpCost, FalseOpCost,
SI);
1339 Scaled64 CondCost = Scaled64::getZero();
1341 if (
auto It = InstCostMap.
find(CI); It != InstCostMap.
end())
1342 CondCost = It->second.NonPredCost;
1343 Scaled64 MispredictCost = getMispredictionCost(
SI, CondCost);
1345 INonPredCost = PredictedPathCost + MispredictCost;
1348 << INonPredCost <<
" for " <<
I <<
"\n");
1350 InstCostMap[&
I] = {IPredCost, INonPredCost};
1351 MaxCost.PredCost = std::max(MaxCost.PredCost, IPredCost);
1352 MaxCost.NonPredCost = std::max(MaxCost.NonPredCost, INonPredCost);
1356 <<
" MaxCost = " << MaxCost.PredCost <<
" "
1357 << MaxCost.NonPredCost <<
"\n");
1363SelectOptimizeImpl::getSImap(
const SelectGroups &SIGroups) {
1365 for (
const SelectGroup &ASI : SIGroups)
1366 for (
const SelectLike &
SI : ASI.Selects)
1372SelectOptimizeImpl::getSGmap(
const SelectGroups &SIGroups) {
1374 for (
const SelectGroup &ASI : SIGroups)
1375 for (
const SelectLike &
SI : ASI.Selects)
1380std::optional<uint64_t>
1381SelectOptimizeImpl::computeInstCost(
const Instruction *
I) {
1385 return std::optional<uint64_t>(ICost.
getValue());
1386 return std::nullopt;
1390SelectOptimizeImpl::getMispredictionCost(
const SelectLike
SI,
1391 const Scaled64 CondCost) {
1399 if (isSelectHighlyPredictable(
SI))
1405 Scaled64 MispredictCost =
1406 std::max(Scaled64::get(MispredictPenalty), CondCost) *
1407 Scaled64::get(MispredictRate);
1408 MispredictCost /= Scaled64::get(100);
1410 return MispredictCost;
1416SelectOptimizeImpl::getPredictedPathCost(Scaled64 TrueCost, Scaled64 FalseCost,
1417 const SelectLike
SI) {
1418 Scaled64 PredPathCost;
1419 uint64_t TrueWeight, FalseWeight;
1421 uint64_t SumWeight = TrueWeight + FalseWeight;
1422 if (SumWeight != 0) {
1423 PredPathCost = TrueCost * Scaled64::get(TrueWeight) +
1424 FalseCost * Scaled64::get(FalseWeight);
1425 PredPathCost /= Scaled64::get(SumWeight);
1426 return PredPathCost;
1431 PredPathCost = std::max(TrueCost * Scaled64::get(3) + FalseCost,
1432 FalseCost * Scaled64::get(3) + TrueCost);
1433 PredPathCost /= Scaled64::get(4);
1434 return PredPathCost;
1437bool SelectOptimizeImpl::isSelectKindSupported(
const SelectLike
SI) {
1439 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.
const SmallVectorImpl< MachineOperand > & 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 TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
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 std::optional< unsigned > getOpcode(ArrayRef< VPValue * > Values)
Returns the opcode of Values or ~0 if they do not all agree.
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...
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.
LLVM_ABI BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="", bool Before=false)
Split the basic block into two basic blocks at the specified instruction.
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 if the block is well formed or null if the block is not well forme...
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.
Conditional or Unconditional Branch instruction.
static BranchInst * Create(BasicBlock *IfTrue, InsertPosition InsertBefore=nullptr)
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)
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
DenseMapIterator< KeyT, ValueT, KeyInfoT, BucketT > iterator
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
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 bool isDebugOrPseudoInst() const LLVM_READONLY
Return true if the instruction is a DbgInfoIntrinsic or PseudoProbeInst.
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.
void setDebugLoc(DebugLoc Loc)
Set the debug location information for 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()
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.
const MCSchedModel * getMCSchedModel() const
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 const TargetLowering * getTargetLowering() const
bool isIntegerTy() const
True if this is an instance of IntegerType.
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.
class_match< ConstantInt > m_ConstantInt()
Match an arbitrary ConstantInt and ignore it.
ThreeOps_match< Cond, LHS, RHS, Instruction::Select > m_Select(const Cond &C, const LHS &L, const RHS &R)
Matches SelectInst.
class_match< Value > m_Value()
Match an arbitrary value and ignore it.
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)
is_zero m_Zero()
Match any null constant or a vector with all elements equal to 0.
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.
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
UnaryFunction for_each(R &&Range, UnaryFunction F)
Provide wrappers to std::for_each which take ranges instead of having to pass begin/end explicitly.
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...
constexpr T divideNearest(U Numerator, V Denominator)
Returns (Numerator / Denominator) rounded by round-half-up.
auto dyn_cast_or_null(const Y &Val)
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...
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.
unsigned MispredictPenalty