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 "Non-debug 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 ++NumLegalInUnsignedVec;
258 unsigned mapToIllegalUnsigned(
260 SmallVector<unsigned> &UnsignedVecForMBB,
263 CanOutlineWithPrevInstr =
false;
266 if (AddedIllegalLastTime)
267 return IllegalInstrNumber;
270 AddedIllegalLastTime =
true;
271 unsigned MINumber = IllegalInstrNumber;
274 UnsignedVecForMBB.
push_back(IllegalInstrNumber);
275 IllegalInstrNumber--;
277 ++NumIllegalInUnsignedVec;
279 assert(LegalInstrNumber < IllegalInstrNumber &&
280 "Instruction mapping overflow!");
295 void convertToUnsignedVec(MachineBasicBlock &
MBB,
296 const TargetInstrInfo &
TII) {
298 <<
"' to unsigned vector ***\n");
302 if (!
TII.isMBBSafeToOutlineFrom(
MBB, Flags))
305 auto OutlinableRanges =
TII.getOutlinableRanges(
MBB, Flags);
307 <<
" outlinable range(s)\n");
308 if (OutlinableRanges.empty())
318 unsigned NumLegalInBlock = 0;
322 bool HaveLegalRange =
false;
326 bool CanOutlineWithPrevInstr =
false;
330 SmallVector<unsigned> UnsignedVecForMBB;
334 for (
auto &OutlinableRange : OutlinableRanges) {
335 auto OutlinableRangeBegin = OutlinableRange.first;
336 auto OutlinableRangeEnd = OutlinableRange.second;
340 << std::distance(OutlinableRangeBegin, OutlinableRangeEnd)
341 <<
" instruction range\n");
343 unsigned NumSkippedInRange = 0;
345 for (; It != OutlinableRangeBegin; ++It) {
346 if (It->isDebugInstr())
351 mapToIllegalUnsigned(It, CanOutlineWithPrevInstr, UnsignedVecForMBB,
356 <<
" instructions outside outlinable range\n");
358 assert(It !=
MBB.
end() &&
"Should still have instructions?");
361 for (; It != OutlinableRangeEnd; ++It) {
362 if (It->isDebugInstr())
365 switch (
TII.getOutliningType(MMI, It, Flags)) {
366 case InstrType::Illegal:
367 mapToIllegalUnsigned(It, CanOutlineWithPrevInstr, UnsignedVecForMBB,
371 case InstrType::Legal:
372 mapToLegalUnsigned(It, CanOutlineWithPrevInstr, HaveLegalRange,
373 NumLegalInBlock, UnsignedVecForMBB,
377 case InstrType::LegalTerminator:
378 mapToLegalUnsigned(It, CanOutlineWithPrevInstr, HaveLegalRange,
379 NumLegalInBlock, UnsignedVecForMBB,
383 mapToIllegalUnsigned(It, CanOutlineWithPrevInstr, UnsignedVecForMBB,
387 case InstrType::Invisible:
391 AddedIllegalLastTime =
false;
397 LLVM_DEBUG(
dbgs() <<
"HaveLegalRange = " << HaveLegalRange <<
"\n");
401 if (HaveLegalRange) {
406 mapToIllegalUnsigned(It, CanOutlineWithPrevInstr, UnsignedVecForMBB,
414 InstructionMapper(
const MachineModuleInfo &MMI_) : MMI(MMI_) {}
430 MachineModuleInfo *MMI =
nullptr;
431 const TargetMachine *TM =
nullptr;
435 bool OutlineFromLinkOnceODRs =
false;
438 unsigned OutlineRepeatedNum = 0;
443 RunOutliner RunOutlinerMode = RunOutliner::AlwaysOutline;
451 std::unique_ptr<OutlinedHashTree> LocalHashTree;
462 StringRef getPassName()
const override {
return "Machine Outliner"; }
464 void getAnalysisUsage(AnalysisUsage &AU)
const override {
469 if (RunOutlinerMode == RunOutliner::OptimisticPGO ||
470 RunOutlinerMode == RunOutliner::ConservativePGO) {
475 ModulePass::getAnalysisUsage(AU);
478 MachineOutliner() : ModulePass(ID) {}
482 void emitNotOutliningCheaperRemark(
483 unsigned StringLen, std::vector<Candidate> &CandidatesForRepeatedSeq,
484 OutlinedFunction &OF);
487 void emitOutlinedFunctionRemark(OutlinedFunction &OF);
503 findCandidates(InstructionMapper &Mapper,
504 std::vector<std::unique_ptr<OutlinedFunction>> &FunctionList);
512 void findGlobalCandidates(
513 InstructionMapper &Mapper,
514 std::vector<std::unique_ptr<OutlinedFunction>> &FunctionList);
524 std::vector<std::unique_ptr<OutlinedFunction>> &FunctionList,
525 InstructionMapper &Mapper,
unsigned &OutlinedFunctionNum);
529 InstructionMapper &Mapper,
535 void computeAndPublishHashSequence(
MachineFunction &MF,
unsigned CandSize);
538 void initializeOutlinerMode(
const Module &M);
541 void emitOutlinedHashTree(
Module &M);
544 bool runOnModule(
Module &M)
override;
548 bool doOutline(
Module &M,
unsigned &OutlinedFunctionNum);
552 DISubprogram *getSubprogramOrNull(
const OutlinedFunction &OF) {
553 for (
const Candidate &
C :
OF.Candidates)
555 if (DISubprogram *SP = MF->getFunction().getSubprogram())
562 void populateMapper(InstructionMapper &Mapper,
Module &M);
568 void initSizeRemarkInfo(
const Module &M,
569 StringMap<unsigned> &FunctionToInstrCount);
574 emitInstrCountChangedRemark(
const Module &M,
575 const StringMap<unsigned> &FunctionToInstrCount);
579char MachineOutliner::ID = 0;
582 MachineOutliner *OL =
new MachineOutliner();
583 OL->RunOutlinerMode = RunOutlinerMode;
590void MachineOutliner::emitNotOutliningCheaperRemark(
591 unsigned StringLen,
std::vector<
Candidate> &CandidatesForRepeatedSeq,
597 Candidate &
C = CandidatesForRepeatedSeq.front();
601 C.front().getDebugLoc(),
C.getMBB());
602 R <<
"Did not outline " <<
NV(
"Length", StringLen) <<
" instructions"
603 <<
" from " <<
NV(
"NumOccurrences", CandidatesForRepeatedSeq.size())
605 <<
" Bytes from outlining all occurrences ("
606 <<
NV(
"OutliningCost", OF.getOutliningCost()) <<
")"
607 <<
" >= Unoutlined instruction bytes ("
608 <<
NV(
"NotOutliningCost", OF.getNotOutlinedCost()) <<
")"
609 <<
" (Also found at: ";
612 for (
unsigned i = 1, e = CandidatesForRepeatedSeq.size(); i < e; i++) {
614 CandidatesForRepeatedSeq[i].front().
getDebugLoc());
625 MachineBasicBlock *
MBB = &*
OF.MF->begin();
626 MachineOptimizationRemarkEmitter
MORE(*
OF.MF,
nullptr);
627 MachineOptimizationRemark
R(
DEBUG_TYPE,
"OutlinedFunction",
629 R <<
"Saved " <<
NV(
"OutliningBenefit",
OF.getBenefit()) <<
" bytes by "
630 <<
"outlining " <<
NV(
"Length",
OF.getNumInstrs()) <<
" instructions "
631 <<
"from " <<
NV(
"NumOccurrences",
OF.getOccurrenceCount())
636 for (
size_t i = 0, e =
OF.Candidates.size(); i < e; i++) {
638 R <<
NV((Twine(
"StartLoc") + Twine(i)).str(),
639 OF.Candidates[i].front().getDebugLoc());
662 auto &InstrList = Mapper.InstrList;
663 auto &UnsignedVec = Mapper.UnsignedVec;
672 auto getValidInstr = [&](
unsigned Index) ->
const MachineInstr * {
673 if (UnsignedVec[Index] >= Mapper.LegalInstrNumber)
675 return &(*InstrList[Index]);
678 auto getStableHashAndFollow =
683 auto It = CurrNode->Successors.find(StableHash);
684 return (It == CurrNode->Successors.end()) ? nullptr : It->second.get();
687 for (
unsigned I = 0;
I <
Size; ++
I) {
689 if (!
MI ||
MI->isDebugInstr())
691 const HashNode *CurrNode = getStableHashAndFollow(*
MI, RootNode);
695 for (
unsigned J =
I + 1; J <
Size; ++J) {
702 CurrNode = getStableHashAndFollow(*MJ, CurrNode);
712 return MatchedEntries;
715void MachineOutliner::findGlobalCandidates(
716 InstructionMapper &Mapper,
717 std::vector<std::unique_ptr<OutlinedFunction>> &FunctionList) {
718 FunctionList.
clear();
720 auto &MBBFlagsMap =
Mapper.MBBFlagsMap;
722 std::vector<Candidate> CandidatesForRepeatedSeq;
724 CandidatesForRepeatedSeq.clear();
727 auto Length = ME.EndIdx - ME.StartIdx + 1;
728 MachineBasicBlock *
MBB = StartIt->getParent();
729 CandidatesForRepeatedSeq.emplace_back(ME.StartIdx,
Length, StartIt, EndIt,
732 const TargetInstrInfo *
TII =
734 unsigned MinRepeats = 1;
735 std::optional<std::unique_ptr<OutlinedFunction>>
OF =
736 TII->getOutliningCandidateInfo(*MMI, CandidatesForRepeatedSeq,
738 if (!
OF.has_value() ||
OF.value()->Candidates.empty())
741 assert(
OF.value()->Candidates.size() == MinRepeats);
742 FunctionList.emplace_back(std::make_unique<GlobalOutlinedFunction>(
743 std::move(
OF.value()), ME.Count));
747void MachineOutliner::findCandidates(
748 InstructionMapper &Mapper,
749 std::vector<std::unique_ptr<OutlinedFunction>> &FunctionList) {
750 FunctionList.clear();
755 std::vector<Candidate> CandidatesForRepeatedSeq;
756 LLVM_DEBUG(
dbgs() <<
"*** Discarding overlapping candidates *** \n");
758 dbgs() <<
"Searching for overlaps in all repeated sequences...\n");
759 for (SuffixTree::RepeatedSubstring &RS : ST) {
760 CandidatesForRepeatedSeq.clear();
761 unsigned StringLen =
RS.Length;
765 unsigned NumDiscarded = 0;
766 unsigned NumKept = 0;
771 for (
const unsigned &StartIdx :
RS.StartIndices) {
793 unsigned EndIdx = StartIdx + StringLen - 1;
794 if (!CandidatesForRepeatedSeq.empty() &&
795 StartIdx <= CandidatesForRepeatedSeq.back().getEndIdx()) {
798 LLVM_DEBUG(
dbgs() <<
" .. DISCARD candidate @ [" << StartIdx <<
", "
799 << EndIdx <<
"]; overlaps with candidate @ ["
800 << CandidatesForRepeatedSeq.back().getStartIdx()
801 <<
", " << CandidatesForRepeatedSeq.back().getEndIdx()
814 MachineBasicBlock *
MBB = StartIt->getParent();
815 CandidatesForRepeatedSeq.emplace_back(StartIdx, StringLen, StartIt, EndIt,
824 unsigned MinRepeats = 2;
829 if (CandidatesForRepeatedSeq.size() < MinRepeats)
834 const TargetInstrInfo *
TII =
835 CandidatesForRepeatedSeq[0].getMF()->getSubtarget().getInstrInfo();
837 std::optional<std::unique_ptr<OutlinedFunction>>
OF =
838 TII->getOutliningCandidateInfo(*MMI, CandidatesForRepeatedSeq,
843 if (!
OF.has_value() ||
OF.value()->Candidates.size() < MinRepeats)
848 emitNotOutliningCheaperRemark(StringLen, CandidatesForRepeatedSeq,
853 FunctionList.emplace_back(std::move(
OF.value()));
857void MachineOutliner::computeAndPublishHashSequence(
MachineFunction &MF,
860 SmallVector<stable_hash> OutlinedHashSequence;
861 for (
auto &
MBB : MF) {
862 for (
auto &NewMI :
MBB) {
865 OutlinedHashSequence.
clear();
876 MF.getName().str() +
".content." + std::to_string(CombinedHash);
877 MF.getFunction().setName(NewName);
881 if (OutlinerMode == CGDataMode::Write) {
882 StableHashAttempts++;
883 if (!OutlinedHashSequence.
empty())
884 LocalHashTree->insert({OutlinedHashSequence, CandSize});
891 Module &M, OutlinedFunction &OF, InstructionMapper &Mapper,
unsigned Name) {
896 std::string FunctionName =
"OUTLINED_FUNCTION_";
897 if (OutlineRepeatedNum > 0)
898 FunctionName += std::to_string(OutlineRepeatedNum + 1) +
"_";
899 FunctionName += std::to_string(Name);
903 LLVMContext &
C =
M.getContext();
905 Function::ExternalLinkage, FunctionName, M);
910 F->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
914 F->addFnAttr(Attribute::OptimizeForSize);
915 F->addFnAttr(Attribute::MinSize);
917 Candidate &FirstCand =
OF.Candidates.front();
918 const TargetInstrInfo &
TII =
921 TII.mergeOutliningCandidateAttributes(*
F,
OF.Candidates);
925 OF.Candidates.cbegin(),
OF.Candidates.cend(), UWTableKind::None,
927 return std::max(K, C.getMF()->getFunction().getUWTableKind());
929 F->setUWTableKind(UW);
933 Builder.CreateRetVoid();
935 MachineModuleInfo &MMI = getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
944 const std::vector<MCCFIInstruction> &Instrs =
946 for (
auto &
MI : FirstCand) {
947 if (
MI.isDebugInstr())
952 if (
MI.isCFIInstruction()) {
953 unsigned CFIIndex =
MI.getOperand(0).getCFIIndex();
954 MCCFIInstruction CFI = Instrs[CFIIndex];
965 for (
auto I = std::next(NewMI.
getIterator());
I != BundleEnd; ++
I) {
973 if (OutlinerMode != CGDataMode::None)
974 computeAndPublishHashSequence(MF,
OF.Candidates.size());
984 const MachineRegisterInfo &MRI = MF.
getRegInfo();
986 LivePhysRegs LiveIns(
TRI);
987 for (
auto &Cand :
OF.Candidates) {
989 MachineBasicBlock &OutlineBB = *Cand.front().getParent();
990 LivePhysRegs CandLiveIns(
TRI);
991 CandLiveIns.addLiveOuts(OutlineBB);
992 for (
const MachineInstr &
MI :
994 CandLiveIns.stepBackward(
MI);
1003 TII.buildOutlinedFrame(
MBB, MF, OF);
1007 if (DISubprogram *SP = getSubprogramOrNull(OF)) {
1009 DICompileUnit *CU =
SP->getUnit();
1010 DIBuilder
DB(M,
true, CU);
1011 DIFile *
Unit =
SP->getFile();
1015 raw_string_ostream MangledNameStream(Dummy);
1018 DISubprogram *OutlinedSP =
DB.createFunction(
1019 Unit ,
F->getName(), StringRef(Dummy), Unit ,
1021 DB.createSubroutineType(
DB.getOrCreateTypeArray({})),
1023 DINode::DIFlags::FlagArtificial ,
1025 DISubprogram::SPFlagDefinition | DISubprogram::SPFlagOptimized);
1028 F->setSubprogram(OutlinedSP);
1036bool MachineOutliner::outline(
1037 Module &M, std::vector<std::unique_ptr<OutlinedFunction>> &FunctionList,
1038 InstructionMapper &Mapper,
unsigned &OutlinedFunctionNum) {
1040 LLVM_DEBUG(
dbgs() <<
"NUMBER OF POTENTIAL FUNCTIONS: " << FunctionList.size()
1042 bool OutlinedSomething =
false;
1046 stable_sort(FunctionList, [](
const std::unique_ptr<OutlinedFunction> &
LHS,
1047 const std::unique_ptr<OutlinedFunction> &
RHS) {
1048 return LHS->getNotOutlinedCost() *
RHS->getOutliningCost() >
1049 RHS->getNotOutlinedCost() *
LHS->getOutliningCost();
1054 auto *UnsignedVecBegin =
Mapper.UnsignedVec.begin();
1056 for (
auto &OF : FunctionList) {
1058 auto NumCandidatesBefore =
OF->Candidates.size();
1062 erase_if(
OF->Candidates, [&UnsignedVecBegin](Candidate &
C) {
1063 return std::any_of(UnsignedVecBegin + C.getStartIdx(),
1064 UnsignedVecBegin + C.getEndIdx() + 1, [](unsigned I) {
1065 return I == static_cast<unsigned>(-1);
1070 auto NumCandidatesAfter =
OF->Candidates.size();
1071 LLVM_DEBUG(
dbgs() <<
"PRUNED: " << NumCandidatesBefore - NumCandidatesAfter
1072 <<
"/" << NumCandidatesBefore <<
" candidates\n");
1090 SmallPtrSet<MachineInstr *, 2> MIs;
1091 for (Candidate &
C :
OF->Candidates) {
1092 for (MachineInstr &
MI :
C)
1101 emitOutlinedFunctionRemark(*OF);
1103 OutlinedFunctionNum++;
1110 for (Candidate &
C :
OF->Candidates) {
1111 MachineBasicBlock &
MBB = *
C.getMBB();
1118 for (MachineInstr &
MI :
C) {
1119 if (
MI.isDebugInstr())
1122 bool HasLine =
DL &&
DL.getLine();
1123 if (!FirstLoc && HasLine)
1135 auto CallInst =
TII.insertOutlinedCall(M,
MBB, StartIt, *MF,
C);
1144 !CallInst->isTerminator() && LastCallLoc ? LastCallLoc : FirstLoc;
1153 for (MachineInstr &
MI :
make_range(SeqBegin, std::next(StartIt)))
1154 MI.setDebugLoc(CallLoc);
1157 auto MBBBeingOutlinedFromName =
1163 << MFBeingOutlinedFromName <<
":"
1164 << MBBBeingOutlinedFromName <<
"\n");
1176 SmallSet<Register, 2> UseRegs, DefRegs;
1185 Last = std::next(CallInst.getReverse());
1186 Iter !=
Last; Iter++) {
1187 MachineInstr *
MI = &*Iter;
1188 if (
MI->isDebugInstr())
1190 SmallSet<Register, 2> InstrUseRegs;
1191 for (MachineOperand &MOP :
MI->operands()) {
1198 DefRegs.
insert(MOP.getReg());
1199 if (UseRegs.
count(MOP.getReg()) &&
1200 !InstrUseRegs.
count(MOP.getReg()))
1203 UseRegs.
erase(MOP.getReg());
1204 }
else if (!MOP.isUndef()) {
1207 UseRegs.
insert(MOP.getReg());
1208 InstrUseRegs.
insert(MOP.getReg());
1211 if (
MI->isCandidateForAdditionalCallInfo())
1212 MI->getMF()->eraseAdditionalCallInfo(
MI);
1217 CallInst->addOperand(
1223 CallInst->addOperand(
1231 MBB.
erase(std::next(StartIt), std::next(EndIt));
1234 for (
unsigned &
I :
make_range(UnsignedVecBegin +
C.getStartIdx(),
1235 UnsignedVecBegin +
C.getEndIdx() + 1))
1236 I =
static_cast<unsigned>(-1);
1237 OutlinedSomething =
true;
1244 LLVM_DEBUG(
dbgs() <<
"OutlinedSomething = " << OutlinedSomething <<
"\n");
1245 return OutlinedSomething;
1255 auto *MF =
MBB.getParent();
1257 ++NumPGOAllowedCold;
1261 auto *BB =
MBB.getBasicBlock();
1262 if (BB && PSI && BFI)
1268 if (
TII->shouldOutlineFromFunctionByDefault(*MF)) {
1270 ++NumPGOOptimisticOutlined;
1277 ++NumPGOConservativeBlockedOutlined;
1281void MachineOutliner::populateMapper(InstructionMapper &Mapper,
Module &M) {
1285 bool EnableProfileGuidedOutlining =
1286 RunOutlinerMode == RunOutliner::OptimisticPGO ||
1287 RunOutlinerMode == RunOutliner::ConservativePGO;
1288 ProfileSummaryInfo *PSI =
nullptr;
1289 if (EnableProfileGuidedOutlining)
1290 PSI = &getAnalysis<ProfileSummaryInfoWrapperPass>().getPSI();
1294 if (
F.hasFnAttribute(Attribute::NoOutline)) {
1295 LLVM_DEBUG(
dbgs() <<
"SKIP: Function has nooutline attribute\n");
1306 LLVM_DEBUG(
dbgs() <<
"SKIP: Function does not have a MachineFunction\n");
1311 BlockFrequencyInfo *BFI =
nullptr;
1312 if (EnableProfileGuidedOutlining &&
F.hasProfileData())
1313 BFI = &getAnalysis<BlockFrequencyInfoWrapperPass>(
F).getBFI();
1314 if (RunOutlinerMode == RunOutliner::TargetDefault &&
1315 !
TII->shouldOutlineFromFunctionByDefault(*MF)) {
1316 LLVM_DEBUG(
dbgs() <<
"SKIP: Target does not want to outline from "
1317 "function by default\n");
1323 if (!
TII->isFunctionSafeToOutlineFrom(*MF, OutlineFromLinkOnceODRs)) {
1325 <<
": unsafe to outline from\n");
1332 const unsigned MinMBBSize = 2;
1334 for (MachineBasicBlock &
MBB : *MF) {
1349 LLVM_DEBUG(
dbgs() <<
" SKIP: MBB size less than minimum size of "
1350 << MinMBBSize <<
"\n");
1362 ++NumPGOBlockedOutlined;
1371 UnsignedVecSize =
Mapper.UnsignedVec.size();
1374void MachineOutliner::initSizeRemarkInfo(
1375 const Module &M, StringMap<unsigned> &FunctionToInstrCount) {
1389void MachineOutliner::emitInstrCountChangedRemark(
1390 const Module &M,
const StringMap<unsigned> &FunctionToInstrCount) {
1402 std::string Fname = std::string(
F.getName());
1404 unsigned FnCountBefore = 0;
1407 auto It = FunctionToInstrCount.
find(Fname);
1411 if (It != FunctionToInstrCount.
end())
1412 FnCountBefore = It->second;
1415 int64_t FnDelta =
static_cast<int64_t
>(FnCountAfter) -
1416 static_cast<int64_t
>(FnCountBefore);
1420 MachineOptimizationRemarkEmitter
MORE(*MF,
nullptr);
1422 MachineOptimizationRemarkAnalysis
R(
"size-info",
"FunctionMISizeChange",
1423 DiagnosticLocation(), &MF->
front());
1424 R << DiagnosticInfoOptimizationBase::Argument(
"Pass",
"Machine Outliner")
1426 << DiagnosticInfoOptimizationBase::Argument(
"Function",
F.getName())
1427 <<
": MI instruction count changed from "
1428 << DiagnosticInfoOptimizationBase::Argument(
"MIInstrsBefore",
1431 << DiagnosticInfoOptimizationBase::Argument(
"MIInstrsAfter",
1434 << DiagnosticInfoOptimizationBase::Argument(
"Delta", FnDelta);
1440void MachineOutliner::initializeOutlinerMode(
const Module &M) {
1444 if (
auto *IndexWrapperPass =
1445 getAnalysisIfAvailable<ImmutableModuleSummaryIndexWrapperPass>()) {
1446 auto *TheIndex = IndexWrapperPass->getIndex();
1449 if (TheIndex && !TheIndex->hasExportedFunctions(M))
1458 OutlinerMode = CGDataMode::Write;
1460 LocalHashTree = std::make_unique<OutlinedHashTree>();
1463 OutlinerMode = CGDataMode::Read;
1466void MachineOutliner::emitOutlinedHashTree(
Module &M) {
1468 if (!LocalHashTree->empty()) {
1470 dbgs() <<
"Emit outlined hash tree. Size: " << LocalHashTree->size()
1473 SmallVector<char> Buf;
1474 raw_svector_ostream OS(Buf);
1476 OutlinedHashTreeRecord HTR(std::move(LocalHashTree));
1479 llvm::StringRef
Data(Buf.data(), Buf.size());
1480 std::unique_ptr<MemoryBuffer> Buffer =
1483 Triple
TT(
M.getTargetTriple());
1490bool MachineOutliner::runOnModule(
Module &M) {
1500 initializeOutlinerMode(M);
1502 MMI = &getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
1503 TM = &getAnalysis<TargetPassConfig>().getTM<TargetMachine>();
1506 unsigned OutlinedFunctionNum = 0;
1508 OutlineRepeatedNum = 0;
1509 if (!doOutline(M, OutlinedFunctionNum))
1513 OutlinedFunctionNum = 0;
1514 OutlineRepeatedNum++;
1515 if (!doOutline(M, OutlinedFunctionNum)) {
1517 dbgs() <<
"Did not outline on iteration " <<
I + 2 <<
" out of "
1524 if (OutlinerMode == CGDataMode::Write)
1525 emitOutlinedHashTree(M);
1530bool MachineOutliner::doOutline(
Module &M,
unsigned &OutlinedFunctionNum) {
1537 dbgs() <<
"Machine Outliner: Running on ";
1538 switch (RunOutlinerMode) {
1539 case RunOutliner::AlwaysOutline:
1540 dbgs() <<
"all functions";
1542 case RunOutliner::OptimisticPGO:
1543 dbgs() <<
"optimistically cold functions";
1545 case RunOutliner::ConservativePGO:
1546 dbgs() <<
"conservatively cold functions";
1548 case RunOutliner::TargetDefault:
1549 dbgs() <<
"target-default functions";
1551 case RunOutliner::NeverOutline:
1560 InstructionMapper
Mapper(*MMI);
1563 populateMapper(Mapper, M);
1564 std::vector<std::unique_ptr<OutlinedFunction>> FunctionList;
1567 if (OutlinerMode == CGDataMode::Read)
1568 findGlobalCandidates(Mapper, FunctionList);
1570 findCandidates(Mapper, FunctionList);
1581 bool ShouldEmitSizeRemarks =
M.shouldEmitInstrCountChangedRemark();
1582 StringMap<unsigned> FunctionToInstrCount;
1583 if (ShouldEmitSizeRemarks)
1584 initSizeRemarkInfo(M, FunctionToInstrCount);
1587 bool OutlinedSomething =
1588 outline(M, FunctionList, Mapper, OutlinedFunctionNum);
1593 if (ShouldEmitSizeRemarks && OutlinedSomething)
1594 emitInstrCountChangedRemark(M, FunctionToInstrCount);
1597 if (!OutlinedSomething)
1598 dbgs() <<
"Stopped outlining at iteration " << OutlineRepeatedNum
1599 <<
" because no changes were found.\n";
1602 return OutlinedSomething;
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
This file defines the DenseMap class.
const HexagonInstrInfo * TII
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 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, DebugLoc OutlinedFnLoc)
#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) 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).
instr_iterator instr_begin()
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
instr_iterator instr_end()
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...
LLVM_ABI void clearKillInfo()
Clears kill flags on all operands.
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.
@ 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.
bool hasNItemsOrMore(IterTy &&Begin, IterTy &&End, unsigned N, Pred &&ShouldBeCounted=[](const decltype(*std::declval< IterTy >()) &) { return true;}, std::enable_if_t< !std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< std::remove_reference_t< decltype(Begin)> >::iterator_category >::value, void > *=nullptr)
Return true if the sequence [Begin, End) has N or more items.
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.
IRBuilder(LLVMContext &, FolderTy, InserterTy) -> IRBuilder< FolderTy, InserterTy >
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.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
auto instructionsWithoutDebug(IterT It, IterT End, bool SkipPseudoOp=true)
Construct a range iterator which begins at It and moves forwards until End is reached,...
LLVM_ABI ModulePass * createMachineOutlinerPass(RunOutliner RunOutlinerMode)
This pass performs outlining on machine instructions directly before printing assembly.
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
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 GlobalVariable * embedBufferInModule(Module &M, MemoryBufferRef Buf, StringRef SectionName, Align Alignment=Align(1), bool SectionExclude=true)
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)
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.