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 assert(DenseMapInfo<unsigned>::getEmptyKey() == (
unsigned)-1 &&
424 "DenseMapInfo<unsigned>'s empty key isn't -1!");
425 assert(DenseMapInfo<unsigned>::getTombstoneKey() == (
unsigned)-2 &&
426 "DenseMapInfo<unsigned>'s tombstone key isn't -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) {
497 void emitNotOutliningCheaperRemark(
498 unsigned StringLen, std::vector<Candidate> &CandidatesForRepeatedSeq,
499 OutlinedFunction &OF);
502 void emitOutlinedFunctionRemark(OutlinedFunction &OF);
518 findCandidates(InstructionMapper &Mapper,
519 std::vector<std::unique_ptr<OutlinedFunction>> &FunctionList);
527 void findGlobalCandidates(
528 InstructionMapper &Mapper,
529 std::vector<std::unique_ptr<OutlinedFunction>> &FunctionList);
539 std::vector<std::unique_ptr<OutlinedFunction>> &FunctionList,
540 InstructionMapper &Mapper,
unsigned &OutlinedFunctionNum);
544 InstructionMapper &Mapper,
550 void computeAndPublishHashSequence(MachineFunction &MF,
unsigned CandSize);
553 void initializeOutlinerMode(
const Module &M);
556 void emitOutlinedHashTree(
Module &M);
559 bool runOnModule(
Module &M)
override;
563 bool doOutline(
Module &M,
unsigned &OutlinedFunctionNum);
568 for (
const Candidate &
C :
OF.Candidates)
569 if (MachineFunction *MF =
C.getMF())
570 if (DISubprogram *SP = MF->getFunction().getSubprogram())
577 void populateMapper(InstructionMapper &Mapper,
Module &M);
583 void initSizeRemarkInfo(
const Module &M,
584 StringMap<unsigned> &FunctionToInstrCount);
589 emitInstrCountChangedRemark(
const Module &M,
590 const StringMap<unsigned> &FunctionToInstrCount);
594char MachineOutliner::ID = 0;
598 MachineOutliner *OL =
new MachineOutliner();
599 OL->RunOutlinerMode = RunOutlinerMode;
608void MachineOutliner::emitNotOutliningCheaperRemark(
609 unsigned StringLen,
std::vector<
Candidate> &CandidatesForRepeatedSeq,
615 Candidate &
C = CandidatesForRepeatedSeq.front();
619 C.front().getDebugLoc(),
C.getMBB());
620 R <<
"Did not outline " <<
NV(
"Length", StringLen) <<
" instructions"
621 <<
" from " <<
NV(
"NumOccurrences", CandidatesForRepeatedSeq.size())
623 <<
" Bytes from outlining all occurrences ("
624 <<
NV(
"OutliningCost", OF.getOutliningCost()) <<
")"
625 <<
" >= Unoutlined instruction bytes ("
626 <<
NV(
"NotOutliningCost", OF.getNotOutlinedCost()) <<
")"
627 <<
" (Also found at: ";
630 for (
unsigned i = 1, e = CandidatesForRepeatedSeq.size(); i < e; i++) {
632 CandidatesForRepeatedSeq[i].front().
getDebugLoc());
643 MachineBasicBlock *
MBB = &*
OF.MF->begin();
644 MachineOptimizationRemarkEmitter
MORE(*
OF.MF,
nullptr);
645 MachineOptimizationRemark
R(
DEBUG_TYPE,
"OutlinedFunction",
647 R <<
"Saved " <<
NV(
"OutliningBenefit",
OF.getBenefit()) <<
" bytes by "
648 <<
"outlining " <<
NV(
"Length",
OF.getNumInstrs()) <<
" instructions "
649 <<
"from " <<
NV(
"NumOccurrences",
OF.getOccurrenceCount())
654 for (
size_t i = 0, e =
OF.Candidates.size(); i < e; i++) {
656 R <<
NV((Twine(
"StartLoc") + Twine(i)).str(),
657 OF.Candidates[i].front().getDebugLoc());
680 auto &InstrList = Mapper.InstrList;
681 auto &UnsignedVec = Mapper.UnsignedVec;
690 auto getValidInstr = [&](
unsigned Index) ->
const MachineInstr * {
691 if (UnsignedVec[Index] >= Mapper.LegalInstrNumber)
693 return &(*InstrList[Index]);
696 auto getStableHashAndFollow =
701 auto It = CurrNode->Successors.find(StableHash);
702 return (It == CurrNode->Successors.end()) ? nullptr : It->second.get();
705 for (
unsigned I = 0;
I <
Size; ++
I) {
707 if (!
MI ||
MI->isDebugInstr())
709 const HashNode *CurrNode = getStableHashAndFollow(*
MI, RootNode);
713 for (
unsigned J =
I + 1; J <
Size; ++J) {
720 CurrNode = getStableHashAndFollow(*MJ, CurrNode);
730 return MatchedEntries;
733void MachineOutliner::findGlobalCandidates(
734 InstructionMapper &Mapper,
735 std::vector<std::unique_ptr<OutlinedFunction>> &FunctionList) {
736 FunctionList.
clear();
738 auto &MBBFlagsMap = Mapper.MBBFlagsMap;
740 std::vector<Candidate> CandidatesForRepeatedSeq;
742 CandidatesForRepeatedSeq.clear();
745 auto Length = ME.EndIdx - ME.StartIdx + 1;
746 MachineBasicBlock *
MBB = StartIt->getParent();
747 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));
765void MachineOutliner::findCandidates(
766 InstructionMapper &Mapper,
767 std::vector<std::unique_ptr<OutlinedFunction>> &FunctionList) {
768 FunctionList.clear();
773 std::vector<Candidate> CandidatesForRepeatedSeq;
774 LLVM_DEBUG(
dbgs() <<
"*** Discarding overlapping candidates *** \n");
776 dbgs() <<
"Searching for overlaps in all repeated sequences...\n");
777 for (SuffixTree::RepeatedSubstring &RS : ST) {
778 CandidatesForRepeatedSeq.clear();
779 unsigned StringLen = RS.Length;
783 unsigned NumDiscarded = 0;
784 unsigned NumKept = 0;
789 for (
const unsigned &StartIdx : RS.StartIndices) {
811 unsigned EndIdx = StartIdx + StringLen - 1;
812 if (!CandidatesForRepeatedSeq.empty() &&
813 StartIdx <= CandidatesForRepeatedSeq.back().getEndIdx()) {
816 LLVM_DEBUG(
dbgs() <<
" .. DISCARD candidate @ [" << StartIdx <<
", "
817 << EndIdx <<
"]; overlaps with candidate @ ["
818 << CandidatesForRepeatedSeq.back().getStartIdx()
819 <<
", " << CandidatesForRepeatedSeq.back().getEndIdx()
832 MachineBasicBlock *
MBB = StartIt->getParent();
833 CandidatesForRepeatedSeq.emplace_back(StartIdx, StringLen, StartIt, EndIt,
835 Mapper.MBBFlagsMap[
MBB]);
842 unsigned MinRepeats = 2;
847 if (CandidatesForRepeatedSeq.size() < MinRepeats)
852 const TargetInstrInfo *
TII =
853 CandidatesForRepeatedSeq[0].getMF()->getSubtarget().getInstrInfo();
855 std::optional<std::unique_ptr<OutlinedFunction>>
OF =
856 TII->getOutliningCandidateInfo(*MMI, CandidatesForRepeatedSeq,
861 if (!
OF.has_value() ||
OF.value()->Candidates.size() < MinRepeats)
866 emitNotOutliningCheaperRemark(StringLen, CandidatesForRepeatedSeq,
871 FunctionList.emplace_back(std::move(
OF.value()));
875void MachineOutliner::computeAndPublishHashSequence(MachineFunction &MF,
878 SmallVector<stable_hash> OutlinedHashSequence;
879 for (
auto &
MBB : MF) {
880 for (
auto &NewMI :
MBB) {
883 OutlinedHashSequence.
clear();
894 MF.getName().str() +
".content." + std::to_string(CombinedHash);
895 MF.getFunction().setName(NewName);
899 if (OutlinerMode == CGDataMode::Write) {
900 StableHashAttempts++;
901 if (!OutlinedHashSequence.
empty())
902 LocalHashTree->insert({OutlinedHashSequence, CandSize});
908MachineFunction *MachineOutliner::createOutlinedFunction(
909 Module &M, OutlinedFunction &OF, InstructionMapper &Mapper,
unsigned Name) {
914 std::string FunctionName =
"OUTLINED_FUNCTION_";
915 if (OutlineRepeatedNum > 0)
916 FunctionName += std::to_string(OutlineRepeatedNum + 1) +
"_";
917 FunctionName += std::to_string(Name);
921 LLVMContext &
C =
M.getContext();
923 Function::ExternalLinkage, FunctionName, M);
928 F->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
932 F->addFnAttr(Attribute::OptimizeForSize);
933 F->addFnAttr(Attribute::MinSize);
935 Candidate &FirstCand =
OF.Candidates.front();
936 const TargetInstrInfo &
TII =
939 TII.mergeOutliningCandidateAttributes(*
F,
OF.Candidates);
943 OF.Candidates.cbegin(),
OF.Candidates.cend(), UWTableKind::None,
945 return std::max(K, C.getMF()->getFunction().getUWTableKind());
947 F->setUWTableKind(UW);
951 Builder.CreateRetVoid();
953 MachineModuleInfo &MMI = getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
961 MachineFunction *OriginalMF = FirstCand.
front().
getMF();
962 const std::vector<MCCFIInstruction> &Instrs =
964 for (
auto &
MI : FirstCand) {
965 if (
MI.isDebugInstr())
970 if (
MI.isCFIInstruction()) {
971 unsigned CFIIndex =
MI.getOperand(0).getCFIIndex();
972 MCCFIInstruction CFI = Instrs[CFIIndex];
982 if (OutlinerMode != CGDataMode::None)
983 computeAndPublishHashSequence(MF,
OF.Candidates.size());
994 const TargetRegisterInfo &
TRI = *
MRI.getTargetRegisterInfo();
995 LivePhysRegs LiveIns(
TRI);
996 for (
auto &Cand :
OF.Candidates) {
998 MachineBasicBlock &OutlineBB = *Cand.front().getParent();
999 LivePhysRegs CandLiveIns(
TRI);
1000 CandLiveIns.addLiveOuts(OutlineBB);
1001 for (
const MachineInstr &
MI :
1003 CandLiveIns.stepBackward(
MI);
1008 LiveIns.addReg(
Reg);
1012 TII.buildOutlinedFrame(
MBB, MF, OF);
1018 DICompileUnit *CU =
SP->getUnit();
1019 DIBuilder
DB(M,
true, CU);
1020 DIFile *
Unit =
SP->getFile();
1024 raw_string_ostream MangledNameStream(Dummy);
1027 DISubprogram *OutlinedSP =
DB.createFunction(
1028 Unit ,
F->getName(), StringRef(Dummy), Unit ,
1030 DB.createSubroutineType(
DB.getOrCreateTypeArray({})),
1032 DINode::DIFlags::FlagArtificial ,
1034 DISubprogram::SPFlagDefinition | DISubprogram::SPFlagOptimized);
1037 F->setSubprogram(OutlinedSP);
1045bool MachineOutliner::outline(
1046 Module &M, std::vector<std::unique_ptr<OutlinedFunction>> &FunctionList,
1047 InstructionMapper &Mapper,
unsigned &OutlinedFunctionNum) {
1049 LLVM_DEBUG(
dbgs() <<
"NUMBER OF POTENTIAL FUNCTIONS: " << FunctionList.size()
1051 bool OutlinedSomething =
false;
1055 stable_sort(FunctionList, [](
const std::unique_ptr<OutlinedFunction> &
LHS,
1056 const std::unique_ptr<OutlinedFunction> &
RHS) {
1057 return LHS->getNotOutlinedCost() *
RHS->getOutliningCost() >
1058 RHS->getNotOutlinedCost() *
LHS->getOutliningCost();
1063 auto *UnsignedVecBegin = Mapper.UnsignedVec.
begin();
1065 for (
auto &OF : FunctionList) {
1067 auto NumCandidatesBefore =
OF->Candidates.size();
1071 erase_if(
OF->Candidates, [&UnsignedVecBegin](Candidate &
C) {
1072 return std::any_of(UnsignedVecBegin + C.getStartIdx(),
1073 UnsignedVecBegin + C.getEndIdx() + 1, [](unsigned I) {
1074 return I == static_cast<unsigned>(-1);
1079 auto NumCandidatesAfter =
OF->Candidates.size();
1080 LLVM_DEBUG(
dbgs() <<
"PRUNED: " << NumCandidatesBefore - NumCandidatesAfter
1081 <<
"/" << NumCandidatesBefore <<
" candidates\n");
1099 SmallPtrSet<MachineInstr *, 2> MIs;
1100 for (Candidate &
C :
OF->Candidates) {
1101 for (MachineInstr &
MI :
C)
1103 NumRemovedLOHs +=
TM->clearLinkerOptimizationHints(MIs);
1110 emitOutlinedFunctionRemark(*OF);
1112 OutlinedFunctionNum++;
1113 MachineFunction *MF =
OF->MF;
1119 for (Candidate &
C :
OF->Candidates) {
1120 MachineBasicBlock &
MBB = *
C.getMBB();
1125 auto CallInst =
TII.insertOutlinedCall(M,
MBB, StartIt, *MF,
C);
1128 auto MBBBeingOutlinedFromName =
1134 << MFBeingOutlinedFromName <<
":"
1135 << MBBBeingOutlinedFromName <<
"\n");
1147 SmallSet<Register, 2> UseRegs, DefRegs;
1156 Last = std::next(CallInst.getReverse());
1157 Iter !=
Last; Iter++) {
1158 MachineInstr *
MI = &*Iter;
1159 SmallSet<Register, 2> InstrUseRegs;
1160 for (MachineOperand &MOP :
MI->operands()) {
1167 DefRegs.
insert(MOP.getReg());
1168 if (UseRegs.
count(MOP.getReg()) &&
1169 !InstrUseRegs.
count(MOP.getReg()))
1172 UseRegs.
erase(MOP.getReg());
1173 }
else if (!MOP.isUndef()) {
1176 UseRegs.
insert(MOP.getReg());
1177 InstrUseRegs.
insert(MOP.getReg());
1180 if (
MI->isCandidateForAdditionalCallInfo())
1181 MI->getMF()->eraseAdditionalCallInfo(
MI);
1186 CallInst->addOperand(
1192 CallInst->addOperand(
1200 MBB.
erase(std::next(StartIt), std::next(EndIt));
1203 for (
unsigned &
I :
make_range(UnsignedVecBegin +
C.getStartIdx(),
1204 UnsignedVecBegin +
C.getEndIdx() + 1))
1205 I =
static_cast<unsigned>(-1);
1206 OutlinedSomething =
true;
1213 LLVM_DEBUG(
dbgs() <<
"OutlinedSomething = " << OutlinedSomething <<
"\n");
1214 return OutlinedSomething;
1224 auto *MF =
MBB.getParent();
1226 ++NumPGOAllowedCold;
1230 auto *BB =
MBB.getBasicBlock();
1231 if (BB && PSI && BFI)
1232 if (
auto Count = BFI->getBlockProfileCount(BB))
1237 if (
TII->shouldOutlineFromFunctionByDefault(*MF)) {
1239 ++NumPGOOptimisticOutlined;
1246 ++NumPGOConservativeBlockedOutlined;
1250void MachineOutliner::populateMapper(InstructionMapper &Mapper,
Module &M) {
1254 bool EnableProfileGuidedOutlining =
1255 RunOutlinerMode == RunOutliner::OptimisticPGO ||
1256 RunOutlinerMode == RunOutliner::ConservativePGO;
1257 ProfileSummaryInfo *PSI =
nullptr;
1258 if (EnableProfileGuidedOutlining)
1259 PSI = &getAnalysis<ProfileSummaryInfoWrapperPass>().getPSI();
1260 for (Function &
F : M) {
1263 if (
F.hasFnAttribute(
"nooutline")) {
1264 LLVM_DEBUG(
dbgs() <<
"SKIP: Function has nooutline attribute\n");
1275 LLVM_DEBUG(
dbgs() <<
"SKIP: Function does not have a MachineFunction\n");
1280 BlockFrequencyInfo *
BFI =
nullptr;
1281 if (EnableProfileGuidedOutlining &&
F.hasProfileData())
1282 BFI = &getAnalysis<BlockFrequencyInfoWrapperPass>(
F).getBFI();
1283 if (RunOutlinerMode == RunOutliner::TargetDefault &&
1284 !
TII->shouldOutlineFromFunctionByDefault(*MF)) {
1285 LLVM_DEBUG(
dbgs() <<
"SKIP: Target does not want to outline from "
1286 "function by default\n");
1292 if (!
TII->isFunctionSafeToOutlineFrom(*MF, OutlineFromLinkOnceODRs)) {
1294 <<
": unsafe to outline from\n");
1301 const unsigned MinMBBSize = 2;
1303 for (MachineBasicBlock &
MBB : *MF) {
1311 if (
MBB.
size() < MinMBBSize) {
1312 LLVM_DEBUG(
dbgs() <<
" SKIP: MBB size less than minimum size of "
1313 << MinMBBSize <<
"\n");
1325 ++NumPGOBlockedOutlined;
1330 Mapper.convertToUnsignedVec(
MBB, *
TII);
1334 UnsignedVecSize = Mapper.UnsignedVec.
size();
1337void MachineOutliner::initSizeRemarkInfo(
1338 const Module &M, StringMap<unsigned> &FunctionToInstrCount) {
1341 for (
const Function &
F : M) {
1352void MachineOutliner::emitInstrCountChangedRemark(
1353 const Module &M,
const StringMap<unsigned> &FunctionToInstrCount) {
1357 for (
const Function &
F : M) {
1365 std::string Fname = std::string(
F.getName());
1367 unsigned FnCountBefore = 0;
1370 auto It = FunctionToInstrCount.
find(Fname);
1374 if (It != FunctionToInstrCount.
end())
1375 FnCountBefore = It->second;
1378 int64_t FnDelta =
static_cast<int64_t
>(FnCountAfter) -
1379 static_cast<int64_t
>(FnCountBefore);
1383 MachineOptimizationRemarkEmitter
MORE(*MF,
nullptr);
1385 MachineOptimizationRemarkAnalysis
R(
"size-info",
"FunctionMISizeChange",
1386 DiagnosticLocation(), &MF->
front());
1387 R << DiagnosticInfoOptimizationBase::Argument(
"Pass",
"Machine Outliner")
1389 << DiagnosticInfoOptimizationBase::Argument(
"Function",
F.getName())
1390 <<
": MI instruction count changed from "
1391 << DiagnosticInfoOptimizationBase::Argument(
"MIInstrsBefore",
1394 << DiagnosticInfoOptimizationBase::Argument(
"MIInstrsAfter",
1397 << DiagnosticInfoOptimizationBase::Argument(
"Delta", FnDelta);
1403void MachineOutliner::initializeOutlinerMode(
const Module &M) {
1407 if (
auto *IndexWrapperPass =
1408 getAnalysisIfAvailable<ImmutableModuleSummaryIndexWrapperPass>()) {
1409 auto *TheIndex = IndexWrapperPass->getIndex();
1412 if (TheIndex && !TheIndex->hasExportedFunctions(M))
1421 OutlinerMode = CGDataMode::Write;
1423 LocalHashTree = std::make_unique<OutlinedHashTree>();
1426 OutlinerMode = CGDataMode::Read;
1429void MachineOutliner::emitOutlinedHashTree(
Module &M) {
1431 if (!LocalHashTree->empty()) {
1433 dbgs() <<
"Emit outlined hash tree. Size: " << LocalHashTree->size()
1436 SmallVector<char> Buf;
1437 raw_svector_ostream OS(Buf);
1439 OutlinedHashTreeRecord HTR(std::move(LocalHashTree));
1442 llvm::StringRef
Data(Buf.data(), Buf.size());
1443 std::unique_ptr<MemoryBuffer> Buffer =
1446 Triple
TT(
M.getTargetTriple());
1453bool MachineOutliner::runOnModule(
Module &M) {
1463 initializeOutlinerMode(M);
1465 MMI = &getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
1466 TM = &getAnalysis<TargetPassConfig>().getTM<TargetMachine>();
1469 unsigned OutlinedFunctionNum = 0;
1471 OutlineRepeatedNum = 0;
1472 if (!doOutline(M, OutlinedFunctionNum))
1476 OutlinedFunctionNum = 0;
1477 OutlineRepeatedNum++;
1478 if (!doOutline(M, OutlinedFunctionNum)) {
1480 dbgs() <<
"Did not outline on iteration " <<
I + 2 <<
" out of "
1487 if (OutlinerMode == CGDataMode::Write)
1488 emitOutlinedHashTree(M);
1493bool MachineOutliner::doOutline(
Module &M,
unsigned &OutlinedFunctionNum) {
1500 dbgs() <<
"Machine Outliner: Running on ";
1501 switch (RunOutlinerMode) {
1502 case RunOutliner::AlwaysOutline:
1503 dbgs() <<
"all functions";
1505 case RunOutliner::OptimisticPGO:
1506 dbgs() <<
"optimistically cold functions";
1508 case RunOutliner::ConservativePGO:
1509 dbgs() <<
"conservatively cold functions";
1511 case RunOutliner::TargetDefault:
1512 dbgs() <<
"target-default functions";
1514 case RunOutliner::NeverOutline:
1523 InstructionMapper Mapper(*MMI);
1526 populateMapper(Mapper, M);
1527 std::vector<std::unique_ptr<OutlinedFunction>> FunctionList;
1530 if (OutlinerMode == CGDataMode::Read)
1531 findGlobalCandidates(Mapper, FunctionList);
1533 findCandidates(Mapper, FunctionList);
1544 bool ShouldEmitSizeRemarks =
M.shouldEmitInstrCountChangedRemark();
1545 StringMap<unsigned> FunctionToInstrCount;
1546 if (ShouldEmitSizeRemarks)
1547 initSizeRemarkInfo(M, FunctionToInstrCount);
1550 bool OutlinedSomething =
1551 outline(M, FunctionList, Mapper, OutlinedFunctionNum);
1556 if (ShouldEmitSizeRemarks && OutlinedSomething)
1557 emitInstrCountChangedRemark(M, FunctionToInstrCount);
1560 if (!OutlinedSomething)
1561 dbgs() <<
"Stopped outlining at iteration " << OutlineRepeatedNum
1562 <<
" because no changes were found.\n";
1565 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 found DebugLoc that has a DILocation, 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...
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
static LLVM_ABI PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
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 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.
LLVM_ABI void initializeMachineOutlinerPass(PassRegistry &)
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.