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 tombstone or empty key to instruction.");
250 "Tried to assign DenseMap tombstone or empty key to instruction.");
253 ++NumLegalInUnsignedVec;
263 unsigned mapToIllegalUnsigned(
265 SmallVector<unsigned> &UnsignedVecForMBB,
268 CanOutlineWithPrevInstr =
false;
271 if (AddedIllegalLastTime)
272 return IllegalInstrNumber;
275 AddedIllegalLastTime =
true;
276 unsigned MINumber = IllegalInstrNumber;
279 UnsignedVecForMBB.
push_back(IllegalInstrNumber);
280 IllegalInstrNumber--;
282 ++NumIllegalInUnsignedVec;
284 assert(LegalInstrNumber < IllegalInstrNumber &&
285 "Instruction mapping overflow!");
287 assert(IllegalInstrNumber != DenseMapInfo<unsigned>::getEmptyKey() &&
288 "IllegalInstrNumber cannot be DenseMap tombstone or empty key!");
290 assert(IllegalInstrNumber != DenseMapInfo<unsigned>::getTombstoneKey() &&
291 "IllegalInstrNumber cannot be DenseMap tombstone or empty key!");
306 void convertToUnsignedVec(MachineBasicBlock &
MBB,
307 const TargetInstrInfo &
TII) {
309 <<
"' to unsigned vector ***\n");
313 if (!
TII.isMBBSafeToOutlineFrom(
MBB, Flags))
316 auto OutlinableRanges =
TII.getOutlinableRanges(
MBB, Flags);
318 <<
" outlinable range(s)\n");
319 if (OutlinableRanges.empty())
329 unsigned NumLegalInBlock = 0;
333 bool HaveLegalRange =
false;
337 bool CanOutlineWithPrevInstr =
false;
341 SmallVector<unsigned> UnsignedVecForMBB;
345 for (
auto &OutlinableRange : OutlinableRanges) {
346 auto OutlinableRangeBegin = OutlinableRange.first;
347 auto OutlinableRangeEnd = OutlinableRange.second;
351 << std::distance(OutlinableRangeBegin, OutlinableRangeEnd)
352 <<
" instruction range\n");
354 unsigned NumSkippedInRange = 0;
356 for (; It != OutlinableRangeBegin; ++It) {
360 mapToIllegalUnsigned(It, CanOutlineWithPrevInstr, UnsignedVecForMBB,
365 <<
" instructions outside outlinable range\n");
367 assert(It !=
MBB.
end() &&
"Should still have instructions?");
370 for (; It != OutlinableRangeEnd; ++It) {
372 switch (
TII.getOutliningType(MMI, It, Flags)) {
373 case InstrType::Illegal:
374 mapToIllegalUnsigned(It, CanOutlineWithPrevInstr, UnsignedVecForMBB,
378 case InstrType::Legal:
379 mapToLegalUnsigned(It, CanOutlineWithPrevInstr, HaveLegalRange,
380 NumLegalInBlock, UnsignedVecForMBB,
384 case InstrType::LegalTerminator:
385 mapToLegalUnsigned(It, CanOutlineWithPrevInstr, HaveLegalRange,
386 NumLegalInBlock, UnsignedVecForMBB,
390 mapToIllegalUnsigned(It, CanOutlineWithPrevInstr, UnsignedVecForMBB,
394 case InstrType::Invisible:
398 AddedIllegalLastTime =
false;
404 LLVM_DEBUG(
dbgs() <<
"HaveLegalRange = " << HaveLegalRange <<
"\n");
408 if (HaveLegalRange) {
413 mapToIllegalUnsigned(It, CanOutlineWithPrevInstr, UnsignedVecForMBB,
421 InstructionMapper(
const MachineModuleInfo &MMI_) : MMI(MMI_) {
424 static_assert(DenseMapInfo<unsigned>::getEmptyKey() ==
425 static_cast<unsigned>(-1));
426 static_assert(DenseMapInfo<unsigned>::getTombstoneKey() ==
427 static_cast<unsigned>(-2));
444 MachineModuleInfo *MMI =
nullptr;
445 const TargetMachine *TM =
nullptr;
449 bool OutlineFromLinkOnceODRs =
false;
452 unsigned OutlineRepeatedNum = 0;
457 RunOutliner RunOutlinerMode = RunOutliner::AlwaysOutline;
465 std::unique_ptr<OutlinedHashTree> LocalHashTree;
476 StringRef getPassName()
const override {
return "Machine Outliner"; }
478 void getAnalysisUsage(AnalysisUsage &AU)
const override {
483 if (RunOutlinerMode == RunOutliner::OptimisticPGO ||
484 RunOutlinerMode == RunOutliner::ConservativePGO) {
489 ModulePass::getAnalysisUsage(AU);
492 MachineOutliner() : ModulePass(ID) {}
496 void emitNotOutliningCheaperRemark(
497 unsigned StringLen, std::vector<Candidate> &CandidatesForRepeatedSeq,
498 OutlinedFunction &OF);
501 void emitOutlinedFunctionRemark(OutlinedFunction &OF);
517 findCandidates(InstructionMapper &Mapper,
518 std::vector<std::unique_ptr<OutlinedFunction>> &FunctionList);
526 void findGlobalCandidates(
527 InstructionMapper &Mapper,
528 std::vector<std::unique_ptr<OutlinedFunction>> &FunctionList);
538 std::vector<std::unique_ptr<OutlinedFunction>> &FunctionList,
539 InstructionMapper &Mapper,
unsigned &OutlinedFunctionNum);
543 InstructionMapper &Mapper,
549 void computeAndPublishHashSequence(MachineFunction &MF,
unsigned CandSize);
552 void initializeOutlinerMode(
const Module &M);
555 void emitOutlinedHashTree(
Module &M);
558 bool runOnModule(
Module &M)
override;
562 bool doOutline(
Module &M,
unsigned &OutlinedFunctionNum);
567 for (
const Candidate &
C :
OF.Candidates)
568 if (MachineFunction *MF =
C.getMF())
569 if (DISubprogram *SP = MF->getFunction().getSubprogram())
576 void populateMapper(InstructionMapper &Mapper,
Module &M);
582 void initSizeRemarkInfo(
const Module &M,
583 StringMap<unsigned> &FunctionToInstrCount);
588 emitInstrCountChangedRemark(
const Module &M,
589 const StringMap<unsigned> &FunctionToInstrCount);
593char MachineOutliner::ID = 0;
596 MachineOutliner *OL =
new MachineOutliner();
597 OL->RunOutlinerMode = RunOutlinerMode;
604void MachineOutliner::emitNotOutliningCheaperRemark(
605 unsigned StringLen,
std::vector<
Candidate> &CandidatesForRepeatedSeq,
611 Candidate &
C = CandidatesForRepeatedSeq.front();
615 C.front().getDebugLoc(),
C.getMBB());
616 R <<
"Did not outline " <<
NV(
"Length", StringLen) <<
" instructions"
617 <<
" from " <<
NV(
"NumOccurrences", CandidatesForRepeatedSeq.size())
619 <<
" Bytes from outlining all occurrences ("
620 <<
NV(
"OutliningCost", OF.getOutliningCost()) <<
")"
621 <<
" >= Unoutlined instruction bytes ("
622 <<
NV(
"NotOutliningCost", OF.getNotOutlinedCost()) <<
")"
623 <<
" (Also found at: ";
626 for (
unsigned i = 1, e = CandidatesForRepeatedSeq.size(); i < e; i++) {
628 CandidatesForRepeatedSeq[i].front().
getDebugLoc());
639 MachineBasicBlock *
MBB = &*
OF.MF->begin();
640 MachineOptimizationRemarkEmitter
MORE(*
OF.MF,
nullptr);
641 MachineOptimizationRemark
R(
DEBUG_TYPE,
"OutlinedFunction",
643 R <<
"Saved " <<
NV(
"OutliningBenefit",
OF.getBenefit()) <<
" bytes by "
644 <<
"outlining " <<
NV(
"Length",
OF.getNumInstrs()) <<
" instructions "
645 <<
"from " <<
NV(
"NumOccurrences",
OF.getOccurrenceCount())
650 for (
size_t i = 0, e =
OF.Candidates.size(); i < e; i++) {
652 R <<
NV((Twine(
"StartLoc") + Twine(i)).str(),
653 OF.Candidates[i].front().getDebugLoc());
676 auto &InstrList = Mapper.InstrList;
677 auto &UnsignedVec = Mapper.UnsignedVec;
686 auto getValidInstr = [&](
unsigned Index) ->
const MachineInstr * {
687 if (UnsignedVec[Index] >= Mapper.LegalInstrNumber)
689 return &(*InstrList[Index]);
692 auto getStableHashAndFollow =
697 auto It = CurrNode->Successors.find(StableHash);
698 return (It == CurrNode->Successors.end()) ? nullptr : It->second.get();
701 for (
unsigned I = 0;
I <
Size; ++
I) {
703 if (!
MI ||
MI->isDebugInstr())
705 const HashNode *CurrNode = getStableHashAndFollow(*
MI, RootNode);
709 for (
unsigned J =
I + 1; J <
Size; ++J) {
716 CurrNode = getStableHashAndFollow(*MJ, CurrNode);
726 return MatchedEntries;
729void MachineOutliner::findGlobalCandidates(
730 InstructionMapper &Mapper,
731 std::vector<std::unique_ptr<OutlinedFunction>> &FunctionList) {
732 FunctionList.
clear();
734 auto &MBBFlagsMap = Mapper.MBBFlagsMap;
736 std::vector<Candidate> CandidatesForRepeatedSeq;
738 CandidatesForRepeatedSeq.clear();
741 auto Length = ME.EndIdx - ME.StartIdx + 1;
742 MachineBasicBlock *
MBB = StartIt->getParent();
743 CandidatesForRepeatedSeq.emplace_back(ME.StartIdx,
Length, StartIt, EndIt,
746 const TargetInstrInfo *
TII =
748 unsigned MinRepeats = 1;
749 std::optional<std::unique_ptr<OutlinedFunction>>
OF =
750 TII->getOutliningCandidateInfo(*MMI, CandidatesForRepeatedSeq,
752 if (!
OF.has_value() ||
OF.value()->Candidates.empty())
755 assert(
OF.value()->Candidates.size() == MinRepeats);
756 FunctionList.emplace_back(std::make_unique<GlobalOutlinedFunction>(
757 std::move(
OF.value()), ME.Count));
761void MachineOutliner::findCandidates(
762 InstructionMapper &Mapper,
763 std::vector<std::unique_ptr<OutlinedFunction>> &FunctionList) {
764 FunctionList.clear();
769 std::vector<Candidate> CandidatesForRepeatedSeq;
770 LLVM_DEBUG(
dbgs() <<
"*** Discarding overlapping candidates *** \n");
772 dbgs() <<
"Searching for overlaps in all repeated sequences...\n");
773 for (SuffixTree::RepeatedSubstring &RS : ST) {
774 CandidatesForRepeatedSeq.clear();
775 unsigned StringLen =
RS.Length;
779 unsigned NumDiscarded = 0;
780 unsigned NumKept = 0;
785 for (
const unsigned &StartIdx :
RS.StartIndices) {
807 unsigned EndIdx = StartIdx + StringLen - 1;
808 if (!CandidatesForRepeatedSeq.empty() &&
809 StartIdx <= CandidatesForRepeatedSeq.back().getEndIdx()) {
812 LLVM_DEBUG(
dbgs() <<
" .. DISCARD candidate @ [" << StartIdx <<
", "
813 << EndIdx <<
"]; overlaps with candidate @ ["
814 << CandidatesForRepeatedSeq.back().getStartIdx()
815 <<
", " << CandidatesForRepeatedSeq.back().getEndIdx()
828 MachineBasicBlock *
MBB = StartIt->getParent();
829 CandidatesForRepeatedSeq.emplace_back(StartIdx, StringLen, StartIt, EndIt,
831 Mapper.MBBFlagsMap[
MBB]);
838 unsigned MinRepeats = 2;
843 if (CandidatesForRepeatedSeq.size() < MinRepeats)
848 const TargetInstrInfo *
TII =
849 CandidatesForRepeatedSeq[0].getMF()->getSubtarget().getInstrInfo();
851 std::optional<std::unique_ptr<OutlinedFunction>>
OF =
852 TII->getOutliningCandidateInfo(*MMI, CandidatesForRepeatedSeq,
857 if (!
OF.has_value() ||
OF.value()->Candidates.size() < MinRepeats)
862 emitNotOutliningCheaperRemark(StringLen, CandidatesForRepeatedSeq,
867 FunctionList.emplace_back(std::move(
OF.value()));
871void MachineOutliner::computeAndPublishHashSequence(MachineFunction &MF,
874 SmallVector<stable_hash> OutlinedHashSequence;
875 for (
auto &
MBB : MF) {
876 for (
auto &NewMI :
MBB) {
879 OutlinedHashSequence.
clear();
890 MF.getName().str() +
".content." + std::to_string(CombinedHash);
891 MF.getFunction().setName(NewName);
895 if (OutlinerMode == CGDataMode::Write) {
896 StableHashAttempts++;
897 if (!OutlinedHashSequence.
empty())
898 LocalHashTree->insert({OutlinedHashSequence, CandSize});
904MachineFunction *MachineOutliner::createOutlinedFunction(
905 Module &M, OutlinedFunction &OF, InstructionMapper &Mapper,
unsigned Name) {
910 std::string FunctionName =
"OUTLINED_FUNCTION_";
911 if (OutlineRepeatedNum > 0)
912 FunctionName += std::to_string(OutlineRepeatedNum + 1) +
"_";
913 FunctionName += std::to_string(Name);
917 LLVMContext &
C =
M.getContext();
919 Function::ExternalLinkage, FunctionName, M);
924 F->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
928 F->addFnAttr(Attribute::OptimizeForSize);
929 F->addFnAttr(Attribute::MinSize);
931 Candidate &FirstCand =
OF.Candidates.front();
932 const TargetInstrInfo &
TII =
935 TII.mergeOutliningCandidateAttributes(*
F,
OF.Candidates);
939 OF.Candidates.cbegin(),
OF.Candidates.cend(), UWTableKind::None,
941 return std::max(K, C.getMF()->getFunction().getUWTableKind());
943 F->setUWTableKind(UW);
947 Builder.CreateRetVoid();
949 MachineModuleInfo &MMI = getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
957 MachineFunction *OriginalMF = FirstCand.
front().
getMF();
958 const std::vector<MCCFIInstruction> &Instrs =
960 for (
auto &
MI : FirstCand) {
961 if (
MI.isDebugInstr())
966 if (
MI.isCFIInstruction()) {
967 unsigned CFIIndex =
MI.getOperand(0).getCFIIndex();
968 MCCFIInstruction CFI = Instrs[CFIIndex];
978 for (
auto I = std::next(NewMI.
getIterator());
I != BundleEnd; ++
I)
984 if (OutlinerMode != CGDataMode::None)
985 computeAndPublishHashSequence(MF,
OF.Candidates.size());
996 const TargetRegisterInfo &
TRI = *
MRI.getTargetRegisterInfo();
997 LivePhysRegs LiveIns(
TRI);
998 for (
auto &Cand :
OF.Candidates) {
1000 MachineBasicBlock &OutlineBB = *Cand.front().getParent();
1001 LivePhysRegs CandLiveIns(
TRI);
1002 CandLiveIns.addLiveOuts(OutlineBB);
1003 for (
const MachineInstr &
MI :
1005 CandLiveIns.stepBackward(
MI);
1010 LiveIns.addReg(
Reg);
1014 TII.buildOutlinedFrame(
MBB, MF, OF);
1020 DICompileUnit *CU =
SP->getUnit();
1021 DIBuilder
DB(M,
true, CU);
1022 DIFile *
Unit =
SP->getFile();
1026 raw_string_ostream MangledNameStream(Dummy);
1029 DISubprogram *OutlinedSP =
DB.createFunction(
1030 Unit ,
F->getName(), StringRef(Dummy), Unit ,
1032 DB.createSubroutineType(
DB.getOrCreateTypeArray({})),
1034 DINode::DIFlags::FlagArtificial ,
1036 DISubprogram::SPFlagDefinition | DISubprogram::SPFlagOptimized);
1039 F->setSubprogram(OutlinedSP);
1047bool MachineOutliner::outline(
1048 Module &M, std::vector<std::unique_ptr<OutlinedFunction>> &FunctionList,
1049 InstructionMapper &Mapper,
unsigned &OutlinedFunctionNum) {
1051 LLVM_DEBUG(
dbgs() <<
"NUMBER OF POTENTIAL FUNCTIONS: " << FunctionList.size()
1053 bool OutlinedSomething =
false;
1057 stable_sort(FunctionList, [](
const std::unique_ptr<OutlinedFunction> &
LHS,
1058 const std::unique_ptr<OutlinedFunction> &
RHS) {
1059 return LHS->getNotOutlinedCost() *
RHS->getOutliningCost() >
1060 RHS->getNotOutlinedCost() *
LHS->getOutliningCost();
1065 auto *UnsignedVecBegin = Mapper.UnsignedVec.
begin();
1067 for (
auto &OF : FunctionList) {
1069 auto NumCandidatesBefore =
OF->Candidates.size();
1073 erase_if(
OF->Candidates, [&UnsignedVecBegin](Candidate &
C) {
1074 return std::any_of(UnsignedVecBegin + C.getStartIdx(),
1075 UnsignedVecBegin + C.getEndIdx() + 1, [](unsigned I) {
1076 return I == static_cast<unsigned>(-1);
1081 auto NumCandidatesAfter =
OF->Candidates.size();
1082 LLVM_DEBUG(
dbgs() <<
"PRUNED: " << NumCandidatesBefore - NumCandidatesAfter
1083 <<
"/" << NumCandidatesBefore <<
" candidates\n");
1101 SmallPtrSet<MachineInstr *, 2> MIs;
1102 for (Candidate &
C :
OF->Candidates) {
1103 for (MachineInstr &
MI :
C)
1112 emitOutlinedFunctionRemark(*OF);
1114 OutlinedFunctionNum++;
1115 MachineFunction *MF =
OF->MF;
1121 for (Candidate &
C :
OF->Candidates) {
1122 MachineBasicBlock &
MBB = *
C.getMBB();
1127 auto CallInst =
TII.insertOutlinedCall(M,
MBB, StartIt, *MF,
C);
1130 auto MBBBeingOutlinedFromName =
1136 << MFBeingOutlinedFromName <<
":"
1137 << MBBBeingOutlinedFromName <<
"\n");
1149 SmallSet<Register, 2> UseRegs, DefRegs;
1158 Last = std::next(CallInst.getReverse());
1159 Iter !=
Last; Iter++) {
1160 MachineInstr *
MI = &*Iter;
1161 SmallSet<Register, 2> InstrUseRegs;
1162 for (MachineOperand &MOP :
MI->operands()) {
1169 DefRegs.
insert(MOP.getReg());
1170 if (UseRegs.
count(MOP.getReg()) &&
1171 !InstrUseRegs.
count(MOP.getReg()))
1174 UseRegs.
erase(MOP.getReg());
1175 }
else if (!MOP.isUndef()) {
1178 UseRegs.
insert(MOP.getReg());
1179 InstrUseRegs.
insert(MOP.getReg());
1182 if (
MI->isCandidateForAdditionalCallInfo())
1183 MI->getMF()->eraseAdditionalCallInfo(
MI);
1188 CallInst->addOperand(
1194 CallInst->addOperand(
1202 MBB.
erase(std::next(StartIt), std::next(EndIt));
1205 for (
unsigned &
I :
make_range(UnsignedVecBegin +
C.getStartIdx(),
1206 UnsignedVecBegin +
C.getEndIdx() + 1))
1207 I =
static_cast<unsigned>(-1);
1208 OutlinedSomething =
true;
1215 LLVM_DEBUG(
dbgs() <<
"OutlinedSomething = " << OutlinedSomething <<
"\n");
1216 return OutlinedSomething;
1226 auto *MF =
MBB.getParent();
1228 ++NumPGOAllowedCold;
1232 auto *BB =
MBB.getBasicBlock();
1233 if (BB && PSI && BFI)
1239 if (
TII->shouldOutlineFromFunctionByDefault(*MF)) {
1241 ++NumPGOOptimisticOutlined;
1248 ++NumPGOConservativeBlockedOutlined;
1252void MachineOutliner::populateMapper(InstructionMapper &Mapper,
Module &M) {
1256 bool EnableProfileGuidedOutlining =
1257 RunOutlinerMode == RunOutliner::OptimisticPGO ||
1258 RunOutlinerMode == RunOutliner::ConservativePGO;
1259 ProfileSummaryInfo *PSI =
nullptr;
1260 if (EnableProfileGuidedOutlining)
1261 PSI = &getAnalysis<ProfileSummaryInfoWrapperPass>().getPSI();
1262 for (Function &
F : M) {
1265 if (
F.hasFnAttribute(Attribute::NoOutline)) {
1266 LLVM_DEBUG(
dbgs() <<
"SKIP: Function has nooutline attribute\n");
1277 LLVM_DEBUG(
dbgs() <<
"SKIP: Function does not have a MachineFunction\n");
1282 BlockFrequencyInfo *BFI =
nullptr;
1283 if (EnableProfileGuidedOutlining &&
F.hasProfileData())
1284 BFI = &getAnalysis<BlockFrequencyInfoWrapperPass>(
F).getBFI();
1285 if (RunOutlinerMode == RunOutliner::TargetDefault &&
1286 !
TII->shouldOutlineFromFunctionByDefault(*MF)) {
1287 LLVM_DEBUG(
dbgs() <<
"SKIP: Target does not want to outline from "
1288 "function by default\n");
1294 if (!
TII->isFunctionSafeToOutlineFrom(*MF, OutlineFromLinkOnceODRs)) {
1296 <<
": unsafe to outline from\n");
1303 const unsigned MinMBBSize = 2;
1305 for (MachineBasicBlock &
MBB : *MF) {
1313 if (
MBB.
size() < MinMBBSize) {
1314 LLVM_DEBUG(
dbgs() <<
" SKIP: MBB size less than minimum size of "
1315 << MinMBBSize <<
"\n");
1327 ++NumPGOBlockedOutlined;
1332 Mapper.convertToUnsignedVec(
MBB, *
TII);
1336 UnsignedVecSize = Mapper.UnsignedVec.
size();
1339void MachineOutliner::initSizeRemarkInfo(
1340 const Module &M, StringMap<unsigned> &FunctionToInstrCount) {
1343 for (
const Function &
F : M) {
1354void MachineOutliner::emitInstrCountChangedRemark(
1355 const Module &M,
const StringMap<unsigned> &FunctionToInstrCount) {
1359 for (
const Function &
F : M) {
1367 std::string Fname = std::string(
F.getName());
1369 unsigned FnCountBefore = 0;
1372 auto It = FunctionToInstrCount.
find(Fname);
1376 if (It != FunctionToInstrCount.
end())
1377 FnCountBefore = It->second;
1380 int64_t FnDelta =
static_cast<int64_t
>(FnCountAfter) -
1381 static_cast<int64_t
>(FnCountBefore);
1385 MachineOptimizationRemarkEmitter
MORE(*MF,
nullptr);
1387 MachineOptimizationRemarkAnalysis
R(
"size-info",
"FunctionMISizeChange",
1388 DiagnosticLocation(), &MF->
front());
1389 R << DiagnosticInfoOptimizationBase::Argument(
"Pass",
"Machine Outliner")
1391 << DiagnosticInfoOptimizationBase::Argument(
"Function",
F.getName())
1392 <<
": MI instruction count changed from "
1393 << DiagnosticInfoOptimizationBase::Argument(
"MIInstrsBefore",
1396 << DiagnosticInfoOptimizationBase::Argument(
"MIInstrsAfter",
1399 << DiagnosticInfoOptimizationBase::Argument(
"Delta", FnDelta);
1405void MachineOutliner::initializeOutlinerMode(
const Module &M) {
1409 if (
auto *IndexWrapperPass =
1410 getAnalysisIfAvailable<ImmutableModuleSummaryIndexWrapperPass>()) {
1411 auto *TheIndex = IndexWrapperPass->getIndex();
1414 if (TheIndex && !TheIndex->hasExportedFunctions(M))
1423 OutlinerMode = CGDataMode::Write;
1425 LocalHashTree = std::make_unique<OutlinedHashTree>();
1428 OutlinerMode = CGDataMode::Read;
1431void MachineOutliner::emitOutlinedHashTree(
Module &M) {
1433 if (!LocalHashTree->empty()) {
1435 dbgs() <<
"Emit outlined hash tree. Size: " << LocalHashTree->size()
1438 SmallVector<char> Buf;
1439 raw_svector_ostream OS(Buf);
1441 OutlinedHashTreeRecord HTR(std::move(LocalHashTree));
1444 llvm::StringRef
Data(Buf.data(), Buf.size());
1445 std::unique_ptr<MemoryBuffer> Buffer =
1448 Triple
TT(
M.getTargetTriple());
1455bool MachineOutliner::runOnModule(
Module &M) {
1465 initializeOutlinerMode(M);
1467 MMI = &getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
1468 TM = &getAnalysis<TargetPassConfig>().getTM<TargetMachine>();
1471 unsigned OutlinedFunctionNum = 0;
1473 OutlineRepeatedNum = 0;
1474 if (!doOutline(M, OutlinedFunctionNum))
1478 OutlinedFunctionNum = 0;
1479 OutlineRepeatedNum++;
1480 if (!doOutline(M, OutlinedFunctionNum)) {
1482 dbgs() <<
"Did not outline on iteration " <<
I + 2 <<
" out of "
1489 if (OutlinerMode == CGDataMode::Write)
1490 emitOutlinedHashTree(M);
1495bool MachineOutliner::doOutline(
Module &M,
unsigned &OutlinedFunctionNum) {
1502 dbgs() <<
"Machine Outliner: Running on ";
1503 switch (RunOutlinerMode) {
1504 case RunOutliner::AlwaysOutline:
1505 dbgs() <<
"all functions";
1507 case RunOutliner::OptimisticPGO:
1508 dbgs() <<
"optimistically cold functions";
1510 case RunOutliner::ConservativePGO:
1511 dbgs() <<
"conservatively cold functions";
1513 case RunOutliner::TargetDefault:
1514 dbgs() <<
"target-default functions";
1516 case RunOutliner::NeverOutline:
1525 InstructionMapper Mapper(*MMI);
1528 populateMapper(Mapper, M);
1529 std::vector<std::unique_ptr<OutlinedFunction>> FunctionList;
1532 if (OutlinerMode == CGDataMode::Read)
1533 findGlobalCandidates(Mapper, FunctionList);
1535 findCandidates(Mapper, FunctionList);
1546 bool ShouldEmitSizeRemarks =
M.shouldEmitInstrCountChangedRemark();
1547 StringMap<unsigned> FunctionToInstrCount;
1548 if (ShouldEmitSizeRemarks)
1549 initSizeRemarkInfo(M, FunctionToInstrCount);
1552 bool OutlinedSomething =
1553 outline(M, FunctionList, Mapper, OutlinedFunctionNum);
1558 if (ShouldEmitSizeRemarks && OutlinedSomething)
1559 emitInstrCountChangedRemark(M, FunctionToInstrCount);
1562 if (!OutlinedSomething)
1563 dbgs() <<
"Stopped outlining at iteration " << OutlineRepeatedNum
1564 <<
" because no changes were found.\n";
1567 return OutlinedSomething;
unsigned const MachineRegisterInfo * MRI
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 ...
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
str - Get the contents as an std::string.
constexpr bool empty() const
empty - Check if the string is empty.
constexpr size_t size() const
size - 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.
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.