89#define DEBUG_TYPE "machine-outliner"
96STATISTIC(NumOutlined,
"Number of candidates outlined");
97STATISTIC(FunctionsCreated,
"Number of functions created");
100STATISTIC(NumLegalInUnsignedVec,
"Outlinable instructions mapped");
102 "Unoutlinable instructions mapped + number of sentinel values");
103STATISTIC(NumSentinels,
"Sentinel values inserted during mapping");
105 "Invisible instructions skipped during mapping");
107 "Total number of instructions mapped and saved to mapping vector");
109 "Count of hashing attempts made for outlined functions");
111 "Count of unsuccessful hashing attempts for outlined functions");
112STATISTIC(NumRemovedLOHs,
"Total number of Linker Optimization Hints removed");
114 "Number of times outlining was blocked by PGO");
116 "Number of times outlining was allowed from cold functions");
118 "Number of times outlining was blocked conservatively when profile "
119 "counts were missing");
121 "Number of times outlining was allowed optimistically when profile "
122 "counts were missing");
131 cl::desc(
"Enable the machine outliner on linkonceodr functions"),
140 "Number of times to rerun the outliner after the initial outline"));
145 "The minimum size in bytes before an outlining candidate is accepted"));
149 cl::desc(
"Consider all leaf descendants of internal nodes of the suffix "
150 "tree as candidates for outlining (if false, only leaf children "
155 cl::desc(
"Disable global outlining only by ignoring "
156 "the codegen data generation or use"),
160 "append-content-hash-outlined-name",
cl::Hidden,
161 cl::desc(
"This appends the content hash to the globally outlined function "
162 "name. It's beneficial for enhancing the precision of the stable "
163 "hash and for ordering the outlined functions."),
169struct InstructionMapper {
176 unsigned IllegalInstrNumber = -3;
180 unsigned LegalInstrNumber = 0;
184 InstructionIntegerMap;
200 bool AddedIllegalLastTime =
false;
208 unsigned mapToLegalUnsigned(
210 bool &HaveLegalRange,
unsigned &NumLegalInBlock,
215 AddedIllegalLastTime =
false;
219 if (CanOutlineWithPrevInstr)
220 HaveLegalRange =
true;
221 CanOutlineWithPrevInstr =
true;
233 std::tie(ResultIt, WasInserted) =
234 InstructionIntegerMap.
insert(std::make_pair(&
MI, LegalInstrNumber));
235 unsigned MINumber = ResultIt->second;
244 if (LegalInstrNumber >= IllegalInstrNumber)
248 "Tried to assign DenseMap empty key to instruction.");
251 ++NumLegalInUnsignedVec;
261 unsigned mapToIllegalUnsigned(
263 SmallVector<unsigned> &UnsignedVecForMBB,
266 CanOutlineWithPrevInstr =
false;
269 if (AddedIllegalLastTime)
270 return IllegalInstrNumber;
273 AddedIllegalLastTime =
true;
274 unsigned MINumber = IllegalInstrNumber;
277 UnsignedVecForMBB.
push_back(IllegalInstrNumber);
278 IllegalInstrNumber--;
280 ++NumIllegalInUnsignedVec;
282 assert(LegalInstrNumber < IllegalInstrNumber &&
283 "Instruction mapping overflow!");
285 assert(IllegalInstrNumber != DenseMapInfo<unsigned>::getEmptyKey() &&
286 "IllegalInstrNumber cannot be DenseMap empty key!");
301 void convertToUnsignedVec(MachineBasicBlock &
MBB,
302 const TargetInstrInfo &
TII) {
304 <<
"' to unsigned vector ***\n");
308 if (!
TII.isMBBSafeToOutlineFrom(
MBB, Flags))
311 auto OutlinableRanges =
TII.getOutlinableRanges(
MBB, Flags);
313 <<
" outlinable range(s)\n");
314 if (OutlinableRanges.empty())
324 unsigned NumLegalInBlock = 0;
328 bool HaveLegalRange =
false;
332 bool CanOutlineWithPrevInstr =
false;
336 SmallVector<unsigned> UnsignedVecForMBB;
340 for (
auto &OutlinableRange : OutlinableRanges) {
341 auto OutlinableRangeBegin = OutlinableRange.first;
342 auto OutlinableRangeEnd = OutlinableRange.second;
346 << std::distance(OutlinableRangeBegin, OutlinableRangeEnd)
347 <<
" instruction range\n");
349 unsigned NumSkippedInRange = 0;
351 for (; It != OutlinableRangeBegin; ++It) {
355 mapToIllegalUnsigned(It, CanOutlineWithPrevInstr, UnsignedVecForMBB,
360 <<
" instructions outside outlinable range\n");
362 assert(It !=
MBB.
end() &&
"Should still have instructions?");
365 for (; It != OutlinableRangeEnd; ++It) {
367 switch (
TII.getOutliningType(MMI, It, Flags)) {
368 case InstrType::Illegal:
369 mapToIllegalUnsigned(It, CanOutlineWithPrevInstr, UnsignedVecForMBB,
373 case InstrType::Legal:
374 mapToLegalUnsigned(It, CanOutlineWithPrevInstr, HaveLegalRange,
375 NumLegalInBlock, UnsignedVecForMBB,
379 case InstrType::LegalTerminator:
380 mapToLegalUnsigned(It, CanOutlineWithPrevInstr, HaveLegalRange,
381 NumLegalInBlock, UnsignedVecForMBB,
385 mapToIllegalUnsigned(It, CanOutlineWithPrevInstr, UnsignedVecForMBB,
389 case InstrType::Invisible:
393 AddedIllegalLastTime =
false;
399 LLVM_DEBUG(
dbgs() <<
"HaveLegalRange = " << HaveLegalRange <<
"\n");
403 if (HaveLegalRange) {
408 mapToIllegalUnsigned(It, CanOutlineWithPrevInstr, UnsignedVecForMBB,
416 InstructionMapper(
const MachineModuleInfo &MMI_) : MMI(MMI_) {
419 static_assert(DenseMapInfo<unsigned>::getEmptyKey() ==
420 static_cast<unsigned>(-1));
437 MachineModuleInfo *MMI =
nullptr;
438 const TargetMachine *TM =
nullptr;
442 bool OutlineFromLinkOnceODRs =
false;
445 unsigned OutlineRepeatedNum = 0;
450 RunOutliner RunOutlinerMode = RunOutliner::AlwaysOutline;
458 std::unique_ptr<OutlinedHashTree> LocalHashTree;
469 StringRef getPassName()
const override {
return "Machine Outliner"; }
471 void getAnalysisUsage(AnalysisUsage &AU)
const override {
476 if (RunOutlinerMode == RunOutliner::OptimisticPGO ||
477 RunOutlinerMode == RunOutliner::ConservativePGO) {
482 ModulePass::getAnalysisUsage(AU);
485 MachineOutliner() : ModulePass(ID) {}
489 void emitNotOutliningCheaperRemark(
490 unsigned StringLen, std::vector<Candidate> &CandidatesForRepeatedSeq,
491 OutlinedFunction &OF);
494 void emitOutlinedFunctionRemark(OutlinedFunction &OF);
510 findCandidates(InstructionMapper &Mapper,
511 std::vector<std::unique_ptr<OutlinedFunction>> &FunctionList);
519 void findGlobalCandidates(
520 InstructionMapper &Mapper,
521 std::vector<std::unique_ptr<OutlinedFunction>> &FunctionList);
531 std::vector<std::unique_ptr<OutlinedFunction>> &FunctionList,
532 InstructionMapper &Mapper,
unsigned &OutlinedFunctionNum);
536 InstructionMapper &Mapper,
542 void computeAndPublishHashSequence(MachineFunction &MF,
unsigned CandSize);
545 void initializeOutlinerMode(
const Module &M);
548 void emitOutlinedHashTree(
Module &M);
551 bool runOnModule(
Module &M)
override;
555 bool doOutline(
Module &M,
unsigned &OutlinedFunctionNum);
560 for (
const Candidate &
C :
OF.Candidates)
561 if (MachineFunction *MF =
C.getMF())
562 if (DISubprogram *SP = MF->getFunction().getSubprogram())
569 void populateMapper(InstructionMapper &Mapper,
Module &M);
575 void initSizeRemarkInfo(
const Module &M,
576 StringMap<unsigned> &FunctionToInstrCount);
581 emitInstrCountChangedRemark(
const Module &M,
582 const StringMap<unsigned> &FunctionToInstrCount);
586char MachineOutliner::ID = 0;
589 MachineOutliner *OL =
new MachineOutliner();
590 OL->RunOutlinerMode = RunOutlinerMode;
597void MachineOutliner::emitNotOutliningCheaperRemark(
598 unsigned StringLen,
std::vector<
Candidate> &CandidatesForRepeatedSeq,
604 Candidate &
C = CandidatesForRepeatedSeq.front();
608 C.front().getDebugLoc(),
C.getMBB());
609 R <<
"Did not outline " <<
NV(
"Length", StringLen) <<
" instructions"
610 <<
" from " <<
NV(
"NumOccurrences", CandidatesForRepeatedSeq.size())
612 <<
" Bytes from outlining all occurrences ("
613 <<
NV(
"OutliningCost", OF.getOutliningCost()) <<
")"
614 <<
" >= Unoutlined instruction bytes ("
615 <<
NV(
"NotOutliningCost", OF.getNotOutlinedCost()) <<
")"
616 <<
" (Also found at: ";
619 for (
unsigned i = 1, e = CandidatesForRepeatedSeq.size(); i < e; i++) {
621 CandidatesForRepeatedSeq[i].front().
getDebugLoc());
632 MachineBasicBlock *
MBB = &*
OF.MF->begin();
633 MachineOptimizationRemarkEmitter
MORE(*
OF.MF,
nullptr);
634 MachineOptimizationRemark
R(
DEBUG_TYPE,
"OutlinedFunction",
636 R <<
"Saved " <<
NV(
"OutliningBenefit",
OF.getBenefit()) <<
" bytes by "
637 <<
"outlining " <<
NV(
"Length",
OF.getNumInstrs()) <<
" instructions "
638 <<
"from " <<
NV(
"NumOccurrences",
OF.getOccurrenceCount())
643 for (
size_t i = 0, e =
OF.Candidates.size(); i < e; i++) {
645 R <<
NV((Twine(
"StartLoc") + Twine(i)).str(),
646 OF.Candidates[i].front().getDebugLoc());
669 auto &InstrList = Mapper.InstrList;
670 auto &UnsignedVec = Mapper.UnsignedVec;
679 auto getValidInstr = [&](
unsigned Index) ->
const MachineInstr * {
680 if (UnsignedVec[Index] >= Mapper.LegalInstrNumber)
682 return &(*InstrList[Index]);
685 auto getStableHashAndFollow =
690 auto It = CurrNode->Successors.find(StableHash);
691 return (It == CurrNode->Successors.end()) ? nullptr : It->second.get();
694 for (
unsigned I = 0;
I <
Size; ++
I) {
696 if (!
MI ||
MI->isDebugInstr())
698 const HashNode *CurrNode = getStableHashAndFollow(*
MI, RootNode);
702 for (
unsigned J =
I + 1; J <
Size; ++J) {
709 CurrNode = getStableHashAndFollow(*MJ, CurrNode);
719 return MatchedEntries;
722void MachineOutliner::findGlobalCandidates(
723 InstructionMapper &Mapper,
724 std::vector<std::unique_ptr<OutlinedFunction>> &FunctionList) {
725 FunctionList.
clear();
727 auto &MBBFlagsMap = Mapper.MBBFlagsMap;
729 std::vector<Candidate> CandidatesForRepeatedSeq;
731 CandidatesForRepeatedSeq.clear();
734 auto Length = ME.EndIdx - ME.StartIdx + 1;
735 MachineBasicBlock *
MBB = StartIt->getParent();
736 CandidatesForRepeatedSeq.emplace_back(ME.StartIdx,
Length, StartIt, EndIt,
739 const TargetInstrInfo *
TII =
741 unsigned MinRepeats = 1;
742 std::optional<std::unique_ptr<OutlinedFunction>>
OF =
743 TII->getOutliningCandidateInfo(*MMI, CandidatesForRepeatedSeq,
745 if (!
OF.has_value() ||
OF.value()->Candidates.empty())
748 assert(
OF.value()->Candidates.size() == MinRepeats);
749 FunctionList.emplace_back(std::make_unique<GlobalOutlinedFunction>(
750 std::move(
OF.value()), ME.Count));
754void MachineOutliner::findCandidates(
755 InstructionMapper &Mapper,
756 std::vector<std::unique_ptr<OutlinedFunction>> &FunctionList) {
757 FunctionList.clear();
762 std::vector<Candidate> CandidatesForRepeatedSeq;
763 LLVM_DEBUG(
dbgs() <<
"*** Discarding overlapping candidates *** \n");
765 dbgs() <<
"Searching for overlaps in all repeated sequences...\n");
766 for (SuffixTree::RepeatedSubstring &RS : ST) {
767 CandidatesForRepeatedSeq.clear();
768 unsigned StringLen =
RS.Length;
772 unsigned NumDiscarded = 0;
773 unsigned NumKept = 0;
778 for (
const unsigned &StartIdx :
RS.StartIndices) {
800 unsigned EndIdx = StartIdx + StringLen - 1;
801 if (!CandidatesForRepeatedSeq.empty() &&
802 StartIdx <= CandidatesForRepeatedSeq.back().getEndIdx()) {
805 LLVM_DEBUG(
dbgs() <<
" .. DISCARD candidate @ [" << StartIdx <<
", "
806 << EndIdx <<
"]; overlaps with candidate @ ["
807 << CandidatesForRepeatedSeq.back().getStartIdx()
808 <<
", " << CandidatesForRepeatedSeq.back().getEndIdx()
821 MachineBasicBlock *
MBB = StartIt->getParent();
822 CandidatesForRepeatedSeq.emplace_back(StartIdx, StringLen, StartIt, EndIt,
824 Mapper.MBBFlagsMap[
MBB]);
831 unsigned MinRepeats = 2;
836 if (CandidatesForRepeatedSeq.size() < MinRepeats)
841 const TargetInstrInfo *
TII =
842 CandidatesForRepeatedSeq[0].getMF()->getSubtarget().getInstrInfo();
844 std::optional<std::unique_ptr<OutlinedFunction>>
OF =
845 TII->getOutliningCandidateInfo(*MMI, CandidatesForRepeatedSeq,
850 if (!
OF.has_value() ||
OF.value()->Candidates.size() < MinRepeats)
855 emitNotOutliningCheaperRemark(StringLen, CandidatesForRepeatedSeq,
860 FunctionList.emplace_back(std::move(
OF.value()));
864void MachineOutliner::computeAndPublishHashSequence(MachineFunction &MF,
867 SmallVector<stable_hash> OutlinedHashSequence;
868 for (
auto &
MBB : MF) {
869 for (
auto &NewMI :
MBB) {
872 OutlinedHashSequence.
clear();
883 MF.getName().str() +
".content." + std::to_string(CombinedHash);
884 MF.getFunction().setName(NewName);
888 if (OutlinerMode == CGDataMode::Write) {
889 StableHashAttempts++;
890 if (!OutlinedHashSequence.
empty())
891 LocalHashTree->insert({OutlinedHashSequence, CandSize});
897MachineFunction *MachineOutliner::createOutlinedFunction(
898 Module &M, OutlinedFunction &OF, InstructionMapper &Mapper,
unsigned Name) {
903 std::string FunctionName =
"OUTLINED_FUNCTION_";
904 if (OutlineRepeatedNum > 0)
905 FunctionName += std::to_string(OutlineRepeatedNum + 1) +
"_";
906 FunctionName += std::to_string(Name);
910 LLVMContext &
C =
M.getContext();
912 Function::ExternalLinkage, FunctionName, M);
917 F->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
921 F->addFnAttr(Attribute::OptimizeForSize);
922 F->addFnAttr(Attribute::MinSize);
924 Candidate &FirstCand =
OF.Candidates.front();
925 const TargetInstrInfo &
TII =
928 TII.mergeOutliningCandidateAttributes(*
F,
OF.Candidates);
932 OF.Candidates.cbegin(),
OF.Candidates.cend(), UWTableKind::None,
934 return std::max(K, C.getMF()->getFunction().getUWTableKind());
936 F->setUWTableKind(UW);
940 Builder.CreateRetVoid();
942 MachineModuleInfo &MMI = getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
950 MachineFunction *OriginalMF = FirstCand.
front().
getMF();
951 const std::vector<MCCFIInstruction> &Instrs =
953 for (
auto &
MI : FirstCand) {
954 if (
MI.isDebugInstr())
959 if (
MI.isCFIInstruction()) {
960 unsigned CFIIndex =
MI.getOperand(0).getCFIIndex();
961 MCCFIInstruction CFI = Instrs[CFIIndex];
971 for (
auto I = std::next(NewMI.
getIterator());
I != BundleEnd; ++
I)
977 if (OutlinerMode != CGDataMode::None)
978 computeAndPublishHashSequence(MF,
OF.Candidates.size());
988 const MachineRegisterInfo &MRI = MF.
getRegInfo();
990 LivePhysRegs LiveIns(
TRI);
991 for (
auto &Cand :
OF.Candidates) {
993 MachineBasicBlock &OutlineBB = *Cand.front().getParent();
994 LivePhysRegs CandLiveIns(
TRI);
995 CandLiveIns.addLiveOuts(OutlineBB);
996 for (
const MachineInstr &
MI :
998 CandLiveIns.stepBackward(
MI);
1003 LiveIns.addReg(
Reg);
1007 TII.buildOutlinedFrame(
MBB, MF, OF);
1013 DICompileUnit *CU =
SP->getUnit();
1014 DIBuilder
DB(M,
true, CU);
1015 DIFile *
Unit =
SP->getFile();
1019 raw_string_ostream MangledNameStream(Dummy);
1022 DISubprogram *OutlinedSP =
DB.createFunction(
1023 Unit ,
F->getName(), StringRef(Dummy), Unit ,
1025 DB.createSubroutineType(
DB.getOrCreateTypeArray({})),
1027 DINode::DIFlags::FlagArtificial ,
1029 DISubprogram::SPFlagDefinition | DISubprogram::SPFlagOptimized);
1032 F->setSubprogram(OutlinedSP);
1040bool MachineOutliner::outline(
1041 Module &M, std::vector<std::unique_ptr<OutlinedFunction>> &FunctionList,
1042 InstructionMapper &Mapper,
unsigned &OutlinedFunctionNum) {
1044 LLVM_DEBUG(
dbgs() <<
"NUMBER OF POTENTIAL FUNCTIONS: " << FunctionList.size()
1046 bool OutlinedSomething =
false;
1050 stable_sort(FunctionList, [](
const std::unique_ptr<OutlinedFunction> &
LHS,
1051 const std::unique_ptr<OutlinedFunction> &
RHS) {
1052 return LHS->getNotOutlinedCost() *
RHS->getOutliningCost() >
1053 RHS->getNotOutlinedCost() *
LHS->getOutliningCost();
1058 auto *UnsignedVecBegin = Mapper.UnsignedVec.
begin();
1060 for (
auto &OF : FunctionList) {
1062 auto NumCandidatesBefore =
OF->Candidates.size();
1066 erase_if(
OF->Candidates, [&UnsignedVecBegin](Candidate &
C) {
1067 return std::any_of(UnsignedVecBegin + C.getStartIdx(),
1068 UnsignedVecBegin + C.getEndIdx() + 1, [](unsigned I) {
1069 return I == static_cast<unsigned>(-1);
1074 auto NumCandidatesAfter =
OF->Candidates.size();
1075 LLVM_DEBUG(
dbgs() <<
"PRUNED: " << NumCandidatesBefore - NumCandidatesAfter
1076 <<
"/" << NumCandidatesBefore <<
" candidates\n");
1094 SmallPtrSet<MachineInstr *, 2> MIs;
1095 for (Candidate &
C :
OF->Candidates) {
1096 for (MachineInstr &
MI :
C)
1105 emitOutlinedFunctionRemark(*OF);
1107 OutlinedFunctionNum++;
1108 MachineFunction *MF =
OF->MF;
1114 for (Candidate &
C :
OF->Candidates) {
1115 MachineBasicBlock &
MBB = *
C.getMBB();
1120 auto CallInst =
TII.insertOutlinedCall(M,
MBB, StartIt, *MF,
C);
1123 auto MBBBeingOutlinedFromName =
1129 << MFBeingOutlinedFromName <<
":"
1130 << MBBBeingOutlinedFromName <<
"\n");
1142 SmallSet<Register, 2> UseRegs, DefRegs;
1151 Last = std::next(CallInst.getReverse());
1152 Iter !=
Last; Iter++) {
1153 MachineInstr *
MI = &*Iter;
1154 if (
MI->isDebugInstr())
1156 SmallSet<Register, 2> InstrUseRegs;
1157 for (MachineOperand &MOP :
MI->operands()) {
1164 DefRegs.
insert(MOP.getReg());
1165 if (UseRegs.
count(MOP.getReg()) &&
1166 !InstrUseRegs.
count(MOP.getReg()))
1169 UseRegs.
erase(MOP.getReg());
1170 }
else if (!MOP.isUndef()) {
1173 UseRegs.
insert(MOP.getReg());
1174 InstrUseRegs.
insert(MOP.getReg());
1177 if (
MI->isCandidateForAdditionalCallInfo())
1178 MI->getMF()->eraseAdditionalCallInfo(
MI);
1183 CallInst->addOperand(
1189 CallInst->addOperand(
1197 MBB.
erase(std::next(StartIt), std::next(EndIt));
1200 for (
unsigned &
I :
make_range(UnsignedVecBegin +
C.getStartIdx(),
1201 UnsignedVecBegin +
C.getEndIdx() + 1))
1202 I =
static_cast<unsigned>(-1);
1203 OutlinedSomething =
true;
1210 LLVM_DEBUG(
dbgs() <<
"OutlinedSomething = " << OutlinedSomething <<
"\n");
1211 return OutlinedSomething;
1221 auto *MF =
MBB.getParent();
1223 ++NumPGOAllowedCold;
1227 auto *BB =
MBB.getBasicBlock();
1228 if (BB && PSI && BFI)
1234 if (
TII->shouldOutlineFromFunctionByDefault(*MF)) {
1236 ++NumPGOOptimisticOutlined;
1243 ++NumPGOConservativeBlockedOutlined;
1247void MachineOutliner::populateMapper(InstructionMapper &Mapper,
Module &M) {
1251 bool EnableProfileGuidedOutlining =
1252 RunOutlinerMode == RunOutliner::OptimisticPGO ||
1253 RunOutlinerMode == RunOutliner::ConservativePGO;
1254 ProfileSummaryInfo *PSI =
nullptr;
1255 if (EnableProfileGuidedOutlining)
1256 PSI = &getAnalysis<ProfileSummaryInfoWrapperPass>().getPSI();
1257 for (Function &
F : M) {
1260 if (
F.hasFnAttribute(Attribute::NoOutline)) {
1261 LLVM_DEBUG(
dbgs() <<
"SKIP: Function has nooutline attribute\n");
1272 LLVM_DEBUG(
dbgs() <<
"SKIP: Function does not have a MachineFunction\n");
1277 BlockFrequencyInfo *BFI =
nullptr;
1278 if (EnableProfileGuidedOutlining &&
F.hasProfileData())
1279 BFI = &getAnalysis<BlockFrequencyInfoWrapperPass>(
F).getBFI();
1280 if (RunOutlinerMode == RunOutliner::TargetDefault &&
1281 !
TII->shouldOutlineFromFunctionByDefault(*MF)) {
1282 LLVM_DEBUG(
dbgs() <<
"SKIP: Target does not want to outline from "
1283 "function by default\n");
1289 if (!
TII->isFunctionSafeToOutlineFrom(*MF, OutlineFromLinkOnceODRs)) {
1291 <<
": unsafe to outline from\n");
1298 const unsigned MinMBBSize = 2;
1300 for (MachineBasicBlock &
MBB : *MF) {
1308 if (
MBB.
size() < MinMBBSize) {
1309 LLVM_DEBUG(
dbgs() <<
" SKIP: MBB size less than minimum size of "
1310 << MinMBBSize <<
"\n");
1322 ++NumPGOBlockedOutlined;
1327 Mapper.convertToUnsignedVec(
MBB, *
TII);
1331 UnsignedVecSize = Mapper.UnsignedVec.
size();
1334void MachineOutliner::initSizeRemarkInfo(
1335 const Module &M, StringMap<unsigned> &FunctionToInstrCount) {
1338 for (
const Function &
F : M) {
1349void MachineOutliner::emitInstrCountChangedRemark(
1350 const Module &M,
const StringMap<unsigned> &FunctionToInstrCount) {
1354 for (
const Function &
F : M) {
1362 std::string Fname = std::string(
F.getName());
1364 unsigned FnCountBefore = 0;
1367 auto It = FunctionToInstrCount.
find(Fname);
1371 if (It != FunctionToInstrCount.
end())
1372 FnCountBefore = It->second;
1375 int64_t FnDelta =
static_cast<int64_t
>(FnCountAfter) -
1376 static_cast<int64_t
>(FnCountBefore);
1380 MachineOptimizationRemarkEmitter
MORE(*MF,
nullptr);
1382 MachineOptimizationRemarkAnalysis
R(
"size-info",
"FunctionMISizeChange",
1383 DiagnosticLocation(), &MF->
front());
1384 R << DiagnosticInfoOptimizationBase::Argument(
"Pass",
"Machine Outliner")
1386 << DiagnosticInfoOptimizationBase::Argument(
"Function",
F.getName())
1387 <<
": MI instruction count changed from "
1388 << DiagnosticInfoOptimizationBase::Argument(
"MIInstrsBefore",
1391 << DiagnosticInfoOptimizationBase::Argument(
"MIInstrsAfter",
1394 << DiagnosticInfoOptimizationBase::Argument(
"Delta", FnDelta);
1400void MachineOutliner::initializeOutlinerMode(
const Module &M) {
1404 if (
auto *IndexWrapperPass =
1405 getAnalysisIfAvailable<ImmutableModuleSummaryIndexWrapperPass>()) {
1406 auto *TheIndex = IndexWrapperPass->getIndex();
1409 if (TheIndex && !TheIndex->hasExportedFunctions(M))
1418 OutlinerMode = CGDataMode::Write;
1420 LocalHashTree = std::make_unique<OutlinedHashTree>();
1423 OutlinerMode = CGDataMode::Read;
1426void MachineOutliner::emitOutlinedHashTree(
Module &M) {
1428 if (!LocalHashTree->empty()) {
1430 dbgs() <<
"Emit outlined hash tree. Size: " << LocalHashTree->size()
1433 SmallVector<char> Buf;
1434 raw_svector_ostream OS(Buf);
1436 OutlinedHashTreeRecord HTR(std::move(LocalHashTree));
1439 llvm::StringRef
Data(Buf.data(), Buf.size());
1440 std::unique_ptr<MemoryBuffer> Buffer =
1443 Triple
TT(
M.getTargetTriple());
1450bool MachineOutliner::runOnModule(
Module &M) {
1460 initializeOutlinerMode(M);
1462 MMI = &getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
1463 TM = &getAnalysis<TargetPassConfig>().getTM<TargetMachine>();
1466 unsigned OutlinedFunctionNum = 0;
1468 OutlineRepeatedNum = 0;
1469 if (!doOutline(M, OutlinedFunctionNum))
1473 OutlinedFunctionNum = 0;
1474 OutlineRepeatedNum++;
1475 if (!doOutline(M, OutlinedFunctionNum)) {
1477 dbgs() <<
"Did not outline on iteration " <<
I + 2 <<
" out of "
1484 if (OutlinerMode == CGDataMode::Write)
1485 emitOutlinedHashTree(M);
1490bool MachineOutliner::doOutline(
Module &M,
unsigned &OutlinedFunctionNum) {
1497 dbgs() <<
"Machine Outliner: Running on ";
1498 switch (RunOutlinerMode) {
1499 case RunOutliner::AlwaysOutline:
1500 dbgs() <<
"all functions";
1502 case RunOutliner::OptimisticPGO:
1503 dbgs() <<
"optimistically cold functions";
1505 case RunOutliner::ConservativePGO:
1506 dbgs() <<
"conservatively cold functions";
1508 case RunOutliner::TargetDefault:
1509 dbgs() <<
"target-default functions";
1511 case RunOutliner::NeverOutline:
1520 InstructionMapper Mapper(*MMI);
1523 populateMapper(Mapper, M);
1524 std::vector<std::unique_ptr<OutlinedFunction>> FunctionList;
1527 if (OutlinerMode == CGDataMode::Read)
1528 findGlobalCandidates(Mapper, FunctionList);
1530 findCandidates(Mapper, FunctionList);
1541 bool ShouldEmitSizeRemarks =
M.shouldEmitInstrCountChangedRemark();
1542 StringMap<unsigned> FunctionToInstrCount;
1543 if (ShouldEmitSizeRemarks)
1544 initSizeRemarkInfo(M, FunctionToInstrCount);
1547 bool OutlinedSomething =
1548 outline(M, FunctionList, Mapper, OutlinedFunctionNum);
1553 if (ShouldEmitSizeRemarks && OutlinedSomething)
1554 emitInstrCountChangedRemark(M, FunctionToInstrCount);
1557 if (!OutlinedSomething)
1558 dbgs() <<
"Stopped outlining at iteration " << OutlineRepeatedNum
1559 <<
" because no changes were found.\n";
1562 return OutlinedSomething;
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file defines the DenseMap class.
const HexagonInstrInfo * TII
static DISubprogram * getSubprogramOrNull(OutlinableGroup &Group)
Get the subprogram if it exists for one of the outlined regions.
Module.h This file contains the declarations for the Module class.
This file implements the LivePhysRegs utility for tracking liveness of physical registers.
Machine Check Debug Module
static DebugLoc getDebugLoc(MachineBasicBlock::instr_iterator FirstMI, MachineBasicBlock::instr_iterator LastMI)
Return the first DebugLoc that has line number information, given a range of instructions.
static cl::opt< bool > DisableGlobalOutlining("disable-global-outlining", cl::Hidden, cl::desc("Disable global outlining only by ignoring " "the codegen data generation or use"), cl::init(false))
static bool allowPGOOutlining(RunOutliner RunOutlinerMode, const ProfileSummaryInfo *PSI, const BlockFrequencyInfo *BFI, MachineBasicBlock &MBB)
static cl::opt< unsigned > OutlinerBenefitThreshold("outliner-benefit-threshold", cl::init(1), cl::Hidden, cl::desc("The minimum size in bytes before an outlining candidate is accepted"))
static cl::opt< bool > OutlinerLeafDescendants("outliner-leaf-descendants", cl::init(true), cl::Hidden, cl::desc("Consider all leaf descendants of internal nodes of the suffix " "tree as candidates for outlining (if false, only leaf children " "are considered)"))
static cl::opt< bool > AppendContentHashToOutlinedName("append-content-hash-outlined-name", cl::Hidden, cl::desc("This appends the content hash to the globally outlined function " "name. It's beneficial for enhancing the precision of the stable " "hash and for ordering the outlined functions."), cl::init(true))
static cl::opt< unsigned > OutlinerReruns("machine-outliner-reruns", cl::init(0), cl::Hidden, cl::desc("Number of times to rerun the outliner after the initial outline"))
Number of times to re-run the outliner.
static cl::opt< bool > EnableLinkOnceODROutlining("enable-linkonceodr-outlining", cl::Hidden, cl::desc("Enable the machine outliner on linkonceodr functions"), cl::init(false))
static SmallVector< MatchedEntry > getMatchedEntries(InstructionMapper &Mapper)
Contains all data structures shared between the outliner implemented in MachineOutliner....
Register const TargetRegisterInfo * TRI
Promote Memory to Register
This is the interface to build a ModuleSummaryIndex for a module.
static Expected< Function * > createOutlinedFunction(OpenMPIRBuilder &OMPBuilder, IRBuilderBase &Builder, const OpenMPIRBuilder::TargetKernelDefaultAttrs &DefaultAttrs, StringRef FuncName, SmallVectorImpl< Value * > &Inputs, OpenMPIRBuilder::TargetBodyGenCallbackTy &CBFunc, OpenMPIRBuilder::TargetGenArgAccessorsCallbackTy &ArgAccessorFuncCB)
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
This file defines the SmallSet class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Target-Independent Code Generator Pass Configuration Options pass.
AnalysisUsage & addUsedIfAvailable()
Add the specified Pass class to the set of analyses used by this pass.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
void setPreservesAll()
Set by analyses that do not transform their input at all.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
BlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to estimate IR basic block frequen...
LLVM_ABI std::optional< uint64_t > getBlockProfileCount(const BasicBlock *BB, bool AllowSynthetic=false) const
Returns the estimated profile count of BB.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
@ InternalLinkage
Rename collisions when linking (static functions).
bool hasAddressTaken() const
Test whether this block is used as something other than the target of a terminator,...
LLVM_ABI DebugLoc findDebugLoc(instr_iterator MBBI)
Find the next valid DebugLoc starting at MBBI, skipping any debug instructions.
MachineInstrBundleIterator< MachineInstr, true > reverse_iterator
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
LLVM_ABI instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
MachineInstrBundleIterator< MachineInstr > iterator
LLVM_ABI StringRef getName() const
Return the name of the corresponding LLVM basic block, or an empty string.
unsigned getInstructionCount() const
Return the number of MachineInstrs in this MachineFunction.
unsigned addFrameInst(const MCCFIInstruction &Inst)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
const std::vector< MCCFIInstruction > & getFrameInstructions() const
Returns a reference to a list of cfi instructions in the function's prologue.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
void setIsOutlined(bool V)
const MachineFunctionProperties & getProperties() const
Get the function properties.
const MachineBasicBlock & front() const
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const MachineInstrBuilder & addCFIIndex(unsigned CFIIndex) const
reverse_iterator getReverse() const
Get a reverse iterator to the same node.
Representation of each machine instruction.
bool isDebugInstr() const
LLVM_ABI void dropMemRefs(MachineFunction &MF)
Clear this MachineInstr's memory reference descriptor list.
LLVM_ABI const MachineFunction * getMF() const
Return the function that contains the basic block that this instruction belongs to.
bool isBundledWithSucc() const
Return true if this instruction is part of a bundle, and it is not the last instruction in the bundle...
void setDebugLoc(DebugLoc DL)
Replace current source information with new such.
This class contains meta information specific to a module.
LLVM_ABI MachineFunction & getOrCreateMachineFunction(Function &F)
Returns the MachineFunction constructed for the IR function F.
LLVM_ABI MachineFunction * getMachineFunction(const Function &F) const
Returns the MachineFunction associated to IR function F if there is one, otherwise nullptr.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
LLVM_ABI void freezeReservedRegs()
freezeReservedRegs - Called by the register allocator to freeze the set of reserved registers before ...
const TargetRegisterInfo * getTargetRegisterInfo() const
LLVM_ABI void getNameWithPrefix(raw_ostream &OS, const GlobalValue *GV, bool CannotUsePrivateLabel) const
Print the appropriate prefix and the specified global variable's name.
static std::unique_ptr< MemoryBuffer > getMemBuffer(StringRef InputData, StringRef BufferName="", bool RequiresNullTerminator=true)
Open the specified memory range as a MemoryBuffer.
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
const HashNode * getRoot() const
Analysis providing profile information.
LLVM_ABI uint64_t getOrCompColdCountThreshold() const
Returns ColdCountThreshold if set.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
size_type count(const T &V) const
count - Return 1 if the element is in the set, 0 otherwise.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
reference emplace_back(ArgTypes &&... Args)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
iterator find(StringRef Key)
std::string str() const
Get the contents as an std::string.
constexpr bool empty() const
Check if the string is empty.
constexpr size_t size() const
Get the string size.
virtual size_t clearLinkerOptimizationHints(const SmallPtrSetImpl< MachineInstr * > &MIs) const
Remove all Linker Optimization Hints (LOH) associated with instructions in MIs and.
virtual const TargetInstrInfo * getInstrInfo() const
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ C
The default llvm calling convention, compatible with C.
@ BasicBlock
Various leaf nodes.
SmallVector< const MachineInstr * > InstrList
bool hasOutlinedHashTree()
const OutlinedHashTree * getOutlinedHashTree()
initializer< Ty > init(const Ty &Val)
Add a small namespace to avoid name clashes with the classes used in the streaming interface.
DiagnosticInfoOptimizationBase::Argument NV
This is an optimization pass for GlobalISel generic memory operations.
void stable_sort(R &&Range)
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
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.
uint64_t stable_hash
An opaque object representing a stable hash code.
auto reverse(ContainerTy &&C)
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI stable_hash stableHashValue(const MachineOperand &MO)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
MachineBasicBlock::instr_iterator getBundleEnd(MachineBasicBlock::instr_iterator I)
Returns an iterator pointing beyond the bundle containing I.
FunctionAddr VTableAddr Count
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
LLVM_ABI ModulePass * createMachineOutlinerPass(RunOutliner RunOutlinerMode)
This pass performs outlining on machine instructions directly before printing assembly.
FunctionAddr VTableAddr uintptr_t uintptr_t Data
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
stable_hash stable_hash_combine(ArrayRef< stable_hash > Buffer)
LLVM_ABI void embedBufferInModule(Module &M, MemoryBufferRef Buf, StringRef SectionName, Align Alignment=Align(1))
Embed the memory buffer Buf into the module M as a global using the specified section name.
LLVM_ABI void addLiveIns(MachineBasicBlock &MBB, const LivePhysRegs &LiveRegs)
Adds registers contained in LiveRegs to the block live-in list of MBB.
LLVM_ABI std::string getCodeGenDataSectionName(CGDataSectKind CGSK, Triple::ObjectFormatType OF, bool AddSegmentInfo=true)
Implement std::hash so that hash_code can be used in STL containers.
MatchedEntry(unsigned StartIdx, unsigned EndIdx, unsigned Count)
An information struct used to provide DenseMap with the various necessary components for a given valu...
A HashNode is an entry in an OutlinedHashTree, holding a hash value and a collection of Successors (o...
std::optional< unsigned > Terminals
The number of terminals in the sequence ending at this node.
An individual sequence of instructions to be replaced with a call to an outlined function.
MachineFunction * getMF() const
The information necessary to create an outlined function for some class of candidate.