[MachineOutliner] Add optimisation remarks for successful outlining
This commit adds optimisation remarks for outlining which fire when a function
is successfully outlined.
To do this, OutlinedFunctions must now contain references to their Candidates.
Since the Candidates must still be sorted and worked on separately, this is
done by working on everything in terms of shared_ptrs to Candidates. This is
good; it means that we can easily move everything to outlining in terms of
the OutlinedFunctions rather than the individual Candidates. This is far more
intuitive than what's currently there!
(Remarks are output when a function is created for some group of Candidates.
In a later commit, all of the outlining logic should be rewritten so that we
loop over OutlinedFunctions rather than over Candidates.)
llvm-svn: 316396
diff --git a/llvm/lib/CodeGen/MachineOutliner.cpp b/llvm/lib/CodeGen/MachineOutliner.cpp
index cf919a0..1bc869e 100644
--- a/llvm/lib/CodeGen/MachineOutliner.cpp
+++ b/llvm/lib/CodeGen/MachineOutliner.cpp
@@ -149,6 +149,8 @@
unsigned OccurrenceCount = 0;
public:
+ std::vector<std::shared_ptr<Candidate>> Candidates;
+
/// The actual outlined function created.
/// This is initialized after we go through and create the actual function.
MachineFunction *MF = nullptr;
@@ -807,10 +809,11 @@
/// type of candidate.
///
/// \returns The length of the longest candidate found.
- unsigned findCandidates(SuffixTree &ST, const TargetInstrInfo &TII,
- InstructionMapper &Mapper,
- std::vector<Candidate> &CandidateList,
- std::vector<OutlinedFunction> &FunctionList);
+ unsigned
+ findCandidates(SuffixTree &ST, const TargetInstrInfo &TII,
+ InstructionMapper &Mapper,
+ std::vector<std::shared_ptr<Candidate>> &CandidateList,
+ std::vector<OutlinedFunction> &FunctionList);
/// \brief Replace the sequences of instructions represented by the
/// \p Candidates in \p CandidateList with calls to \p MachineFunctions
@@ -820,7 +823,8 @@
/// \param CandidateList A list of candidates to be outlined.
/// \param FunctionList A list of functions to be inserted into the module.
/// \param Mapper Contains the instruction mappings for the module.
- bool outline(Module &M, const ArrayRef<Candidate> &CandidateList,
+ bool outline(Module &M,
+ const ArrayRef<std::shared_ptr<Candidate>> &CandidateList,
std::vector<OutlinedFunction> &FunctionList,
InstructionMapper &Mapper);
@@ -841,10 +845,11 @@
/// \param TII TargetInstrInfo for the module.
///
/// \returns The length of the longest candidate found. 0 if there are none.
- unsigned buildCandidateList(std::vector<Candidate> &CandidateList,
- std::vector<OutlinedFunction> &FunctionList,
- SuffixTree &ST, InstructionMapper &Mapper,
- const TargetInstrInfo &TII);
+ unsigned
+ buildCandidateList(std::vector<std::shared_ptr<Candidate>> &CandidateList,
+ std::vector<OutlinedFunction> &FunctionList,
+ SuffixTree &ST, InstructionMapper &Mapper,
+ const TargetInstrInfo &TII);
/// Helper function for pruneOverlaps.
/// Removes \p C from the candidate list, and updates its \p OutlinedFunction.
@@ -863,7 +868,7 @@
/// \param Mapper Contains instruction mapping info for outlining.
/// \param MaxCandidateLen The length of the longest candidate.
/// \param TII TargetInstrInfo for the module.
- void pruneOverlaps(std::vector<Candidate> &CandidateList,
+ void pruneOverlaps(std::vector<std::shared_ptr<Candidate>> &CandidateList,
std::vector<OutlinedFunction> &FunctionList,
InstructionMapper &Mapper, unsigned MaxCandidateLen,
const TargetInstrInfo &TII);
@@ -887,11 +892,10 @@
INITIALIZE_PASS(MachineOutliner, DEBUG_TYPE, "Machine Function Outliner", false,
false)
-unsigned
-MachineOutliner::findCandidates(SuffixTree &ST, const TargetInstrInfo &TII,
- InstructionMapper &Mapper,
- std::vector<Candidate> &CandidateList,
- std::vector<OutlinedFunction> &FunctionList) {
+unsigned MachineOutliner::findCandidates(
+ SuffixTree &ST, const TargetInstrInfo &TII, InstructionMapper &Mapper,
+ std::vector<std::shared_ptr<Candidate>> &CandidateList,
+ std::vector<OutlinedFunction> &FunctionList) {
CandidateList.clear();
FunctionList.clear();
unsigned MaxLen = 0;
@@ -1004,13 +1008,17 @@
// At this point, the candidate class is seen as beneficial. Set their
// benefit values and save them in the candidate list.
+ std::vector<std::shared_ptr<Candidate>> CandidatesForFn;
for (Candidate &C : CandidatesForRepeatedSeq) {
C.Benefit = Benefit;
C.MInfo = MInfo;
- CandidateList.push_back(C);
+ std::shared_ptr<Candidate> Cptr = std::make_shared<Candidate>(C);
+ CandidateList.push_back(Cptr);
+ CandidatesForFn.push_back(Cptr);
}
FunctionList.push_back(OF);
+ FunctionList.back().Candidates = CandidatesForFn;
// Move to the next function.
Parent.IsInTree = false;
@@ -1038,11 +1046,10 @@
<< "\n";);
}
-void MachineOutliner::pruneOverlaps(std::vector<Candidate> &CandidateList,
- std::vector<OutlinedFunction> &FunctionList,
- InstructionMapper &Mapper,
- unsigned MaxCandidateLen,
- const TargetInstrInfo &TII) {
+void MachineOutliner::pruneOverlaps(
+ std::vector<std::shared_ptr<Candidate>> &CandidateList,
+ std::vector<OutlinedFunction> &FunctionList, InstructionMapper &Mapper,
+ unsigned MaxCandidateLen, const TargetInstrInfo &TII) {
// Return true if this candidate became unbeneficial for outlining in a
// previous step.
@@ -1069,7 +1076,7 @@
// This is O(MaxCandidateLen * CandidateList.size()).
for (auto It = CandidateList.begin(), Et = CandidateList.end(); It != Et;
It++) {
- Candidate &C1 = *It;
+ Candidate &C1 = **It;
// If C1 was already pruned, or its function is no longer beneficial for
// outlining, move to the next candidate.
@@ -1088,7 +1095,7 @@
// FarthestPossibleIdx indices away from C1. There are at most
// MaxCandidateLen of these.
for (auto Sit = It + 1; Sit != Et; Sit++) {
- Candidate &C2 = *Sit;
+ Candidate &C2 = **Sit;
// Is this candidate too far away to overlap?
if (C2.getStartIdx() < FarthestPossibleIdx)
@@ -1130,11 +1137,10 @@
}
}
-unsigned
-MachineOutliner::buildCandidateList(std::vector<Candidate> &CandidateList,
- std::vector<OutlinedFunction> &FunctionList,
- SuffixTree &ST, InstructionMapper &Mapper,
- const TargetInstrInfo &TII) {
+unsigned MachineOutliner::buildCandidateList(
+ std::vector<std::shared_ptr<Candidate>> &CandidateList,
+ std::vector<OutlinedFunction> &FunctionList, SuffixTree &ST,
+ InstructionMapper &Mapper, const TargetInstrInfo &TII) {
std::vector<unsigned> CandidateSequence; // Current outlining candidate.
unsigned MaxCandidateLen = 0; // Length of the longest candidate.
@@ -1145,7 +1151,10 @@
// Sort the candidates in decending order. This will simplify the outlining
// process when we have to remove the candidates from the mapping by
// allowing us to cut them out without keeping track of an offset.
- std::stable_sort(CandidateList.begin(), CandidateList.end());
+ std::stable_sort(
+ CandidateList.begin(), CandidateList.end(),
+ [](const std::shared_ptr<Candidate> &LHS,
+ const std::shared_ptr<Candidate> &RHS) { return *LHS < *RHS; });
return MaxCandidateLen;
}
@@ -1204,15 +1213,14 @@
return &MF;
}
-bool MachineOutliner::outline(Module &M,
- const ArrayRef<Candidate> &CandidateList,
- std::vector<OutlinedFunction> &FunctionList,
- InstructionMapper &Mapper) {
+bool MachineOutliner::outline(
+ Module &M, const ArrayRef<std::shared_ptr<Candidate>> &CandidateList,
+ std::vector<OutlinedFunction> &FunctionList, InstructionMapper &Mapper) {
bool OutlinedSomething = false;
// Replace the candidates with calls to their respective outlined functions.
- for (const Candidate &C : CandidateList) {
-
+ for (const std::shared_ptr<Candidate> &Cptr : CandidateList) {
+ Candidate &C = *Cptr;
// Was the candidate removed during pruneOverlaps?
if (!C.InCandidateList)
continue;
@@ -1240,6 +1248,37 @@
// Does this candidate have a function yet?
if (!OF.MF) {
OF.MF = createOutlinedFunction(M, OF, Mapper);
+ MachineBasicBlock *MBB = &*OF.MF->begin();
+
+ // Output a remark telling the user that an outlined function was created,
+ // and explaining where it came from.
+ MachineOptimizationRemarkEmitter MORE(*OF.MF, nullptr);
+ MachineOptimizationRemark R(DEBUG_TYPE, "OutlinedFunction",
+ MBB->findDebugLoc(MBB->begin()), MBB);
+ R << "Saved " << NV("OutliningBenefit", OF.getBenefit())
+ << " instructions by "
+ << "outlining " << NV("Length", OF.Sequence.size()) << " instructions "
+ << "from " << NV("NumOccurrences", OF.getOccurrenceCount())
+ << " locations. "
+ << "(Found at: ";
+
+ // Tell the user the other places the candidate was found.
+ for (size_t i = 0, e = OF.Candidates.size(); i < e; i++) {
+
+ // Skip over things that were pruned.
+ if (!OF.Candidates[i]->InCandidateList)
+ continue;
+
+ R << NV(
+ (Twine("StartLoc") + Twine(i)).str(),
+ Mapper.InstrList[OF.Candidates[i]->getStartIdx()]->getDebugLoc());
+ if (i != e - 1)
+ R << ", ";
+ }
+
+ R << ")";
+
+ MORE.emit(R);
FunctionsCreated++;
}
@@ -1300,7 +1339,7 @@
// Construct a suffix tree, use it to find candidates, and then outline them.
SuffixTree ST(Mapper.UnsignedVec);
- std::vector<Candidate> CandidateList;
+ std::vector<std::shared_ptr<Candidate>> CandidateList;
std::vector<OutlinedFunction> FunctionList;
// Find all of the outlining candidates.