aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/CodeGen/MachineOutliner.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/CodeGen/MachineOutliner.cpp')
-rw-r--r--llvm/lib/CodeGen/MachineOutliner.cpp131
1 files changed, 68 insertions, 63 deletions
diff --git a/llvm/lib/CodeGen/MachineOutliner.cpp b/llvm/lib/CodeGen/MachineOutliner.cpp
index 5e3ebf1..f1cb2e3 100644
--- a/llvm/lib/CodeGen/MachineOutliner.cpp
+++ b/llvm/lib/CodeGen/MachineOutliner.cpp
@@ -1414,78 +1414,83 @@ bool MachineOutliner::outline(
// Number to append to the current outlined function.
unsigned OutlinedFunctionNum = 0;
- // Replace the candidates with calls to their respective outlined functions.
- for (const std::shared_ptr<Candidate> &Cptr : CandidateList) {
- Candidate &C = *Cptr;
- // Was the candidate removed during pruneOverlaps?
- if (!C.InCandidateList)
- continue;
-
- // If not, then look at its OutlinedFunction.
- OutlinedFunction &OF = FunctionList[C.FunctionIdx];
-
- // Was its OutlinedFunction made unbeneficial during pruneOverlaps?
+ // Sort by benefit. The most beneficial functions should be outlined first.
+ std::stable_sort(
+ FunctionList.begin(), FunctionList.end(),
+ [](const OutlinedFunction &LHS, const OutlinedFunction &RHS) {
+ return LHS.getBenefit() > RHS.getBenefit();
+ });
+
+ // Walk over each function, outlining them as we go along. Functions are
+ // outlined greedily, based off the sort above.
+ for (OutlinedFunction &OF : FunctionList) {
+ // If we outlined something that overlapped with a candidate in a previous
+ // step, then we can't outline from it.
+ erase_if(OF.Candidates,
+ [](std::shared_ptr<Candidate> &C) { return !C->InCandidateList; });
+
+ // If we made it unbeneficial to outline this function, skip it.
if (OF.getBenefit() < 1)
continue;
- // Does this candidate have a function yet?
- if (!OF.MF) {
- OF.MF = createOutlinedFunction(M, OF, Mapper, OutlinedFunctionNum);
- emitOutlinedFunctionRemark(OF);
- FunctionsCreated++;
- OutlinedFunctionNum++; // Created a function, move to the next name.
- }
-
+ // It's beneficial. Create the function and outline its sequence's
+ // occurrences.
+ OF.MF = createOutlinedFunction(M, OF, Mapper, OutlinedFunctionNum);
+ emitOutlinedFunctionRemark(OF);
+ FunctionsCreated++;
+ OutlinedFunctionNum++; // Created a function, move to the next name.
MachineFunction *MF = OF.MF;
- MachineBasicBlock &MBB = *C.getMBB();
- MachineBasicBlock::iterator StartIt = C.front();
- MachineBasicBlock::iterator EndIt = C.back();
- assert(StartIt != C.getMBB()->end() && "StartIt out of bounds!");
- assert(EndIt != C.getMBB()->end() && "EndIt out of bounds!");
-
const TargetSubtargetInfo &STI = MF->getSubtarget();
const TargetInstrInfo &TII = *STI.getInstrInfo();
- // Insert a call to the new function and erase the old sequence.
- auto CallInst = TII.insertOutlinedCall(M, MBB, StartIt, *OF.MF, C);
-
- // If the caller tracks liveness, then we need to make sure that anything
- // we outline doesn't break liveness assumptions.
- // The outlined functions themselves currently don't track liveness, but
- // we should make sure that the ranges we yank things out of aren't
- // wrong.
- if (MBB.getParent()->getProperties().hasProperty(
- MachineFunctionProperties::Property::TracksLiveness)) {
- // Helper lambda for adding implicit def operands to the call instruction.
- auto CopyDefs = [&CallInst](MachineInstr &MI) {
- for (MachineOperand &MOP : MI.operands()) {
- // Skip over anything that isn't a register.
- if (!MOP.isReg())
- continue;
-
- // If it's a def, add it to the call instruction.
- if (MOP.isDef())
- CallInst->addOperand(
- MachineOperand::CreateReg(MOP.getReg(), true, /* isDef = true */
- true /* isImp = true */));
- }
- };
-
- // Copy over the defs in the outlined range.
- // First inst in outlined range <-- Anything that's defined in this
- // ... .. range has to be added as an implicit
- // Last inst in outlined range <-- def to the call instruction.
- std::for_each(CallInst, std::next(EndIt), CopyDefs);
- }
+ // Replace occurrences of the sequence with calls to the new function.
+ for (std::shared_ptr<Candidate> &Cptr : OF.Candidates) {
+ Candidate &C = *Cptr;
+ MachineBasicBlock &MBB = *C.getMBB();
+ MachineBasicBlock::iterator StartIt = C.front();
+ MachineBasicBlock::iterator EndIt = C.back();
+
+ // Insert the call.
+ auto CallInst = TII.insertOutlinedCall(M, MBB, StartIt, *MF, C);
+
+ // If the caller tracks liveness, then we need to make sure that
+ // anything we outline doesn't break liveness assumptions. The outlined
+ // functions themselves currently don't track liveness, but we should
+ // make sure that the ranges we yank things out of aren't wrong.
+ if (MBB.getParent()->getProperties().hasProperty(
+ MachineFunctionProperties::Property::TracksLiveness)) {
+ // Helper lambda for adding implicit def operands to the call
+ // instruction.
+ auto CopyDefs = [&CallInst](MachineInstr &MI) {
+ for (MachineOperand &MOP : MI.operands()) {
+ // Skip over anything that isn't a register.
+ if (!MOP.isReg())
+ continue;
+
+ // If it's a def, add it to the call instruction.
+ if (MOP.isDef())
+ CallInst->addOperand(MachineOperand::CreateReg(
+ MOP.getReg(), true, /* isDef = true */
+ true /* isImp = true */));
+ }
+ };
+ // Copy over the defs in the outlined range.
+ // First inst in outlined range <-- Anything that's defined in this
+ // ... .. range has to be added as an
+ // implicit Last inst in outlined range <-- def to the call
+ // instruction.
+ std::for_each(CallInst, std::next(EndIt), CopyDefs);
+ }
- // Erase from the point after where the call was inserted up to, and
- // including, the final instruction in the sequence.
- // Erase needs one past the end, so we need std::next there too.
- MBB.erase(std::next(StartIt), std::next(EndIt));
- OutlinedSomething = true;
+ // Erase from the point after where the call was inserted up to, and
+ // including, the final instruction in the sequence.
+ // Erase needs one past the end, so we need std::next there too.
+ MBB.erase(std::next(StartIt), std::next(EndIt));
+ OutlinedSomething = true;
- // Statistics.
- NumOutlined++;
+ // Statistics.
+ NumOutlined++;
+ }
}
LLVM_DEBUG(dbgs() << "OutlinedSomething = " << OutlinedSomething << "\n";);