[llvm] [CGData][MachineOutliner] Global Outlining (PR #90074)
Ellis Hoag via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 5 12:05:35 PDT 2024
================
@@ -585,6 +644,107 @@ void MachineOutliner::emitOutlinedFunctionRemark(OutlinedFunction &OF) {
MORE.emit(R);
}
+struct MatchedEntry {
+ size_t StartIdx;
+ size_t Length;
+ size_t Count;
+};
+
+static const HashNode *followHashNode(stable_hash StableHash,
+ const HashNode *Current) {
+ auto I = Current->Successors.find(StableHash);
+ return (I == Current->Successors.end()) ? nullptr : I->second.get();
+}
+
+// Find all matches in the global outlined hash tree.
+// It's quadratic complexity in theory, but it's nearly linear in practice
+// since the length of outlined sequences are small within a block.
+static std::vector<MatchedEntry> getMatchedEntries(InstructionMapper &Mapper) {
+ auto &InstrList = Mapper.InstrList;
+ auto &UnsignedVec = Mapper.UnsignedVec;
+
+ std::vector<MatchedEntry> MatchedEntries;
+ auto Size = UnsignedVec.size();
+
+ // Get the global outlined hash tree built from the previous run.
+ assert(cgdata::hasOutlinedHashTree());
+ const auto *RootNode = cgdata::getOutlinedHashTree()->getRoot();
+ for (size_t I = 0; I < Size; ++I) {
+ // Skip the invalid mapping.
+ if (UnsignedVec[I] >= Mapper.LegalInstrNumber)
+ continue;
+ const MachineInstr &MI = *InstrList[I];
+ // Skip debug instructions as we did for the outlined function.
+ if (MI.isDebugInstr())
+ continue;
+ // Skip the empty hash value.
+ stable_hash StableHashI = stableHashValue(MI);
+ if (!StableHashI)
+ continue;
+
+ const HashNode *LastNode = followHashNode(StableHashI, RootNode);
+ if (!LastNode)
+ continue;
+
+ size_t J = I + 1;
+ for (; J < Size; ++J) {
+ // Break on the invalid mapping.
+ if (UnsignedVec[J] >= Mapper.LegalInstrNumber)
+ break;
+ // Skip debug instructions as we did for the outlined function.
+ const MachineInstr &MJ = *InstrList[J];
+ if (MJ.isDebugInstr())
+ continue;
+ // Break on the empty hash value.
+ stable_hash StableHashJ = stableHashValue(MJ);
+ if (!StableHashJ)
+ break;
+ LastNode = followHashNode(StableHashJ, LastNode);
+ if (!LastNode)
+ break;
+
+ // Even with a match ending with a terminal, we continue finding
+ // matches to populate all candidates.
+ auto Count = LastNode->Terminals;
+ if (Count)
+ MatchedEntries.push_back({I, J - I + 1, *Count});
+ }
+ }
+
+ return MatchedEntries;
+}
+
+void MachineOutliner::findGlobalCandidates(
+ InstructionMapper &Mapper,
+ std::vector<std::unique_ptr<OutlinedFunction>> &FunctionList) {
+ FunctionList.clear();
+ auto &InstrList = Mapper.InstrList;
+ auto &MBBFlagsMap = Mapper.MBBFlagsMap;
+
+ std::vector<Candidate> CandidatesForRepeatedSeq;
+ for (auto &ME : getMatchedEntries(Mapper)) {
+ CandidatesForRepeatedSeq.clear();
+ MachineBasicBlock::iterator StartIt = InstrList[ME.StartIdx];
+ MachineBasicBlock::iterator EndIt = InstrList[ME.StartIdx + ME.Length - 1];
+ MachineBasicBlock *MBB = StartIt->getParent();
+ CandidatesForRepeatedSeq.emplace_back(ME.StartIdx, ME.Length, StartIt,
+ EndIt, MBB, FunctionList.size(),
+ MBBFlagsMap[MBB]);
+ const TargetInstrInfo *TII =
+ MBB->getParent()->getSubtarget().getInstrInfo();
+ unsigned MinRepeats = 1;
+ std::optional<std::unique_ptr<OutlinedFunction>> OF =
+ TII->getOutliningCandidateInfo(*MMI, CandidatesForRepeatedSeq,
+ MinRepeats);
+ if (!OF.has_value() || OF.value()->Candidates.empty())
+ continue;
+ // We create a global candidate each match.
----------------
ellishg wrote:
```suggestion
// We create a global candidate for each match.
```
https://github.com/llvm/llvm-project/pull/90074
More information about the llvm-commits
mailing list