89#define DEBUG_TYPE "machine-outliner"
96STATISTIC(NumOutlined,
"Number of candidates outlined");
97STATISTIC(FunctionsCreated,
"Number of functions created");
100STATISTIC(NumLegalInUnsignedVec,
"Outlinable instructions mapped");
102 "Unoutlinable instructions mapped + number of sentinel values");
103STATISTIC(NumSentinels,
"Sentinel values inserted during mapping");
105 "Invisible instructions skipped during mapping");
107 "Total number of instructions mapped and saved to mapping vector");
109 "Count of hashing attempts made for outlined functions");
111 "Count of unsuccessful hashing attempts for outlined functions");
112STATISTIC(NumRemovedLOHs,
"Total number of Linker Optimization Hints removed");
114 "Number of times outlining was blocked by PGO");
116 "Number of times outlining was allowed from cold functions");
118 "Number of times outlining was blocked conservatively when profile "
119 "counts were missing");
121 "Number of times outlining was allowed optimistically when profile "
122 "counts were missing");
131 cl::desc(
"Enable the machine outliner on linkonceodr functions"),
140 "Number of times to rerun the outliner after the initial outline"));
145 "The minimum size in bytes before an outlining candidate is accepted"));
149 cl::desc(
"Consider all leaf descendants of internal nodes of the suffix "
150 "tree as candidates for outlining (if false, only leaf children "
155 cl::desc(
"Disable global outlining only by ignoring "
156 "the codegen data generation or use"),
160 "append-content-hash-outlined-name",
cl::Hidden,
161 cl::desc(
"This appends the content hash to the globally outlined function "
162 "name. It's beneficial for enhancing the precision of the stable "
163 "hash and for ordering the outlined functions."),
169struct InstructionMapper {
176 unsigned IllegalInstrNumber = -3;
180 unsigned LegalInstrNumber = 0;
184 InstructionIntegerMap;
200 bool AddedIllegalLastTime =
false;
208 unsigned mapToLegalUnsigned(
210 bool &HaveLegalRange,
unsigned &NumLegalInBlock,
215 AddedIllegalLastTime =
false;
219 if (CanOutlineWithPrevInstr)
220 HaveLegalRange =
true;
221 CanOutlineWithPrevInstr =
true;
233 std::tie(ResultIt, WasInserted) =
234 InstructionIntegerMap.
insert(std::make_pair(&
MI, LegalInstrNumber));
235 unsigned MINumber = ResultIt->second;
244 if (LegalInstrNumber >= IllegalInstrNumber)
248 ++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) {
349 mapToIllegalUnsigned(It, CanOutlineWithPrevInstr, UnsignedVecForMBB,
354 <<
" instructions outside outlinable range\n");
356 assert(It !=
MBB.
end() &&
"Should still have instructions?");
359 for (; It != OutlinableRangeEnd; ++It) {
361 switch (
TII.getOutliningType(MMI, It, Flags)) {
362 case InstrType::Illegal:
363 mapToIllegalUnsigned(It, CanOutlineWithPrevInstr, UnsignedVecForMBB,
367 case InstrType::Legal:
368 mapToLegalUnsigned(It, CanOutlineWithPrevInstr, HaveLegalRange,
369 NumLegalInBlock, UnsignedVecForMBB,
373 case InstrType::LegalTerminator:
374 mapToLegalUnsigned(It, CanOutlineWithPrevInstr, HaveLegalRange,
375 NumLegalInBlock, UnsignedVecForMBB,
379 mapToIllegalUnsigned(It, CanOutlineWithPrevInstr, UnsignedVecForMBB,
383 case InstrType::Invisible:
387 AddedIllegalLastTime =
false;
393 LLVM_DEBUG(
dbgs() <<
"HaveLegalRange = " << HaveLegalRange <<
"\n");
397 if (HaveLegalRange) {
402 mapToIllegalUnsigned(It, CanOutlineWithPrevInstr, UnsignedVecForMBB,
410 InstructionMapper(
const MachineModuleInfo &MMI_) : MMI(MMI_) {}
426 MachineModuleInfo *MMI =
nullptr;
427 const TargetMachine *TM =
nullptr;
431 bool OutlineFromLinkOnceODRs =
false;
434 unsigned OutlineRepeatedNum = 0;
439 RunOutliner RunOutlinerMode = RunOutliner::AlwaysOutline;
447 std::unique_ptr<OutlinedHashTree> LocalHashTree;
458 StringRef getPassName()
const override {
return "Machine Outliner"; }
460 void getAnalysisUsage(AnalysisUsage &AU)
const override {
465 if (RunOutlinerMode == RunOutliner::OptimisticPGO ||
466 RunOutlinerMode == RunOutliner::ConservativePGO) {
471 ModulePass::getAnalysisUsage(AU);
474 MachineOutliner() : ModulePass(ID) {}
478 void emitNotOutliningCheaperRemark(
479 unsigned StringLen, std::vector<Candidate> &CandidatesForRepeatedSeq,
480 OutlinedFunction &OF);
483 void emitOutlinedFunctionRemark(OutlinedFunction &OF);
499 findCandidates(InstructionMapper &Mapper,
500 std::vector<std::unique_ptr<OutlinedFunction>> &FunctionList);
508 void findGlobalCandidates(
509 InstructionMapper &Mapper,
510 std::vector<std::unique_ptr<OutlinedFunction>> &FunctionList);
520 std::vector<std::unique_ptr<OutlinedFunction>> &FunctionList,
521 InstructionMapper &Mapper,
unsigned &OutlinedFunctionNum);
525 InstructionMapper &Mapper,
531 void computeAndPublishHashSequence(MachineFunction &MF,
unsigned CandSize);
534 void initializeOutlinerMode(
const Module &M);
537 void emitOutlinedHashTree(
Module &M);
540 bool runOnModule(
Module &M)
override;
544 bool doOutline(
Module &M,
unsigned &OutlinedFunctionNum);
549 for (
const Candidate &
C :
OF.Candidates)
550 if (MachineFunction *MF =
C.getMF())
551 if (DISubprogram *SP = MF->getFunction().getSubprogram())
558 void populateMapper(InstructionMapper &Mapper,
Module &M);
564 void initSizeRemarkInfo(
const Module &M,
565 StringMap<unsigned> &FunctionToInstrCount);
570 emitInstrCountChangedRemark(
const Module &M,
571 const StringMap<unsigned> &FunctionToInstrCount);
575char MachineOutliner::ID = 0;
578 MachineOutliner *OL =
new MachineOutliner();
579 OL->RunOutlinerMode = RunOutlinerMode;
586void MachineOutliner::emitNotOutliningCheaperRemark(
587 unsigned StringLen,
std::vector<
Candidate> &CandidatesForRepeatedSeq,
593 Candidate &
C = CandidatesForRepeatedSeq.front();
597 C.front().getDebugLoc(),
C.getMBB());
598 R <<
"Did not outline " <<
NV(
"Length", StringLen) <<
" instructions"
599 <<
" from " <<
NV(
"NumOccurrences", CandidatesForRepeatedSeq.size())
601 <<
" Bytes from outlining all occurrences ("
602 <<
NV(
"OutliningCost", OF.getOutliningCost()) <<
")"
603 <<
" >= Unoutlined instruction bytes ("
604 <<
NV(
"NotOutliningCost", OF.getNotOutlinedCost()) <<
")"
605 <<
" (Also found at: ";
608 for (
unsigned i = 1, e = CandidatesForRepeatedSeq.size(); i < e; i++) {
610 CandidatesForRepeatedSeq[i].front().
getDebugLoc());
621 MachineBasicBlock *
MBB = &*
OF.MF->begin();
622 MachineOptimizationRemarkEmitter
MORE(*
OF.MF,
nullptr);
623 MachineOptimizationRemark
R(
DEBUG_TYPE,
"OutlinedFunction",
625 R <<
"Saved " <<
NV(
"OutliningBenefit",
OF.getBenefit()) <<
" bytes by "
626 <<
"outlining " <<
NV(
"Length",
OF.getNumInstrs()) <<
" instructions "
627 <<
"from " <<
NV(
"NumOccurrences",
OF.getOccurrenceCount())
632 for (
size_t i = 0, e =
OF.Candidates.size(); i < e; i++) {
634 R <<
NV((Twine(
"StartLoc") + Twine(i)).str(),
635 OF.Candidates[i].front().getDebugLoc());
658 auto &InstrList = Mapper.InstrList;
659 auto &UnsignedVec = Mapper.UnsignedVec;
668 auto getValidInstr = [&](
unsigned Index) ->
const MachineInstr * {
669 if (UnsignedVec[Index] >= Mapper.LegalInstrNumber)
671 return &(*InstrList[Index]);
674 auto getStableHashAndFollow =
679 auto It = CurrNode->Successors.find(StableHash);
680 return (It == CurrNode->Successors.end()) ? nullptr : It->second.get();
683 for (
unsigned I = 0;
I <
Size; ++
I) {
685 if (!
MI ||
MI->isDebugInstr())
687 const HashNode *CurrNode = getStableHashAndFollow(*
MI, RootNode);
691 for (
unsigned J =
I + 1; J <
Size; ++J) {
698 CurrNode = getStableHashAndFollow(*MJ, CurrNode);
708 return MatchedEntries;
711void MachineOutliner::findGlobalCandidates(
712 InstructionMapper &Mapper,
713 std::vector<std::unique_ptr<OutlinedFunction>> &FunctionList) {
714 FunctionList.
clear();
716 auto &MBBFlagsMap = Mapper.MBBFlagsMap;
718 std::vector<Candidate> CandidatesForRepeatedSeq;
720 CandidatesForRepeatedSeq.clear();
723 auto Length = ME.EndIdx - ME.StartIdx + 1;
724 MachineBasicBlock *
MBB = StartIt->getParent();
725 CandidatesForRepeatedSeq.emplace_back(ME.StartIdx,
Length, StartIt, EndIt,
728 const TargetInstrInfo *
TII =
730 unsigned MinRepeats = 1;
731 std::optional<std::unique_ptr<OutlinedFunction>>
OF =
732 TII->getOutliningCandidateInfo(*MMI, CandidatesForRepeatedSeq,
734 if (!
OF.has_value() ||
OF.value()->Candidates.empty())
737 assert(
OF.value()->Candidates.size() == MinRepeats);
738 FunctionList.emplace_back(std::make_unique<GlobalOutlinedFunction>(
739 std::move(
OF.value()), ME.Count));
743void MachineOutliner::findCandidates(
744 InstructionMapper &Mapper,
745 std::vector<std::unique_ptr<OutlinedFunction>> &FunctionList) {
746 FunctionList.clear();
751 std::vector<Candidate> CandidatesForRepeatedSeq;
752 LLVM_DEBUG(
dbgs() <<
"*** Discarding overlapping candidates *** \n");
754 dbgs() <<
"Searching for overlaps in all repeated sequences...\n");
755 for (SuffixTree::RepeatedSubstring &RS : ST) {
756 CandidatesForRepeatedSeq.clear();
757 unsigned StringLen =
RS.Length;
761 unsigned NumDiscarded = 0;
762 unsigned NumKept = 0;
767 for (
const unsigned &StartIdx :
RS.StartIndices) {
789 unsigned EndIdx = StartIdx + StringLen - 1;
790 if (!CandidatesForRepeatedSeq.empty() &&
791 StartIdx <= CandidatesForRepeatedSeq.back().getEndIdx()) {
794 LLVM_DEBUG(
dbgs() <<
" .. DISCARD candidate @ [" << StartIdx <<
", "
795 << EndIdx <<
"]; overlaps with candidate @ ["
796 << CandidatesForRepeatedSeq.back().getStartIdx()
797 <<
", " << CandidatesForRepeatedSeq.back().getEndIdx()
810 MachineBasicBlock *
MBB = StartIt->getParent();
811 CandidatesForRepeatedSeq.emplace_back(StartIdx, StringLen, StartIt, EndIt,
813 Mapper.MBBFlagsMap[
MBB]);
820 unsigned MinRepeats = 2;
825 if (CandidatesForRepeatedSeq.size() < MinRepeats)
830 const TargetInstrInfo *
TII =
831 CandidatesForRepeatedSeq[0].getMF()->getSubtarget().getInstrInfo();
833 std::optional<std::unique_ptr<OutlinedFunction>>
OF =
834 TII->getOutliningCandidateInfo(*MMI, CandidatesForRepeatedSeq,
839 if (!
OF.has_value() ||
OF.value()->Candidates.size() < MinRepeats)
844 emitNotOutliningCheaperRemark(StringLen, CandidatesForRepeatedSeq,
849 FunctionList.emplace_back(std::move(
OF.value()));
853void MachineOutliner::computeAndPublishHashSequence(MachineFunction &MF,
856 SmallVector<stable_hash> OutlinedHashSequence;
857 for (
auto &
MBB : MF) {
858 for (
auto &NewMI :
MBB) {
861 OutlinedHashSequence.
clear();
872 MF.getName().str() +
".content." + std::to_string(CombinedHash);
873 MF.getFunction().setName(NewName);
877 if (OutlinerMode == CGDataMode::Write) {
878 StableHashAttempts++;
879 if (!OutlinedHashSequence.
empty())
880 LocalHashTree->insert({OutlinedHashSequence, CandSize});
886MachineFunction *MachineOutliner::createOutlinedFunction(
887 Module &M, OutlinedFunction &OF, InstructionMapper &Mapper,
unsigned Name) {
892 std::string FunctionName =
"OUTLINED_FUNCTION_";
893 if (OutlineRepeatedNum > 0)
894 FunctionName += std::to_string(OutlineRepeatedNum + 1) +
"_";
895 FunctionName += std::to_string(Name);
899 LLVMContext &
C =
M.getContext();
901 Function::ExternalLinkage, FunctionName, M);
906 F->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
910 F->addFnAttr(Attribute::OptimizeForSize);
911 F->addFnAttr(Attribute::MinSize);
913 Candidate &FirstCand =
OF.Candidates.front();
914 const TargetInstrInfo &
TII =
917 TII.mergeOutliningCandidateAttributes(*
F,
OF.Candidates);
921 OF.Candidates.cbegin(),
OF.Candidates.cend(), UWTableKind::None,
923 return std::max(K, C.getMF()->getFunction().getUWTableKind());
925 F->setUWTableKind(UW);
929 Builder.CreateRetVoid();
931 MachineModuleInfo &MMI = getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
939 MachineFunction *OriginalMF = FirstCand.
front().
getMF();
940 const std::vector<MCCFIInstruction> &Instrs =
942 for (
auto &
MI : FirstCand) {
943 if (
MI.isDebugInstr())
948 if (
MI.isCFIInstruction()) {
949 unsigned CFIIndex =
MI.getOperand(0).getCFIIndex();
950 MCCFIInstruction CFI = Instrs[CFIIndex];
960 for (
auto I = std::next(NewMI.
getIterator());
I != BundleEnd; ++
I)
966 if (OutlinerMode != CGDataMode::None)
967 computeAndPublishHashSequence(MF,
OF.Candidates.size());
977 const MachineRegisterInfo &MRI = MF.
getRegInfo();
979 LivePhysRegs LiveIns(
TRI);
980 for (
auto &Cand :
OF.Candidates) {
982 MachineBasicBlock &OutlineBB = *Cand.front().getParent();
983 LivePhysRegs CandLiveIns(
TRI);
984 CandLiveIns.addLiveOuts(OutlineBB);
985 for (
const MachineInstr &
MI :
987 CandLiveIns.stepBackward(
MI);
996 TII.buildOutlinedFrame(
MBB, MF, OF);
1002 DICompileUnit *CU =
SP->getUnit();
1003 DIBuilder
DB(M,
true, CU);
1004 DIFile *
Unit =
SP->getFile();
1008 raw_string_ostream MangledNameStream(Dummy);
1011 DISubprogram *OutlinedSP =
DB.createFunction(
1012 Unit ,
F->getName(), StringRef(Dummy), Unit ,
1014 DB.createSubroutineType(
DB.getOrCreateTypeArray({})),
1016 DINode::DIFlags::FlagArtificial ,
1018 DISubprogram::SPFlagDefinition | DISubprogram::SPFlagOptimized);
1021 F->setSubprogram(OutlinedSP);
1029bool MachineOutliner::outline(
1030 Module &M, std::vector<std::unique_ptr<OutlinedFunction>> &FunctionList,
1031 InstructionMapper &Mapper,
unsigned &OutlinedFunctionNum) {
1033 LLVM_DEBUG(
dbgs() <<
"NUMBER OF POTENTIAL FUNCTIONS: " << FunctionList.size()
1035 bool OutlinedSomething =
false;
1039 stable_sort(FunctionList, [](
const std::unique_ptr<OutlinedFunction> &
LHS,
1040 const std::unique_ptr<OutlinedFunction> &
RHS) {
1041 return LHS->getNotOutlinedCost() *
RHS->getOutliningCost() >
1042 RHS->getNotOutlinedCost() *
LHS->getOutliningCost();
1047 auto *UnsignedVecBegin = Mapper.UnsignedVec.
begin();
1049 for (
auto &OF : FunctionList) {
1051 auto NumCandidatesBefore =
OF->Candidates.size();
1055 erase_if(
OF->Candidates, [&UnsignedVecBegin](Candidate &
C) {
1056 return std::any_of(UnsignedVecBegin + C.getStartIdx(),
1057 UnsignedVecBegin + C.getEndIdx() + 1, [](unsigned I) {
1058 return I == static_cast<unsigned>(-1);
1063 auto NumCandidatesAfter =
OF->Candidates.size();
1064 LLVM_DEBUG(
dbgs() <<
"PRUNED: " << NumCandidatesBefore - NumCandidatesAfter
1065 <<
"/" << NumCandidatesBefore <<
" candidates\n");
1083 SmallPtrSet<MachineInstr *, 2> MIs;
1084 for (Candidate &
C :
OF->Candidates) {
1085 for (MachineInstr &
MI :
C)
1094 emitOutlinedFunctionRemark(*OF);
1096 OutlinedFunctionNum++;
1097 MachineFunction *MF =
OF->MF;
1103 for (Candidate &
C :
OF->Candidates) {
1104 MachineBasicBlock &
MBB = *
C.getMBB();
1109 auto CallInst =
TII.insertOutlinedCall(M,
MBB, StartIt, *MF,
C);
1112 auto MBBBeingOutlinedFromName =
1118 << MFBeingOutlinedFromName <<
":"
1119 << MBBBeingOutlinedFromName <<
"\n");
1131 SmallSet<Register, 2> UseRegs, DefRegs;
1140 Last = std::next(CallInst.getReverse());
1141 Iter !=
Last; Iter++) {
1142 MachineInstr *
MI = &*Iter;
1143 if (
MI->isDebugInstr())
1145 SmallSet<Register, 2> InstrUseRegs;
1146 for (MachineOperand &MOP :
MI->operands()) {
1153 DefRegs.
insert(MOP.getReg());
1154 if (UseRegs.
count(MOP.getReg()) &&
1155 !InstrUseRegs.
count(MOP.getReg()))
1158 UseRegs.
erase(MOP.getReg());
1159 }
else if (!MOP.isUndef()) {
1162 UseRegs.
insert(MOP.getReg());
1163 InstrUseRegs.
insert(MOP.getReg());
1166 if (
MI->isCandidateForAdditionalCallInfo())
1167 MI->getMF()->eraseAdditionalCallInfo(
MI);
1172 CallInst->addOperand(
1178 CallInst->addOperand(
1186 MBB.
erase(std::next(StartIt), std::next(EndIt));
1189 for (
unsigned &
I :
make_range(UnsignedVecBegin +
C.getStartIdx(),
1190 UnsignedVecBegin +
C.getEndIdx() + 1))
1191 I =
static_cast<unsigned>(-1);
1192 OutlinedSomething =
true;
1199 LLVM_DEBUG(
dbgs() <<
"OutlinedSomething = " << OutlinedSomething <<
"\n");
1200 return OutlinedSomething;
1210 auto *MF =
MBB.getParent();
1212 ++NumPGOAllowedCold;
1216 auto *BB =
MBB.getBasicBlock();
1217 if (BB && PSI && BFI)
1223 if (
TII->shouldOutlineFromFunctionByDefault(*MF)) {
1225 ++NumPGOOptimisticOutlined;
1232 ++NumPGOConservativeBlockedOutlined;
1236void MachineOutliner::populateMapper(InstructionMapper &Mapper,
Module &M) {
1240 bool EnableProfileGuidedOutlining =
1241 RunOutlinerMode == RunOutliner::OptimisticPGO ||
1242 RunOutlinerMode == RunOutliner::ConservativePGO;
1243 ProfileSummaryInfo *PSI =
nullptr;
1244 if (EnableProfileGuidedOutlining)
1245 PSI = &getAnalysis<ProfileSummaryInfoWrapperPass>().getPSI();
1246 for (Function &
F : M) {
1249 if (
F.hasFnAttribute(Attribute::NoOutline)) {
1250 LLVM_DEBUG(
dbgs() <<
"SKIP: Function has nooutline attribute\n");
1261 LLVM_DEBUG(
dbgs() <<
"SKIP: Function does not have a MachineFunction\n");
1266 BlockFrequencyInfo *BFI =
nullptr;
1267 if (EnableProfileGuidedOutlining &&
F.hasProfileData())
1268 BFI = &getAnalysis<BlockFrequencyInfoWrapperPass>(
F).getBFI();
1269 if (RunOutlinerMode == RunOutliner::TargetDefault &&
1270 !
TII->shouldOutlineFromFunctionByDefault(*MF)) {
1271 LLVM_DEBUG(
dbgs() <<
"SKIP: Target does not want to outline from "
1272 "function by default\n");
1278 if (!
TII->isFunctionSafeToOutlineFrom(*MF, OutlineFromLinkOnceODRs)) {
1280 <<
": unsafe to outline from\n");
1287 const unsigned MinMBBSize = 2;
1289 for (MachineBasicBlock &
MBB : *MF) {
1297 if (
MBB.
size() < MinMBBSize) {
1298 LLVM_DEBUG(
dbgs() <<
" SKIP: MBB size less than minimum size of "
1299 << MinMBBSize <<
"\n");
1311 ++NumPGOBlockedOutlined;
1316 Mapper.convertToUnsignedVec(
MBB, *
TII);
1320 UnsignedVecSize = Mapper.UnsignedVec.
size();
1323void MachineOutliner::initSizeRemarkInfo(
1324 const Module &M, StringMap<unsigned> &FunctionToInstrCount) {
1327 for (
const Function &
F : M) {
1338void MachineOutliner::emitInstrCountChangedRemark(
1339 const Module &M,
const StringMap<unsigned> &FunctionToInstrCount) {
1343 for (
const Function &
F : M) {
1351 std::string Fname = std::string(
F.getName());
1353 unsigned FnCountBefore = 0;
1356 auto It = FunctionToInstrCount.
find(Fname);
1360 if (It != FunctionToInstrCount.
end())
1361 FnCountBefore = It->second;
1364 int64_t FnDelta =
static_cast<int64_t
>(FnCountAfter) -
1365 static_cast<int64_t
>(FnCountBefore);
1369 MachineOptimizationRemarkEmitter
MORE(*MF,
nullptr);
1371 MachineOptimizationRemarkAnalysis
R(
"size-info",
"FunctionMISizeChange",
1372 DiagnosticLocation(), &MF->
front());
1373 R << DiagnosticInfoOptimizationBase::Argument(
"Pass",
"Machine Outliner")
1375 << DiagnosticInfoOptimizationBase::Argument(
"Function",
F.getName())
1376 <<
": MI instruction count changed from "
1377 << DiagnosticInfoOptimizationBase::Argument(
"MIInstrsBefore",
1380 << DiagnosticInfoOptimizationBase::Argument(
"MIInstrsAfter",
1383 << DiagnosticInfoOptimizationBase::Argument(
"Delta", FnDelta);
1389void MachineOutliner::initializeOutlinerMode(
const Module &M) {
1393 if (
auto *IndexWrapperPass =
1394 getAnalysisIfAvailable<ImmutableModuleSummaryIndexWrapperPass>()) {
1395 auto *TheIndex = IndexWrapperPass->getIndex();
1398 if (TheIndex && !TheIndex->hasExportedFunctions(M))
1407 OutlinerMode = CGDataMode::Write;
1409 LocalHashTree = std::make_unique<OutlinedHashTree>();
1412 OutlinerMode = CGDataMode::Read;
1415void MachineOutliner::emitOutlinedHashTree(
Module &M) {
1417 if (!LocalHashTree->empty()) {
1419 dbgs() <<
"Emit outlined hash tree. Size: " << LocalHashTree->size()
1422 SmallVector<char> Buf;
1423 raw_svector_ostream OS(Buf);
1425 OutlinedHashTreeRecord HTR(std::move(LocalHashTree));
1428 llvm::StringRef
Data(Buf.data(), Buf.size());
1429 std::unique_ptr<MemoryBuffer> Buffer =
1432 Triple
TT(
M.getTargetTriple());
1439bool MachineOutliner::runOnModule(
Module &M) {
1449 initializeOutlinerMode(M);
1451 MMI = &getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
1452 TM = &getAnalysis<TargetPassConfig>().getTM<TargetMachine>();
1455 unsigned OutlinedFunctionNum = 0;
1457 OutlineRepeatedNum = 0;
1458 if (!doOutline(M, OutlinedFunctionNum))
1462 OutlinedFunctionNum = 0;
1463 OutlineRepeatedNum++;
1464 if (!doOutline(M, OutlinedFunctionNum)) {
1466 dbgs() <<
"Did not outline on iteration " <<
I + 2 <<
" out of "
1473 if (OutlinerMode == CGDataMode::Write)
1474 emitOutlinedHashTree(M);
1479bool MachineOutliner::doOutline(
Module &M,
unsigned &OutlinedFunctionNum) {
1486 dbgs() <<
"Machine Outliner: Running on ";
1487 switch (RunOutlinerMode) {
1488 case RunOutliner::AlwaysOutline:
1489 dbgs() <<
"all functions";
1491 case RunOutliner::OptimisticPGO:
1492 dbgs() <<
"optimistically cold functions";
1494 case RunOutliner::ConservativePGO:
1495 dbgs() <<
"conservatively cold functions";
1497 case RunOutliner::TargetDefault:
1498 dbgs() <<
"target-default functions";
1500 case RunOutliner::NeverOutline:
1509 InstructionMapper Mapper(*MMI);
1512 populateMapper(Mapper, M);
1513 std::vector<std::unique_ptr<OutlinedFunction>> FunctionList;
1516 if (OutlinerMode == CGDataMode::Read)
1517 findGlobalCandidates(Mapper, FunctionList);
1519 findCandidates(Mapper, FunctionList);
1530 bool ShouldEmitSizeRemarks =
M.shouldEmitInstrCountChangedRemark();
1531 StringMap<unsigned> FunctionToInstrCount;
1532 if (ShouldEmitSizeRemarks)
1533 initSizeRemarkInfo(M, FunctionToInstrCount);
1536 bool OutlinedSomething =
1537 outline(M, FunctionList, Mapper, OutlinedFunctionNum);
1542 if (ShouldEmitSizeRemarks && OutlinedSomething)
1543 emitInstrCountChangedRemark(M, FunctionToInstrCount);
1546 if (!OutlinedSomething)
1547 dbgs() <<
"Stopped outlining at iteration " << OutlineRepeatedNum
1548 <<
" because no changes were found.\n";
1551 return OutlinedSomething;
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file defines the DenseMap class.
const HexagonInstrInfo * TII
static DISubprogram * getSubprogramOrNull(OutlinableGroup &Group)
Get the subprogram if it exists for one of the outlined regions.
Module.h This file contains the declarations for the Module class.
This file implements the LivePhysRegs utility for tracking liveness of physical registers.
Machine Check Debug Module
static DebugLoc getDebugLoc(MachineBasicBlock::instr_iterator FirstMI, MachineBasicBlock::instr_iterator LastMI)
Return the first DebugLoc that has line number information, given a range of instructions.
static cl::opt< bool > DisableGlobalOutlining("disable-global-outlining", cl::Hidden, cl::desc("Disable global outlining only by ignoring " "the codegen data generation or use"), cl::init(false))
static bool allowPGOOutlining(RunOutliner RunOutlinerMode, const ProfileSummaryInfo *PSI, const BlockFrequencyInfo *BFI, MachineBasicBlock &MBB)
static cl::opt< unsigned > OutlinerBenefitThreshold("outliner-benefit-threshold", cl::init(1), cl::Hidden, cl::desc("The minimum size in bytes before an outlining candidate is accepted"))
static cl::opt< bool > OutlinerLeafDescendants("outliner-leaf-descendants", cl::init(true), cl::Hidden, cl::desc("Consider all leaf descendants of internal nodes of the suffix " "tree as candidates for outlining (if false, only leaf children " "are considered)"))
static cl::opt< bool > AppendContentHashToOutlinedName("append-content-hash-outlined-name", cl::Hidden, cl::desc("This appends the content hash to the globally outlined function " "name. It's beneficial for enhancing the precision of the stable " "hash and for ordering the outlined functions."), cl::init(true))
static cl::opt< unsigned > OutlinerReruns("machine-outliner-reruns", cl::init(0), cl::Hidden, cl::desc("Number of times to rerun the outliner after the initial outline"))
Number of times to re-run the outliner.
static cl::opt< bool > EnableLinkOnceODROutlining("enable-linkonceodr-outlining", cl::Hidden, cl::desc("Enable the machine outliner on linkonceodr functions"), cl::init(false))
static SmallVector< MatchedEntry > getMatchedEntries(InstructionMapper &Mapper)
Contains all data structures shared between the outliner implemented in MachineOutliner....
Register const TargetRegisterInfo * TRI
Promote Memory to Register
This is the interface to build a ModuleSummaryIndex for a module.
static Expected< Function * > createOutlinedFunction(OpenMPIRBuilder &OMPBuilder, IRBuilderBase &Builder, const OpenMPIRBuilder::TargetKernelDefaultAttrs &DefaultAttrs, StringRef FuncName, SmallVectorImpl< Value * > &Inputs, OpenMPIRBuilder::TargetBodyGenCallbackTy &CBFunc, OpenMPIRBuilder::TargetGenArgAccessorsCallbackTy &ArgAccessorFuncCB)
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
This file defines the SmallSet class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Target-Independent Code Generator Pass Configuration Options pass.
AnalysisUsage & addUsedIfAvailable()
Add the specified Pass class to the set of analyses used by this pass.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
void setPreservesAll()
Set by analyses that do not transform their input at all.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
BlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to estimate IR basic block frequen...
LLVM_ABI std::optional< uint64_t > getBlockProfileCount(const BasicBlock *BB, bool AllowSynthetic=false) const
Returns the estimated profile count of BB.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
@ InternalLinkage
Rename collisions when linking (static functions).
bool hasAddressTaken() const
Test whether this block is used as something other than the target of a terminator,...
LLVM_ABI DebugLoc findDebugLoc(instr_iterator MBBI)
Find the next valid DebugLoc starting at MBBI, skipping any debug instructions.
MachineInstrBundleIterator< MachineInstr, true > reverse_iterator
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
LLVM_ABI instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
MachineInstrBundleIterator< MachineInstr > iterator
LLVM_ABI StringRef getName() const
Return the name of the corresponding LLVM basic block, or an empty string.
unsigned getInstructionCount() const
Return the number of MachineInstrs in this MachineFunction.
unsigned addFrameInst(const MCCFIInstruction &Inst)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
const std::vector< MCCFIInstruction > & getFrameInstructions() const
Returns a reference to a list of cfi instructions in the function's prologue.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
void setIsOutlined(bool V)
const MachineFunctionProperties & getProperties() const
Get the function properties.
const MachineBasicBlock & front() const
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const MachineInstrBuilder & addCFIIndex(unsigned CFIIndex) const
reverse_iterator getReverse() const
Get a reverse iterator to the same node.
Representation of each machine instruction.
bool isDebugInstr() const
LLVM_ABI void dropMemRefs(MachineFunction &MF)
Clear this MachineInstr's memory reference descriptor list.
LLVM_ABI const MachineFunction * getMF() const
Return the function that contains the basic block that this instruction belongs to.
bool isBundledWithSucc() const
Return true if this instruction is part of a bundle, and it is not the last instruction in the bundle...
void setDebugLoc(DebugLoc DL)
Replace current source information with new such.
This class contains meta information specific to a module.
LLVM_ABI MachineFunction & getOrCreateMachineFunction(Function &F)
Returns the MachineFunction constructed for the IR function F.
LLVM_ABI MachineFunction * getMachineFunction(const Function &F) const
Returns the MachineFunction associated to IR function F if there is one, otherwise nullptr.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
LLVM_ABI void freezeReservedRegs()
freezeReservedRegs - Called by the register allocator to freeze the set of reserved registers before ...
const TargetRegisterInfo * getTargetRegisterInfo() const
LLVM_ABI void getNameWithPrefix(raw_ostream &OS, const GlobalValue *GV, bool CannotUsePrivateLabel) const
Print the appropriate prefix and the specified global variable's name.
static std::unique_ptr< MemoryBuffer > getMemBuffer(StringRef InputData, StringRef BufferName="", bool RequiresNullTerminator=true)
Open the specified memory range as a MemoryBuffer.
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
const HashNode * getRoot() const
Analysis providing profile information.
LLVM_ABI uint64_t getOrCompColdCountThreshold() const
Returns ColdCountThreshold if set.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
size_type count(const T &V) const
count - Return 1 if the element is in the set, 0 otherwise.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
reference emplace_back(ArgTypes &&... Args)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
iterator find(StringRef Key)
std::string str() const
Get the contents as an std::string.
constexpr bool empty() const
Check if the string is empty.
constexpr size_t size() const
Get the string size.
virtual size_t clearLinkerOptimizationHints(const SmallPtrSetImpl< MachineInstr * > &MIs) const
Remove all Linker Optimization Hints (LOH) associated with instructions in MIs and.
virtual const TargetInstrInfo * getInstrInfo() const
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ C
The default llvm calling convention, compatible with C.
@ BasicBlock
Various leaf nodes.
SmallVector< const MachineInstr * > InstrList
bool hasOutlinedHashTree()
const OutlinedHashTree * getOutlinedHashTree()
initializer< Ty > init(const Ty &Val)
Add a small namespace to avoid name clashes with the classes used in the streaming interface.
DiagnosticInfoOptimizationBase::Argument NV
This is an optimization pass for GlobalISel generic memory operations.
void stable_sort(R &&Range)
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
uint64_t stable_hash
An opaque object representing a stable hash code.
auto reverse(ContainerTy &&C)
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI stable_hash stableHashValue(const MachineOperand &MO)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
MachineBasicBlock::instr_iterator getBundleEnd(MachineBasicBlock::instr_iterator I)
Returns an iterator pointing beyond the bundle containing I.
FunctionAddr VTableAddr Count
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
LLVM_ABI ModulePass * createMachineOutlinerPass(RunOutliner RunOutlinerMode)
This pass performs outlining on machine instructions directly before printing assembly.
FunctionAddr VTableAddr uintptr_t uintptr_t Data
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
stable_hash stable_hash_combine(ArrayRef< stable_hash > Buffer)
LLVM_ABI void embedBufferInModule(Module &M, MemoryBufferRef Buf, StringRef SectionName, Align Alignment=Align(1))
Embed the memory buffer Buf into the module M as a global using the specified section name.
LLVM_ABI void addLiveIns(MachineBasicBlock &MBB, const LivePhysRegs &LiveRegs)
Adds registers contained in LiveRegs to the block live-in list of MBB.
LLVM_ABI std::string getCodeGenDataSectionName(CGDataSectKind CGSK, Triple::ObjectFormatType OF, bool AddSegmentInfo=true)
Implement std::hash so that hash_code can be used in STL containers.
MatchedEntry(unsigned StartIdx, unsigned EndIdx, unsigned Count)
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.