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);
488 void createOutlinedFunctionIfBeneficial(
489 std::vector<Candidate> &Candidates,
unsigned StringLen,
490 unsigned MinRepeats,
const TargetInstrInfo &
TII,
491 std::vector<std::unique_ptr<OutlinedFunction>> &FunctionList);
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);
559 DISubprogram *getSubprogramOrNull(
const OutlinedFunction &OF) {
560 for (
const Candidate &
C :
OF.Candidates)
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());
679 auto &InstrList = Mapper.InstrList;
680 auto &UnsignedVec = Mapper.UnsignedVec;
687 Mapper.MMI.getModule()->getContext().getLibraryOptions();
691 auto getValidInstr = [&](
unsigned Index) ->
const MachineInstr * {
692 if (UnsignedVec[Index] >= Mapper.LegalInstrNumber)
694 return &(*InstrList[Index]);
697 auto getStableHashAndFollow =
702 auto It = CurrNode->Successors.find(StableHash);
703 return (It == CurrNode->Successors.end()) ? nullptr : It->second.get();
706 for (
unsigned I = 0;
I <
Size; ++
I) {
708 if (!
MI ||
MI->isDebugInstr())
710 const HashNode *CurrNode = getStableHashAndFollow(*
MI, RootNode);
714 for (
unsigned J =
I + 1; J <
Size; ++J) {
721 CurrNode = getStableHashAndFollow(*MJ, CurrNode);
731 return MatchedEntries;
734void MachineOutliner::findGlobalCandidates(
735 InstructionMapper &Mapper,
736 std::vector<std::unique_ptr<OutlinedFunction>> &FunctionList) {
737 FunctionList.
clear();
739 auto &MBBFlagsMap =
Mapper.MBBFlagsMap;
741 std::vector<Candidate> CandidatesForRepeatedSeq;
743 CandidatesForRepeatedSeq.clear();
746 auto Length = ME.EndIdx - ME.StartIdx + 1;
747 MachineBasicBlock *
MBB = StartIt->getParent();
748 CandidatesForRepeatedSeq.emplace_back(ME.StartIdx,
Length, StartIt, EndIt,
750 const TargetInstrInfo *
TII =
752 unsigned MinRepeats = 1;
753 std::optional<std::unique_ptr<OutlinedFunction>>
OF =
754 TII->getOutliningCandidateInfo(*MMI, CandidatesForRepeatedSeq,
756 if (!
OF.has_value() ||
OF.value()->Candidates.empty())
759 assert(
OF.value()->Candidates.size() == MinRepeats);
760 FunctionList.emplace_back(std::make_unique<GlobalOutlinedFunction>(
761 std::move(
OF.value()), ME.Count));
767 return F.hasSection() ?
F.getSection() :
StringRef();
779 if (It == Sections.
end()) {
782 It = Sections.
end() - 1;
784 Partitions[std::distance(Sections.
begin(), It)].
push_back(std::move(
C));
789void MachineOutliner::createOutlinedFunctionIfBeneficial(
790 std::vector<Candidate> &Candidates,
unsigned StringLen,
unsigned MinRepeats,
791 const TargetInstrInfo &
TII,
792 std::vector<std::unique_ptr<OutlinedFunction>> &FunctionList) {
793 if (Candidates.size() < MinRepeats)
796 std::optional<std::unique_ptr<OutlinedFunction>>
OF =
797 TII.getOutliningCandidateInfo(*MMI, Candidates, MinRepeats);
801 if (!
OF.has_value() ||
OF.value()->Candidates.size() < MinRepeats)
806 emitNotOutliningCheaperRemark(StringLen, Candidates, *
OF.value());
810 FunctionList.emplace_back(std::move(
OF.value()));
813void MachineOutliner::findCandidates(
814 InstructionMapper &Mapper,
815 std::vector<std::unique_ptr<OutlinedFunction>> &FunctionList) {
816 FunctionList.clear();
821 std::vector<Candidate> CandidatesForRepeatedSeq;
822 LLVM_DEBUG(
dbgs() <<
"*** Discarding overlapping candidates *** \n");
824 dbgs() <<
"Searching for overlaps in all repeated sequences...\n");
825 for (SuffixTree::RepeatedSubstring &RS : ST) {
826 CandidatesForRepeatedSeq.clear();
827 unsigned StringLen =
RS.Length;
831 unsigned NumDiscarded = 0;
832 unsigned NumKept = 0;
837 for (
const unsigned &StartIdx :
RS.StartIndices) {
859 unsigned EndIdx = StartIdx + StringLen - 1;
860 if (!CandidatesForRepeatedSeq.empty() &&
861 StartIdx <= CandidatesForRepeatedSeq.back().getEndIdx()) {
864 LLVM_DEBUG(
dbgs() <<
" .. DISCARD candidate @ [" << StartIdx <<
", "
865 << EndIdx <<
"]; overlaps with candidate @ ["
866 << CandidatesForRepeatedSeq.back().getStartIdx()
867 <<
", " << CandidatesForRepeatedSeq.back().getEndIdx()
880 MachineBasicBlock *
MBB = StartIt->getParent();
881 CandidatesForRepeatedSeq.emplace_back(StartIdx, StringLen, StartIt, EndIt,
889 unsigned MinRepeats = 2;
894 if (CandidatesForRepeatedSeq.size() < MinRepeats)
899 const TargetInstrInfo *
TII =
900 CandidatesForRepeatedSeq[0].getMF()->getSubtarget().getInstrInfo();
905 if (!
TII->supportsSectionAwareOutlining()) {
906 createOutlinedFunctionIfBeneficial(CandidatesForRepeatedSeq, StringLen,
907 MinRepeats, *
TII, FunctionList);
913 <<
"*** Section Aware Outlining is enabled for the target *** \n");
920 for (std::vector<Candidate> &Partition : Partitions) {
923 dbgs() <<
" .. section '"
924 << (
Section.empty() ? StringRef(
"<none>") : Section)
925 <<
"': " << Partition.size() <<
" candidates\n";
927 createOutlinedFunctionIfBeneficial(Partition, StringLen, MinRepeats, *
TII,
933void MachineOutliner::computeAndPublishHashSequence(
MachineFunction &MF,
936 SmallVector<stable_hash> OutlinedHashSequence;
937 for (
auto &
MBB : MF) {
938 for (
auto &NewMI :
MBB) {
941 OutlinedHashSequence.
clear();
952 MF.getName().str() +
".content." + std::to_string(CombinedHash);
953 MF.getFunction().setName(NewName);
957 if (OutlinerMode == CGDataMode::Write) {
958 StableHashAttempts++;
959 if (!OutlinedHashSequence.
empty())
960 LocalHashTree->insert({OutlinedHashSequence, CandSize});
967 Module &M, OutlinedFunction &OF, InstructionMapper &Mapper,
unsigned Name) {
972 std::string FunctionName =
"OUTLINED_FUNCTION_";
973 if (OutlineRepeatedNum > 0)
974 FunctionName += std::to_string(OutlineRepeatedNum + 1) +
"_";
975 FunctionName += std::to_string(Name);
979 LLVMContext &
C =
M.getContext();
981 Function::ExternalLinkage, FunctionName, M);
986 F->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
990 F->addFnAttr(Attribute::OptimizeForSize);
991 F->addFnAttr(Attribute::MinSize);
993 Candidate &FirstCand =
OF.Candidates.front();
994 const TargetInstrInfo &
TII =
997 TII.mergeOutliningCandidateAttributes(*
F,
OF.Candidates);
999 if (
TII.supportsSectionAwareOutlining()) {
1010 OF.Candidates.cbegin(),
OF.Candidates.cend(), UWTableKind::None,
1012 return std::max(K, C.getMF()->getFunction().getUWTableKind());
1014 F->setUWTableKind(UW);
1018 Builder.CreateRetVoid();
1020 MachineModuleInfo &MMI = getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
1029 const std::vector<MCCFIInstruction> &Instrs =
1031 for (
auto &
MI : FirstCand) {
1032 if (
MI.isDebugInstr())
1037 if (
MI.isCFIInstruction()) {
1038 unsigned CFIIndex =
MI.getOperand(0).getCFIIndex();
1039 MCCFIInstruction CFI = Instrs[CFIIndex];
1050 for (
auto I = std::next(NewMI.
getIterator());
I != BundleEnd; ++
I) {
1058 if (OutlinerMode != CGDataMode::None)
1059 computeAndPublishHashSequence(MF,
OF.Candidates.size());
1069 const MachineRegisterInfo &MRI = MF.
getRegInfo();
1071 LivePhysRegs LiveIns(
TRI);
1072 for (
auto &Cand :
OF.Candidates) {
1074 MachineBasicBlock &OutlineBB = *Cand.front().getParent();
1075 LivePhysRegs CandLiveIns(
TRI);
1076 CandLiveIns.addLiveOuts(OutlineBB);
1077 for (
const MachineInstr &
MI :
1079 CandLiveIns.stepBackward(
MI);
1084 LiveIns.addReg(
Reg);
1088 TII.buildOutlinedFrame(
MBB, MF, OF);
1092 if (DISubprogram *SP = getSubprogramOrNull(OF)) {
1094 DICompileUnit *CU =
SP->getUnit();
1095 DIBuilder
DB(M,
true, CU);
1096 DIFile *
Unit =
SP->getFile();
1100 raw_string_ostream MangledNameStream(Dummy);
1103 DISubprogram *OutlinedSP =
DB.createFunction(
1104 Unit ,
F->getName(), StringRef(Dummy), Unit ,
1106 DB.createSubroutineType(
DB.getOrCreateTypeArray({})),
1108 DINode::DIFlags::FlagArtificial ,
1110 DISubprogram::SPFlagDefinition | DISubprogram::SPFlagOptimized);
1113 F->setSubprogram(OutlinedSP);
1121bool MachineOutliner::outline(
1122 Module &M, std::vector<std::unique_ptr<OutlinedFunction>> &FunctionList,
1123 InstructionMapper &Mapper,
unsigned &OutlinedFunctionNum) {
1125 LLVM_DEBUG(
dbgs() <<
"NUMBER OF POTENTIAL FUNCTIONS: " << FunctionList.size()
1127 bool OutlinedSomething =
false;
1131 stable_sort(FunctionList, [](
const std::unique_ptr<OutlinedFunction> &
LHS,
1132 const std::unique_ptr<OutlinedFunction> &
RHS) {
1133 return LHS->getNotOutlinedCost() *
RHS->getOutliningCost() >
1134 RHS->getNotOutlinedCost() *
LHS->getOutliningCost();
1139 auto *UnsignedVecBegin =
Mapper.UnsignedVec.begin();
1141 for (
auto &OF : FunctionList) {
1143 auto NumCandidatesBefore =
OF->Candidates.size();
1147 erase_if(
OF->Candidates, [&UnsignedVecBegin](Candidate &
C) {
1148 return std::any_of(UnsignedVecBegin + C.getStartIdx(),
1149 UnsignedVecBegin + C.getEndIdx() + 1, [](unsigned I) {
1150 return I == static_cast<unsigned>(-1);
1155 auto NumCandidatesAfter =
OF->Candidates.size();
1156 LLVM_DEBUG(
dbgs() <<
"PRUNED: " << NumCandidatesBefore - NumCandidatesAfter
1157 <<
"/" << NumCandidatesBefore <<
" candidates\n");
1175 SmallPtrSet<MachineInstr *, 2> MIs;
1176 for (Candidate &
C :
OF->Candidates) {
1177 for (MachineInstr &
MI :
C)
1186 emitOutlinedFunctionRemark(*OF);
1188 OutlinedFunctionNum++;
1195 for (Candidate &
C :
OF->Candidates) {
1196 MachineBasicBlock &
MBB = *
C.getMBB();
1203 for (MachineInstr &
MI :
C) {
1204 if (
MI.isDebugInstr())
1207 if (!
DL || !
DL.getLine())
1212 MergedCallLoc = MergedCallLoc
1223 auto CallInst =
TII.insertOutlinedCall(M,
MBB, StartIt, *MF,
C);
1232 !CallInst->isTerminator() && MergedCallLoc ? MergedCallLoc : FirstLoc;
1242 for (MachineInstr &
MI :
make_range(SeqBegin, std::next(StartIt)))
1243 MI.setDebugLoc(CallLoc);
1246 auto MBBBeingOutlinedFromName =
1252 << MFBeingOutlinedFromName <<
":"
1253 << MBBBeingOutlinedFromName <<
"\n");
1265 SmallSet<Register, 2> UseRegs, DefRegs;
1274 Last = std::next(CallInst.getReverse());
1275 Iter !=
Last; Iter++) {
1276 MachineInstr *
MI = &*Iter;
1277 if (
MI->isDebugInstr())
1279 SmallSet<Register, 2> InstrUseRegs;
1280 for (MachineOperand &MOP :
MI->operands()) {
1287 DefRegs.
insert(MOP.getReg());
1288 if (UseRegs.
count(MOP.getReg()) &&
1289 !InstrUseRegs.
count(MOP.getReg()))
1292 UseRegs.
erase(MOP.getReg());
1293 }
else if (!MOP.isUndef()) {
1296 UseRegs.
insert(MOP.getReg());
1297 InstrUseRegs.
insert(MOP.getReg());
1300 if (
MI->isCandidateForAdditionalCallInfo())
1301 MI->getMF()->eraseAdditionalCallInfo(
MI);
1306 CallInst->addOperand(
1312 CallInst->addOperand(
1320 MBB.
erase(std::next(StartIt), std::next(EndIt));
1323 for (
unsigned &
I :
make_range(UnsignedVecBegin +
C.getStartIdx(),
1324 UnsignedVecBegin +
C.getEndIdx() + 1))
1325 I =
static_cast<unsigned>(-1);
1326 OutlinedSomething =
true;
1333 LLVM_DEBUG(
dbgs() <<
"OutlinedSomething = " << OutlinedSomething <<
"\n");
1334 return OutlinedSomething;
1344 auto *MF =
MBB.getParent();
1346 ++NumPGOAllowedCold;
1350 auto *BB =
MBB.getBasicBlock();
1351 if (BB && PSI && BFI)
1357 if (
TII->shouldOutlineFromFunctionByDefault(*MF)) {
1359 ++NumPGOOptimisticOutlined;
1366 ++NumPGOConservativeBlockedOutlined;
1370void MachineOutliner::populateMapper(InstructionMapper &Mapper,
Module &M) {
1374 bool EnableProfileGuidedOutlining =
1375 RunOutlinerMode == RunOutliner::OptimisticPGO ||
1376 RunOutlinerMode == RunOutliner::ConservativePGO;
1377 ProfileSummaryInfo *PSI =
nullptr;
1378 if (EnableProfileGuidedOutlining)
1379 PSI = &getAnalysis<ProfileSummaryInfoWrapperPass>().getPSI();
1383 if (
F.hasFnAttribute(Attribute::NoOutline)) {
1384 LLVM_DEBUG(
dbgs() <<
"SKIP: Function has nooutline attribute\n");
1395 LLVM_DEBUG(
dbgs() <<
"SKIP: Function does not have a MachineFunction\n");
1400 BlockFrequencyInfo *BFI =
nullptr;
1401 if (EnableProfileGuidedOutlining &&
F.hasProfileData())
1402 BFI = &getAnalysis<BlockFrequencyInfoWrapperPass>(
F).getBFI();
1403 if (RunOutlinerMode == RunOutliner::TargetDefault &&
1404 !
TII->shouldOutlineFromFunctionByDefault(*MF)) {
1405 LLVM_DEBUG(
dbgs() <<
"SKIP: Target does not want to outline from "
1406 "function by default\n");
1412 if (!
TII->isFunctionSafeToOutlineFrom(*MF, OutlineFromLinkOnceODRs)) {
1414 <<
": unsafe to outline from\n");
1421 const unsigned MinMBBSize = 2;
1423 for (MachineBasicBlock &
MBB : *MF) {
1438 LLVM_DEBUG(
dbgs() <<
" SKIP: MBB size less than minimum size of "
1439 << MinMBBSize <<
"\n");
1451 ++NumPGOBlockedOutlined;
1460 UnsignedVecSize =
Mapper.UnsignedVec.size();
1463void MachineOutliner::initSizeRemarkInfo(
1464 const Module &M, StringMap<unsigned> &FunctionToInstrCount) {
1478void MachineOutliner::emitInstrCountChangedRemark(
1479 const Module &M,
const StringMap<unsigned> &FunctionToInstrCount) {
1491 std::string Fname = std::string(
F.getName());
1493 unsigned FnCountBefore = 0;
1496 auto It = FunctionToInstrCount.
find(Fname);
1500 if (It != FunctionToInstrCount.
end())
1501 FnCountBefore = It->second;
1504 int64_t FnDelta =
static_cast<int64_t
>(FnCountAfter) -
1505 static_cast<int64_t
>(FnCountBefore);
1509 MachineOptimizationRemarkEmitter
MORE(*MF,
nullptr);
1511 MachineOptimizationRemarkAnalysis
R(
"size-info",
"FunctionMISizeChange",
1512 DiagnosticLocation(), &MF->
front());
1513 R << DiagnosticInfoOptimizationBase::Argument(
"Pass",
"Machine Outliner")
1515 << DiagnosticInfoOptimizationBase::Argument(
"Function",
F.getName())
1516 <<
": MI instruction count changed from "
1517 << DiagnosticInfoOptimizationBase::Argument(
"MIInstrsBefore",
1520 << DiagnosticInfoOptimizationBase::Argument(
"MIInstrsAfter",
1523 << DiagnosticInfoOptimizationBase::Argument(
"Delta", FnDelta);
1529void MachineOutliner::initializeOutlinerMode(
const Module &M) {
1533 if (
auto *IndexWrapperPass =
1534 getAnalysisIfAvailable<ImmutableModuleSummaryIndexWrapperPass>()) {
1535 auto *TheIndex = IndexWrapperPass->getIndex();
1538 if (TheIndex && !TheIndex->hasExportedFunctions(M))
1546 const cl::LibraryOptionsContext &LibraryOptions =
1547 M.getContext().getLibraryOptions();
1549 OutlinerMode = CGDataMode::Write;
1551 LocalHashTree = std::make_unique<OutlinedHashTree>();
1554 OutlinerMode = CGDataMode::Read;
1557void MachineOutliner::emitOutlinedHashTree(
Module &M) {
1559 if (!LocalHashTree->empty()) {
1561 dbgs() <<
"Emit outlined hash tree. Size: " << LocalHashTree->size()
1564 SmallVector<char> Buf;
1565 raw_svector_ostream OS(Buf);
1567 OutlinedHashTreeRecord HTR(std::move(LocalHashTree));
1570 llvm::StringRef
Data(Buf.data(), Buf.size());
1571 std::unique_ptr<MemoryBuffer> Buffer =
1574 Triple
TT(
M.getTargetTriple());
1581bool MachineOutliner::runOnModule(
Module &M) {
1591 initializeOutlinerMode(M);
1593 MMI = &getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
1594 TM = &getAnalysis<TargetPassConfig>().getTM<TargetMachine>();
1597 unsigned OutlinedFunctionNum = 0;
1599 OutlineRepeatedNum = 0;
1600 if (!doOutline(M, OutlinedFunctionNum))
1604 OutlinedFunctionNum = 0;
1605 OutlineRepeatedNum++;
1606 if (!doOutline(M, OutlinedFunctionNum)) {
1608 dbgs() <<
"Did not outline on iteration " <<
I + 2 <<
" out of "
1615 if (OutlinerMode == CGDataMode::Write)
1616 emitOutlinedHashTree(M);
1621bool MachineOutliner::doOutline(
Module &M,
unsigned &OutlinedFunctionNum) {
1628 dbgs() <<
"Machine Outliner: Running on ";
1629 switch (RunOutlinerMode) {
1630 case RunOutliner::AlwaysOutline:
1631 dbgs() <<
"all functions";
1633 case RunOutliner::OptimisticPGO:
1634 dbgs() <<
"optimistically cold functions";
1636 case RunOutliner::ConservativePGO:
1637 dbgs() <<
"conservatively cold functions";
1639 case RunOutliner::TargetDefault:
1640 dbgs() <<
"target-default functions";
1642 case RunOutliner::NeverOutline:
1651 InstructionMapper
Mapper(*MMI);
1654 populateMapper(Mapper, M);
1655 std::vector<std::unique_ptr<OutlinedFunction>> FunctionList;
1658 if (OutlinerMode == CGDataMode::Read)
1659 findGlobalCandidates(Mapper, FunctionList);
1661 findCandidates(Mapper, FunctionList);
1672 bool ShouldEmitSizeRemarks =
M.shouldEmitInstrCountChangedRemark();
1673 StringMap<unsigned> FunctionToInstrCount;
1674 if (ShouldEmitSizeRemarks)
1675 initSizeRemarkInfo(M, FunctionToInstrCount);
1678 bool OutlinedSomething =
1679 outline(M, FunctionList, Mapper, OutlinedFunctionNum);
1684 if (ShouldEmitSizeRemarks && OutlinedSomething)
1685 emitInstrCountChangedRemark(M, FunctionToInstrCount);
1688 if (!OutlinedSomething)
1689 dbgs() <<
"Stopped outlining at iteration " << OutlineRepeatedNum
1690 <<
" because no changes were found.\n";
1693 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 SmallVector< std::vector< Candidate > > partitionCandidatesByInputSection(std::vector< Candidate > &Candidates)
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 StringRef getCandidateInputSection(const Candidate &C)
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 stable_hash hashInstruction(const MachineInstr &MI)
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.
static LLVM_ABI DebugLoc getMergedLocation(DebugLoc LocA, DebugLoc LocB)
When two instructions are combined into a single instruction we also need to combine the original loc...
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.
StringRef getSection() const
Get the custom section of this global if it has one.
bool hasSection() const
Check if this global has a custom object file section.
@ 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)
Represent a constant reference to a string, i.e.
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
const OutlinedHashTree * getOutlinedHashTree(const cl::LibraryOptionsContext &LibraryOptions)
bool hasOutlinedHashTree(const cl::LibraryOptionsContext &LibraryOptions)
bool emitCGData(const cl::LibraryOptionsContext &LibraryOptions)
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)
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
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.
LLVM_ABI stable_hash stableHashValue(const MachineOperand &MO, bool SourceQualifyLocalGlobals=false)
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 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.