88#define DEBUG_TYPE "machine-outliner"
95STATISTIC(NumOutlined,
"Number of candidates outlined");
96STATISTIC(FunctionsCreated,
"Number of functions created");
99STATISTIC(NumLegalInUnsignedVec,
"Outlinable instructions mapped");
101 "Unoutlinable instructions mapped + number of sentinel values");
102STATISTIC(NumSentinels,
"Sentinel values inserted during mapping");
104 "Invisible instructions skipped during mapping");
106 "Total number of instructions mapped and saved to mapping vector");
108 "Count of hashing attempts made for outlined functions");
110 "Count of unsuccessful hashing attempts for outlined functions");
111STATISTIC(NumRemovedLOHs,
"Total number of Linker Optimization Hints removed");
113 "Number of times outlining was blocked by PGO");
115 "Number of times outlining was allowed from cold functions");
117 "Number of times outlining was blocked conservatively when profile "
118 "counts were missing");
120 "Number of times outlining was allowed optimistically when profile "
121 "counts were missing");
130 cl::desc(
"Enable the machine outliner on linkonceodr functions"),
139 "Number of times to rerun the outliner after the initial outline"));
144 "The minimum size in bytes before an outlining candidate is accepted"));
148 cl::desc(
"Consider all leaf descendants of internal nodes of the suffix "
149 "tree as candidates for outlining (if false, only leaf children "
154 cl::desc(
"Disable global outlining only by ignoring "
155 "the codegen data generation or use"),
159 "append-content-hash-outlined-name",
cl::Hidden,
160 cl::desc(
"This appends the content hash to the globally outlined function "
161 "name. It's beneficial for enhancing the precision of the stable "
162 "hash and for ordering the outlined functions."),
168struct InstructionMapper {
175 unsigned IllegalInstrNumber = -3;
179 unsigned LegalInstrNumber = 0;
183 InstructionIntegerMap;
199 bool AddedIllegalLastTime =
false;
207 unsigned mapToLegalUnsigned(
209 bool &HaveLegalRange,
unsigned &NumLegalInBlock,
214 AddedIllegalLastTime =
false;
218 if (CanOutlineWithPrevInstr)
219 HaveLegalRange =
true;
220 CanOutlineWithPrevInstr =
true;
232 std::tie(ResultIt, WasInserted) =
233 InstructionIntegerMap.
insert(std::make_pair(&
MI, LegalInstrNumber));
234 unsigned MINumber = ResultIt->second;
243 if (LegalInstrNumber >= IllegalInstrNumber)
247 "Tried to assign DenseMap tombstone or empty key to instruction.");
249 "Tried to assign DenseMap tombstone or empty key to instruction.");
252 ++NumLegalInUnsignedVec;
262 unsigned mapToIllegalUnsigned(
264 SmallVector<unsigned> &UnsignedVecForMBB,
267 CanOutlineWithPrevInstr =
false;
270 if (AddedIllegalLastTime)
271 return IllegalInstrNumber;
274 AddedIllegalLastTime =
true;
275 unsigned MINumber = IllegalInstrNumber;
278 UnsignedVecForMBB.
push_back(IllegalInstrNumber);
279 IllegalInstrNumber--;
281 ++NumIllegalInUnsignedVec;
283 assert(LegalInstrNumber < IllegalInstrNumber &&
284 "Instruction mapping overflow!");
286 assert(IllegalInstrNumber != DenseMapInfo<unsigned>::getEmptyKey() &&
287 "IllegalInstrNumber cannot be DenseMap tombstone or empty key!");
289 assert(IllegalInstrNumber != DenseMapInfo<unsigned>::getTombstoneKey() &&
290 "IllegalInstrNumber cannot be DenseMap tombstone or empty key!");
305 void convertToUnsignedVec(MachineBasicBlock &
MBB,
306 const TargetInstrInfo &
TII) {
308 <<
"' to unsigned vector ***\n");
312 if (!
TII.isMBBSafeToOutlineFrom(
MBB, Flags))
315 auto OutlinableRanges =
TII.getOutlinableRanges(
MBB, Flags);
317 <<
" outlinable range(s)\n");
318 if (OutlinableRanges.empty())
328 unsigned NumLegalInBlock = 0;
332 bool HaveLegalRange =
false;
336 bool CanOutlineWithPrevInstr =
false;
340 SmallVector<unsigned> UnsignedVecForMBB;
344 for (
auto &OutlinableRange : OutlinableRanges) {
345 auto OutlinableRangeBegin = OutlinableRange.first;
346 auto OutlinableRangeEnd = OutlinableRange.second;
350 << std::distance(OutlinableRangeBegin, OutlinableRangeEnd)
351 <<
" instruction range\n");
353 unsigned NumSkippedInRange = 0;
355 for (; It != OutlinableRangeBegin; ++It) {
359 mapToIllegalUnsigned(It, CanOutlineWithPrevInstr, UnsignedVecForMBB,
364 <<
" instructions outside outlinable range\n");
366 assert(It !=
MBB.
end() &&
"Should still have instructions?");
369 for (; It != OutlinableRangeEnd; ++It) {
371 switch (
TII.getOutliningType(MMI, It, Flags)) {
372 case InstrType::Illegal:
373 mapToIllegalUnsigned(It, CanOutlineWithPrevInstr, UnsignedVecForMBB,
377 case InstrType::Legal:
378 mapToLegalUnsigned(It, CanOutlineWithPrevInstr, HaveLegalRange,
379 NumLegalInBlock, UnsignedVecForMBB,
383 case InstrType::LegalTerminator:
384 mapToLegalUnsigned(It, CanOutlineWithPrevInstr, HaveLegalRange,
385 NumLegalInBlock, UnsignedVecForMBB,
389 mapToIllegalUnsigned(It, CanOutlineWithPrevInstr, UnsignedVecForMBB,
393 case InstrType::Invisible:
397 AddedIllegalLastTime =
false;
403 LLVM_DEBUG(
dbgs() <<
"HaveLegalRange = " << HaveLegalRange <<
"\n");
407 if (HaveLegalRange) {
412 mapToIllegalUnsigned(It, CanOutlineWithPrevInstr, UnsignedVecForMBB,
420 InstructionMapper(
const MachineModuleInfo &MMI_) : MMI(MMI_) {
423 static_assert(DenseMapInfo<unsigned>::getEmptyKey() ==
424 static_cast<unsigned>(-1));
425 static_assert(DenseMapInfo<unsigned>::getTombstoneKey() ==
426 static_cast<unsigned>(-2));
443 MachineModuleInfo *MMI =
nullptr;
444 const TargetMachine *TM =
nullptr;
448 bool OutlineFromLinkOnceODRs =
false;
451 unsigned OutlineRepeatedNum = 0;
456 RunOutliner RunOutlinerMode = RunOutliner::AlwaysOutline;
464 std::unique_ptr<OutlinedHashTree> LocalHashTree;
475 StringRef getPassName()
const override {
return "Machine Outliner"; }
477 void getAnalysisUsage(AnalysisUsage &AU)
const override {
482 if (RunOutlinerMode == RunOutliner::OptimisticPGO ||
483 RunOutlinerMode == RunOutliner::ConservativePGO) {
488 ModulePass::getAnalysisUsage(AU);
491 MachineOutliner() : ModulePass(ID) {}
495 void emitNotOutliningCheaperRemark(
496 unsigned StringLen, std::vector<Candidate> &CandidatesForRepeatedSeq,
497 OutlinedFunction &OF);
500 void emitOutlinedFunctionRemark(OutlinedFunction &OF);
516 findCandidates(InstructionMapper &Mapper,
517 std::vector<std::unique_ptr<OutlinedFunction>> &FunctionList);
525 void findGlobalCandidates(
526 InstructionMapper &Mapper,
527 std::vector<std::unique_ptr<OutlinedFunction>> &FunctionList);
537 std::vector<std::unique_ptr<OutlinedFunction>> &FunctionList,
538 InstructionMapper &Mapper,
unsigned &OutlinedFunctionNum);
542 InstructionMapper &Mapper,
548 void computeAndPublishHashSequence(MachineFunction &MF,
unsigned CandSize);
551 void initializeOutlinerMode(
const Module &M);
554 void emitOutlinedHashTree(
Module &M);
557 bool runOnModule(
Module &M)
override;
561 bool doOutline(
Module &M,
unsigned &OutlinedFunctionNum);
566 for (
const Candidate &
C :
OF.Candidates)
567 if (MachineFunction *MF =
C.getMF())
568 if (DISubprogram *SP = MF->getFunction().getSubprogram())
575 void populateMapper(InstructionMapper &Mapper,
Module &M);
581 void initSizeRemarkInfo(
const Module &M,
582 StringMap<unsigned> &FunctionToInstrCount);
587 emitInstrCountChangedRemark(
const Module &M,
588 const StringMap<unsigned> &FunctionToInstrCount);
592char MachineOutliner::ID = 0;
595 MachineOutliner *OL =
new MachineOutliner();
596 OL->RunOutlinerMode = RunOutlinerMode;
603void MachineOutliner::emitNotOutliningCheaperRemark(
604 unsigned StringLen,
std::vector<
Candidate> &CandidatesForRepeatedSeq,
610 Candidate &
C = CandidatesForRepeatedSeq.front();
614 C.front().getDebugLoc(),
C.getMBB());
615 R <<
"Did not outline " <<
NV(
"Length", StringLen) <<
" instructions"
616 <<
" from " <<
NV(
"NumOccurrences", CandidatesForRepeatedSeq.size())
618 <<
" Bytes from outlining all occurrences ("
619 <<
NV(
"OutliningCost", OF.getOutliningCost()) <<
")"
620 <<
" >= Unoutlined instruction bytes ("
621 <<
NV(
"NotOutliningCost", OF.getNotOutlinedCost()) <<
")"
622 <<
" (Also found at: ";
625 for (
unsigned i = 1, e = CandidatesForRepeatedSeq.size(); i < e; i++) {
627 CandidatesForRepeatedSeq[i].front().
getDebugLoc());
638 MachineBasicBlock *
MBB = &*
OF.MF->begin();
639 MachineOptimizationRemarkEmitter
MORE(*
OF.MF,
nullptr);
640 MachineOptimizationRemark
R(
DEBUG_TYPE,
"OutlinedFunction",
642 R <<
"Saved " <<
NV(
"OutliningBenefit",
OF.getBenefit()) <<
" bytes by "
643 <<
"outlining " <<
NV(
"Length",
OF.getNumInstrs()) <<
" instructions "
644 <<
"from " <<
NV(
"NumOccurrences",
OF.getOccurrenceCount())
649 for (
size_t i = 0, e =
OF.Candidates.size(); i < e; i++) {
651 R <<
NV((Twine(
"StartLoc") + Twine(i)).str(),
652 OF.Candidates[i].front().getDebugLoc());
675 auto &InstrList = Mapper.InstrList;
676 auto &UnsignedVec = Mapper.UnsignedVec;
685 auto getValidInstr = [&](
unsigned Index) ->
const MachineInstr * {
686 if (UnsignedVec[Index] >= Mapper.LegalInstrNumber)
688 return &(*InstrList[Index]);
691 auto getStableHashAndFollow =
696 auto It = CurrNode->Successors.find(StableHash);
697 return (It == CurrNode->Successors.end()) ? nullptr : It->second.get();
700 for (
unsigned I = 0;
I <
Size; ++
I) {
702 if (!
MI ||
MI->isDebugInstr())
704 const HashNode *CurrNode = getStableHashAndFollow(*
MI, RootNode);
708 for (
unsigned J =
I + 1; J <
Size; ++J) {
715 CurrNode = getStableHashAndFollow(*MJ, CurrNode);
725 return MatchedEntries;
728void MachineOutliner::findGlobalCandidates(
729 InstructionMapper &Mapper,
730 std::vector<std::unique_ptr<OutlinedFunction>> &FunctionList) {
731 FunctionList.
clear();
733 auto &MBBFlagsMap = Mapper.MBBFlagsMap;
735 std::vector<Candidate> CandidatesForRepeatedSeq;
737 CandidatesForRepeatedSeq.clear();
740 auto Length = ME.EndIdx - ME.StartIdx + 1;
741 MachineBasicBlock *
MBB = StartIt->getParent();
742 CandidatesForRepeatedSeq.emplace_back(ME.StartIdx,
Length, StartIt, EndIt,
745 const TargetInstrInfo *
TII =
747 unsigned MinRepeats = 1;
748 std::optional<std::unique_ptr<OutlinedFunction>>
OF =
749 TII->getOutliningCandidateInfo(*MMI, CandidatesForRepeatedSeq,
751 if (!
OF.has_value() ||
OF.value()->Candidates.empty())
754 assert(
OF.value()->Candidates.size() == MinRepeats);
755 FunctionList.emplace_back(std::make_unique<GlobalOutlinedFunction>(
756 std::move(
OF.value()), ME.Count));
760void MachineOutliner::findCandidates(
761 InstructionMapper &Mapper,
762 std::vector<std::unique_ptr<OutlinedFunction>> &FunctionList) {
763 FunctionList.clear();
768 std::vector<Candidate> CandidatesForRepeatedSeq;
769 LLVM_DEBUG(
dbgs() <<
"*** Discarding overlapping candidates *** \n");
771 dbgs() <<
"Searching for overlaps in all repeated sequences...\n");
772 for (SuffixTree::RepeatedSubstring &RS : ST) {
773 CandidatesForRepeatedSeq.clear();
774 unsigned StringLen =
RS.Length;
778 unsigned NumDiscarded = 0;
779 unsigned NumKept = 0;
784 for (
const unsigned &StartIdx :
RS.StartIndices) {
806 unsigned EndIdx = StartIdx + StringLen - 1;
807 if (!CandidatesForRepeatedSeq.empty() &&
808 StartIdx <= CandidatesForRepeatedSeq.back().getEndIdx()) {
811 LLVM_DEBUG(
dbgs() <<
" .. DISCARD candidate @ [" << StartIdx <<
", "
812 << EndIdx <<
"]; overlaps with candidate @ ["
813 << CandidatesForRepeatedSeq.back().getStartIdx()
814 <<
", " << CandidatesForRepeatedSeq.back().getEndIdx()
827 MachineBasicBlock *
MBB = StartIt->getParent();
828 CandidatesForRepeatedSeq.emplace_back(StartIdx, StringLen, StartIt, EndIt,
830 Mapper.MBBFlagsMap[
MBB]);
837 unsigned MinRepeats = 2;
842 if (CandidatesForRepeatedSeq.size() < MinRepeats)
847 const TargetInstrInfo *
TII =
848 CandidatesForRepeatedSeq[0].getMF()->getSubtarget().getInstrInfo();
850 std::optional<std::unique_ptr<OutlinedFunction>>
OF =
851 TII->getOutliningCandidateInfo(*MMI, CandidatesForRepeatedSeq,
856 if (!
OF.has_value() ||
OF.value()->Candidates.size() < MinRepeats)
861 emitNotOutliningCheaperRemark(StringLen, CandidatesForRepeatedSeq,
866 FunctionList.emplace_back(std::move(
OF.value()));
870void MachineOutliner::computeAndPublishHashSequence(MachineFunction &MF,
873 SmallVector<stable_hash> OutlinedHashSequence;
874 for (
auto &
MBB : MF) {
875 for (
auto &NewMI :
MBB) {
878 OutlinedHashSequence.
clear();
889 MF.getName().str() +
".content." + std::to_string(CombinedHash);
890 MF.getFunction().setName(NewName);
894 if (OutlinerMode == CGDataMode::Write) {
895 StableHashAttempts++;
896 if (!OutlinedHashSequence.
empty())
897 LocalHashTree->insert({OutlinedHashSequence, CandSize});
903MachineFunction *MachineOutliner::createOutlinedFunction(
904 Module &M, OutlinedFunction &OF, InstructionMapper &Mapper,
unsigned Name) {
909 std::string FunctionName =
"OUTLINED_FUNCTION_";
910 if (OutlineRepeatedNum > 0)
911 FunctionName += std::to_string(OutlineRepeatedNum + 1) +
"_";
912 FunctionName += std::to_string(Name);
916 LLVMContext &
C =
M.getContext();
918 Function::ExternalLinkage, FunctionName, M);
923 F->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
927 F->addFnAttr(Attribute::OptimizeForSize);
928 F->addFnAttr(Attribute::MinSize);
930 Candidate &FirstCand =
OF.Candidates.front();
931 const TargetInstrInfo &
TII =
934 TII.mergeOutliningCandidateAttributes(*
F,
OF.Candidates);
938 OF.Candidates.cbegin(),
OF.Candidates.cend(), UWTableKind::None,
940 return std::max(K, C.getMF()->getFunction().getUWTableKind());
942 F->setUWTableKind(UW);
946 Builder.CreateRetVoid();
948 MachineModuleInfo &MMI = getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
956 MachineFunction *OriginalMF = FirstCand.
front().
getMF();
957 const std::vector<MCCFIInstruction> &Instrs =
959 for (
auto &
MI : FirstCand) {
960 if (
MI.isDebugInstr())
965 if (
MI.isCFIInstruction()) {
966 unsigned CFIIndex =
MI.getOperand(0).getCFIIndex();
967 MCCFIInstruction CFI = Instrs[CFIIndex];
977 if (OutlinerMode != CGDataMode::None)
978 computeAndPublishHashSequence(MF,
OF.Candidates.size());
989 const TargetRegisterInfo &
TRI = *
MRI.getTargetRegisterInfo();
990 LivePhysRegs LiveIns(
TRI);
991 for (
auto &Cand :
OF.Candidates) {
993 MachineBasicBlock &OutlineBB = *Cand.front().getParent();
994 LivePhysRegs CandLiveIns(
TRI);
995 CandLiveIns.addLiveOuts(OutlineBB);
996 for (
const MachineInstr &
MI :
998 CandLiveIns.stepBackward(
MI);
1003 LiveIns.addReg(
Reg);
1007 TII.buildOutlinedFrame(
MBB, MF, OF);
1013 DICompileUnit *CU =
SP->getUnit();
1014 DIBuilder
DB(M,
true, CU);
1015 DIFile *
Unit =
SP->getFile();
1019 raw_string_ostream MangledNameStream(Dummy);
1022 DISubprogram *OutlinedSP =
DB.createFunction(
1023 Unit ,
F->getName(), StringRef(Dummy), Unit ,
1025 DB.createSubroutineType(
DB.getOrCreateTypeArray({})),
1027 DINode::DIFlags::FlagArtificial ,
1029 DISubprogram::SPFlagDefinition | DISubprogram::SPFlagOptimized);
1032 F->setSubprogram(OutlinedSP);
1040bool MachineOutliner::outline(
1041 Module &M, std::vector<std::unique_ptr<OutlinedFunction>> &FunctionList,
1042 InstructionMapper &Mapper,
unsigned &OutlinedFunctionNum) {
1044 LLVM_DEBUG(
dbgs() <<
"NUMBER OF POTENTIAL FUNCTIONS: " << FunctionList.size()
1046 bool OutlinedSomething =
false;
1050 stable_sort(FunctionList, [](
const std::unique_ptr<OutlinedFunction> &
LHS,
1051 const std::unique_ptr<OutlinedFunction> &
RHS) {
1052 return LHS->getNotOutlinedCost() *
RHS->getOutliningCost() >
1053 RHS->getNotOutlinedCost() *
LHS->getOutliningCost();
1058 auto *UnsignedVecBegin = Mapper.UnsignedVec.
begin();
1060 for (
auto &OF : FunctionList) {
1062 auto NumCandidatesBefore =
OF->Candidates.size();
1066 erase_if(
OF->Candidates, [&UnsignedVecBegin](Candidate &
C) {
1067 return std::any_of(UnsignedVecBegin + C.getStartIdx(),
1068 UnsignedVecBegin + C.getEndIdx() + 1, [](unsigned I) {
1069 return I == static_cast<unsigned>(-1);
1074 auto NumCandidatesAfter =
OF->Candidates.size();
1075 LLVM_DEBUG(
dbgs() <<
"PRUNED: " << NumCandidatesBefore - NumCandidatesAfter
1076 <<
"/" << NumCandidatesBefore <<
" candidates\n");
1094 SmallPtrSet<MachineInstr *, 2> MIs;
1095 for (Candidate &
C :
OF->Candidates) {
1096 for (MachineInstr &
MI :
C)
1105 emitOutlinedFunctionRemark(*OF);
1107 OutlinedFunctionNum++;
1108 MachineFunction *MF =
OF->MF;
1114 for (Candidate &
C :
OF->Candidates) {
1115 MachineBasicBlock &
MBB = *
C.getMBB();
1120 auto CallInst =
TII.insertOutlinedCall(M,
MBB, StartIt, *MF,
C);
1123 auto MBBBeingOutlinedFromName =
1129 << MFBeingOutlinedFromName <<
":"
1130 << MBBBeingOutlinedFromName <<
"\n");
1142 SmallSet<Register, 2> UseRegs, DefRegs;
1151 Last = std::next(CallInst.getReverse());
1152 Iter !=
Last; Iter++) {
1153 MachineInstr *
MI = &*Iter;
1154 SmallSet<Register, 2> InstrUseRegs;
1155 for (MachineOperand &MOP :
MI->operands()) {
1162 DefRegs.
insert(MOP.getReg());
1163 if (UseRegs.
count(MOP.getReg()) &&
1164 !InstrUseRegs.
count(MOP.getReg()))
1167 UseRegs.
erase(MOP.getReg());
1168 }
else if (!MOP.isUndef()) {
1171 UseRegs.
insert(MOP.getReg());
1172 InstrUseRegs.
insert(MOP.getReg());
1175 if (
MI->isCandidateForAdditionalCallInfo())
1176 MI->getMF()->eraseAdditionalCallInfo(
MI);
1181 CallInst->addOperand(
1187 CallInst->addOperand(
1195 MBB.
erase(std::next(StartIt), std::next(EndIt));
1198 for (
unsigned &
I :
make_range(UnsignedVecBegin +
C.getStartIdx(),
1199 UnsignedVecBegin +
C.getEndIdx() + 1))
1200 I =
static_cast<unsigned>(-1);
1201 OutlinedSomething =
true;
1208 LLVM_DEBUG(
dbgs() <<
"OutlinedSomething = " << OutlinedSomething <<
"\n");
1209 return OutlinedSomething;
1219 auto *MF =
MBB.getParent();
1221 ++NumPGOAllowedCold;
1225 auto *BB =
MBB.getBasicBlock();
1226 if (BB && PSI && BFI)
1232 if (
TII->shouldOutlineFromFunctionByDefault(*MF)) {
1234 ++NumPGOOptimisticOutlined;
1241 ++NumPGOConservativeBlockedOutlined;
1245void MachineOutliner::populateMapper(InstructionMapper &Mapper,
Module &M) {
1249 bool EnableProfileGuidedOutlining =
1250 RunOutlinerMode == RunOutliner::OptimisticPGO ||
1251 RunOutlinerMode == RunOutliner::ConservativePGO;
1252 ProfileSummaryInfo *PSI =
nullptr;
1253 if (EnableProfileGuidedOutlining)
1254 PSI = &getAnalysis<ProfileSummaryInfoWrapperPass>().getPSI();
1255 for (Function &
F : M) {
1258 if (
F.hasFnAttribute(
"nooutline")) {
1259 LLVM_DEBUG(
dbgs() <<
"SKIP: Function has nooutline attribute\n");
1270 LLVM_DEBUG(
dbgs() <<
"SKIP: Function does not have a MachineFunction\n");
1275 BlockFrequencyInfo *BFI =
nullptr;
1276 if (EnableProfileGuidedOutlining &&
F.hasProfileData())
1277 BFI = &getAnalysis<BlockFrequencyInfoWrapperPass>(
F).getBFI();
1278 if (RunOutlinerMode == RunOutliner::TargetDefault &&
1279 !
TII->shouldOutlineFromFunctionByDefault(*MF)) {
1280 LLVM_DEBUG(
dbgs() <<
"SKIP: Target does not want to outline from "
1281 "function by default\n");
1287 if (!
TII->isFunctionSafeToOutlineFrom(*MF, OutlineFromLinkOnceODRs)) {
1289 <<
": unsafe to outline from\n");
1296 const unsigned MinMBBSize = 2;
1298 for (MachineBasicBlock &
MBB : *MF) {
1306 if (
MBB.
size() < MinMBBSize) {
1307 LLVM_DEBUG(
dbgs() <<
" SKIP: MBB size less than minimum size of "
1308 << MinMBBSize <<
"\n");
1320 ++NumPGOBlockedOutlined;
1325 Mapper.convertToUnsignedVec(
MBB, *
TII);
1329 UnsignedVecSize = Mapper.UnsignedVec.
size();
1332void MachineOutliner::initSizeRemarkInfo(
1333 const Module &M, StringMap<unsigned> &FunctionToInstrCount) {
1336 for (
const Function &
F : M) {
1347void MachineOutliner::emitInstrCountChangedRemark(
1348 const Module &M,
const StringMap<unsigned> &FunctionToInstrCount) {
1352 for (
const Function &
F : M) {
1360 std::string Fname = std::string(
F.getName());
1362 unsigned FnCountBefore = 0;
1365 auto It = FunctionToInstrCount.
find(Fname);
1369 if (It != FunctionToInstrCount.
end())
1370 FnCountBefore = It->second;
1373 int64_t FnDelta =
static_cast<int64_t
>(FnCountAfter) -
1374 static_cast<int64_t
>(FnCountBefore);
1378 MachineOptimizationRemarkEmitter
MORE(*MF,
nullptr);
1380 MachineOptimizationRemarkAnalysis
R(
"size-info",
"FunctionMISizeChange",
1381 DiagnosticLocation(), &MF->
front());
1382 R << DiagnosticInfoOptimizationBase::Argument(
"Pass",
"Machine Outliner")
1384 << DiagnosticInfoOptimizationBase::Argument(
"Function",
F.getName())
1385 <<
": MI instruction count changed from "
1386 << DiagnosticInfoOptimizationBase::Argument(
"MIInstrsBefore",
1389 << DiagnosticInfoOptimizationBase::Argument(
"MIInstrsAfter",
1392 << DiagnosticInfoOptimizationBase::Argument(
"Delta", FnDelta);
1398void MachineOutliner::initializeOutlinerMode(
const Module &M) {
1402 if (
auto *IndexWrapperPass =
1403 getAnalysisIfAvailable<ImmutableModuleSummaryIndexWrapperPass>()) {
1404 auto *TheIndex = IndexWrapperPass->getIndex();
1407 if (TheIndex && !TheIndex->hasExportedFunctions(M))
1416 OutlinerMode = CGDataMode::Write;
1418 LocalHashTree = std::make_unique<OutlinedHashTree>();
1421 OutlinerMode = CGDataMode::Read;
1424void MachineOutliner::emitOutlinedHashTree(
Module &M) {
1426 if (!LocalHashTree->empty()) {
1428 dbgs() <<
"Emit outlined hash tree. Size: " << LocalHashTree->size()
1431 SmallVector<char> Buf;
1432 raw_svector_ostream OS(Buf);
1434 OutlinedHashTreeRecord HTR(std::move(LocalHashTree));
1437 llvm::StringRef
Data(Buf.data(), Buf.size());
1438 std::unique_ptr<MemoryBuffer> Buffer =
1441 Triple
TT(
M.getTargetTriple());
1448bool MachineOutliner::runOnModule(
Module &M) {
1458 initializeOutlinerMode(M);
1460 MMI = &getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
1461 TM = &getAnalysis<TargetPassConfig>().getTM<TargetMachine>();
1464 unsigned OutlinedFunctionNum = 0;
1466 OutlineRepeatedNum = 0;
1467 if (!doOutline(M, OutlinedFunctionNum))
1471 OutlinedFunctionNum = 0;
1472 OutlineRepeatedNum++;
1473 if (!doOutline(M, OutlinedFunctionNum)) {
1475 dbgs() <<
"Did not outline on iteration " <<
I + 2 <<
" out of "
1482 if (OutlinerMode == CGDataMode::Write)
1483 emitOutlinedHashTree(M);
1488bool MachineOutliner::doOutline(
Module &M,
unsigned &OutlinedFunctionNum) {
1495 dbgs() <<
"Machine Outliner: Running on ";
1496 switch (RunOutlinerMode) {
1497 case RunOutliner::AlwaysOutline:
1498 dbgs() <<
"all functions";
1500 case RunOutliner::OptimisticPGO:
1501 dbgs() <<
"optimistically cold functions";
1503 case RunOutliner::ConservativePGO:
1504 dbgs() <<
"conservatively cold functions";
1506 case RunOutliner::TargetDefault:
1507 dbgs() <<
"target-default functions";
1509 case RunOutliner::NeverOutline:
1518 InstructionMapper Mapper(*MMI);
1521 populateMapper(Mapper, M);
1522 std::vector<std::unique_ptr<OutlinedFunction>> FunctionList;
1525 if (OutlinerMode == CGDataMode::Read)
1526 findGlobalCandidates(Mapper, FunctionList);
1528 findCandidates(Mapper, FunctionList);
1539 bool ShouldEmitSizeRemarks =
M.shouldEmitInstrCountChangedRemark();
1540 StringMap<unsigned> FunctionToInstrCount;
1541 if (ShouldEmitSizeRemarks)
1542 initSizeRemarkInfo(M, FunctionToInstrCount);
1545 bool OutlinedSomething =
1546 outline(M, FunctionList, Mapper, OutlinedFunctionNum);
1551 if (ShouldEmitSizeRemarks && OutlinedSomething)
1552 emitInstrCountChangedRemark(M, FunctionToInstrCount);
1555 if (!OutlinedSomething)
1556 dbgs() <<
"Stopped outlining at iteration " << OutlineRepeatedNum
1557 <<
" because no changes were found.\n";
1560 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.
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...
#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)
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.