Skip to content

Commit

Permalink
[MachineOutliner][NFC] Refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
kyulee-com committed Apr 26, 2024
1 parent d22358a commit 70b54f9
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 33 deletions.
5 changes: 3 additions & 2 deletions llvm/include/llvm/CodeGen/MachineOutliner.h
Original file line number Diff line number Diff line change
Expand Up @@ -234,11 +234,11 @@ struct OutlinedFunction {
unsigned FrameConstructionID = 0;

/// Return the number of candidates for this \p OutlinedFunction.
unsigned getOccurrenceCount() const { return Candidates.size(); }
virtual unsigned getOccurrenceCount() const { return Candidates.size(); }

/// Return the number of bytes it would take to outline this
/// function.
unsigned getOutliningCost() const {
virtual unsigned getOutliningCost() const {
unsigned CallOverhead = 0;
for (const Candidate &C : Candidates)
CallOverhead += C.getCallOverhead();
Expand Down Expand Up @@ -272,6 +272,7 @@ struct OutlinedFunction {
}

OutlinedFunction() = delete;
virtual ~OutlinedFunction() = default;
};
} // namespace outliner
} // namespace llvm
Expand Down
11 changes: 9 additions & 2 deletions llvm/include/llvm/CodeGen/TargetInstrInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -2053,13 +2053,20 @@ class TargetInstrInfo : public MCInstrInfo {

/// Returns a \p outliner::OutlinedFunction struct containing target-specific
/// information for a set of outlining candidates. Returns std::nullopt if the
/// candidates are not suitable for outlining.
/// candidates are not suitable for outlining. \p MinRep is the minimum
/// number of times the instruction sequence must be repeated.
virtual std::optional<outliner::OutlinedFunction> getOutliningCandidateInfo(
std::vector<outliner::Candidate> &RepeatedSequenceLocs) const {
std::vector<outliner::Candidate> &RepeatedSequenceLocs,
unsigned MipRep) const {
llvm_unreachable(
"Target didn't implement TargetInstrInfo::getOutliningCandidateInfo!");
}

virtual std::optional<outliner::OutlinedFunction> getOutliningCandidateInfo(
std::vector<outliner::Candidate> &RepeatedSequenceLocs) const {
return getOutliningCandidateInfo(RepeatedSequenceLocs, /*MipRep=*/2);
}

/// Optional target hook to create the LLVM IR attributes for the outlined
/// function. If overridden, the overriding function must call the default
/// implementation.
Expand Down
53 changes: 28 additions & 25 deletions llvm/lib/CodeGen/MachineOutliner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -446,16 +446,19 @@ struct MachineOutliner : public ModulePass {
/// \param Mapper Contains outlining mapping information.
/// \param[out] FunctionList Filled with a list of \p OutlinedFunctions
/// each type of candidate.
void findCandidates(InstructionMapper &Mapper,
std::vector<OutlinedFunction> &FunctionList);
void
findCandidates(InstructionMapper &Mapper,
std::vector<std::unique_ptr<OutlinedFunction>> &FunctionList);

/// Replace the sequences of instructions represented by \p OutlinedFunctions
/// with calls to functions.
///
/// \param M The module we are outlining from.
/// \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, std::vector<OutlinedFunction> &FunctionList,
/// \param[out] OutlinedFunctionNum The outlined function number.
bool outline(Module &M,
std::vector<std::unique_ptr<OutlinedFunction>> &FunctionList,
InstructionMapper &Mapper, unsigned &OutlinedFunctionNum);

/// Creates a function for \p OF and inserts it into the module.
Expand Down Expand Up @@ -574,7 +577,8 @@ void MachineOutliner::emitOutlinedFunctionRemark(OutlinedFunction &OF) {
}

void MachineOutliner::findCandidates(
InstructionMapper &Mapper, std::vector<OutlinedFunction> &FunctionList) {
InstructionMapper &Mapper,
std::vector<std::unique_ptr<OutlinedFunction>> &FunctionList) {
FunctionList.clear();
SuffixTree ST(Mapper.UnsignedVec);

Expand Down Expand Up @@ -674,7 +678,7 @@ void MachineOutliner::findCandidates(
continue;
}

FunctionList.push_back(*OF);
FunctionList.push_back(std::make_unique<OutlinedFunction>(*OF));
}
}

Expand Down Expand Up @@ -819,69 +823,68 @@ MachineFunction *MachineOutliner::createOutlinedFunction(
return &MF;
}

bool MachineOutliner::outline(Module &M,
std::vector<OutlinedFunction> &FunctionList,
InstructionMapper &Mapper,
unsigned &OutlinedFunctionNum) {
bool MachineOutliner::outline(
Module &M, std::vector<std::unique_ptr<OutlinedFunction>> &FunctionList,
InstructionMapper &Mapper, unsigned &OutlinedFunctionNum) {
LLVM_DEBUG(dbgs() << "*** Outlining ***\n");
LLVM_DEBUG(dbgs() << "NUMBER OF POTENTIAL FUNCTIONS: " << FunctionList.size()
<< "\n");
bool OutlinedSomething = false;

// Sort by benefit. The most beneficial functions should be outlined first.
stable_sort(FunctionList,
[](const OutlinedFunction &LHS, const OutlinedFunction &RHS) {
return LHS.getBenefit() > RHS.getBenefit();
});
stable_sort(FunctionList, [](const std::unique_ptr<OutlinedFunction> &LHS,
const std::unique_ptr<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.
auto *UnsignedVecBegin = Mapper.UnsignedVec.begin();
LLVM_DEBUG(dbgs() << "WALKING FUNCTION LIST\n");
for (OutlinedFunction &OF : FunctionList) {
for (auto &OF : FunctionList) {
#ifndef NDEBUG
auto NumCandidatesBefore = OF.Candidates.size();
auto NumCandidatesBefore = OF->Candidates.size();
#endif
// If we outlined something that overlapped with a candidate in a previous
// step, then we can't outline from it.
erase_if(OF.Candidates, [&UnsignedVecBegin](Candidate &C) {
erase_if(OF->Candidates, [&UnsignedVecBegin](Candidate &C) {
return std::any_of(UnsignedVecBegin + C.getStartIdx(),
UnsignedVecBegin + C.getEndIdx() + 1, [](unsigned I) {
return I == static_cast<unsigned>(-1);
});
});

#ifndef NDEBUG
auto NumCandidatesAfter = OF.Candidates.size();
auto NumCandidatesAfter = OF->Candidates.size();
LLVM_DEBUG(dbgs() << "PRUNED: " << NumCandidatesBefore - NumCandidatesAfter
<< "/" << NumCandidatesBefore << " candidates\n");
#endif

// If we made it unbeneficial to outline this function, skip it.
if (OF.getBenefit() < OutlinerBenefitThreshold) {
LLVM_DEBUG(dbgs() << "SKIP: Expected benefit (" << OF.getBenefit()
if (OF->getBenefit() < OutlinerBenefitThreshold) {
LLVM_DEBUG(dbgs() << "SKIP: Expected benefit (" << OF->getBenefit()
<< " B) < threshold (" << OutlinerBenefitThreshold
<< " B)\n");
continue;
}

LLVM_DEBUG(dbgs() << "OUTLINE: Expected benefit (" << OF.getBenefit()
LLVM_DEBUG(dbgs() << "OUTLINE: Expected benefit (" << OF->getBenefit()
<< " B) > threshold (" << OutlinerBenefitThreshold
<< " B)\n");

// It's beneficial. Create the function and outline its sequence's
// occurrences.
OF.MF = createOutlinedFunction(M, OF, Mapper, OutlinedFunctionNum);
emitOutlinedFunctionRemark(OF);
OF->MF = createOutlinedFunction(M, *OF, Mapper, OutlinedFunctionNum);
emitOutlinedFunctionRemark(*OF);
FunctionsCreated++;
OutlinedFunctionNum++; // Created a function, move to the next name.
MachineFunction *MF = OF.MF;
MachineFunction *MF = OF->MF;
const TargetSubtargetInfo &STI = MF->getSubtarget();
const TargetInstrInfo &TII = *STI.getInstrInfo();

// Replace occurrences of the sequence with calls to the new function.
LLVM_DEBUG(dbgs() << "CREATE OUTLINED CALLS\n");
for (Candidate &C : OF.Candidates) {
for (Candidate &C : OF->Candidates) {
MachineBasicBlock &MBB = *C.getMBB();
MachineBasicBlock::iterator StartIt = C.begin();
MachineBasicBlock::iterator EndIt = std::prev(C.end());
Expand Down Expand Up @@ -1173,7 +1176,7 @@ bool MachineOutliner::doOutline(Module &M, unsigned &OutlinedFunctionNum) {

// Prepare instruction mappings for the suffix tree.
populateMapper(Mapper, M, MMI);
std::vector<OutlinedFunction> FunctionList;
std::vector<std::unique_ptr<OutlinedFunction>> FunctionList;

// Find all of the outlining candidates.
findCandidates(Mapper, FunctionList);
Expand Down
7 changes: 4 additions & 3 deletions llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8240,7 +8240,8 @@ static bool outliningCandidatesV8_3OpsConsensus(const outliner::Candidate &a,

std::optional<outliner::OutlinedFunction>
AArch64InstrInfo::getOutliningCandidateInfo(
std::vector<outliner::Candidate> &RepeatedSequenceLocs) const {
std::vector<outliner::Candidate> &RepeatedSequenceLocs,
unsigned MinRep) const {
outliner::Candidate &FirstCand = RepeatedSequenceLocs[0];

unsigned SequenceSize = 0;
Expand Down Expand Up @@ -8354,7 +8355,7 @@ AArch64InstrInfo::getOutliningCandidateInfo(
llvm::erase_if(RepeatedSequenceLocs, hasIllegalSPModification);

// If the sequence doesn't have enough candidates left, then we're done.
if (RepeatedSequenceLocs.size() < 2)
if (RepeatedSequenceLocs.size() < MinRep)
return std::nullopt;
}

Expand Down Expand Up @@ -8598,7 +8599,7 @@ AArch64InstrInfo::getOutliningCandidateInfo(
}

// If we dropped all of the candidates, bail out here.
if (RepeatedSequenceLocs.size() < 2) {
if (RepeatedSequenceLocs.size() < MinRep) {
RepeatedSequenceLocs.clear();
return std::nullopt;
}
Expand Down
3 changes: 2 additions & 1 deletion llvm/lib/Target/AArch64/AArch64InstrInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -463,7 +463,8 @@ class AArch64InstrInfo final : public AArch64GenInstrInfo {
bool isFunctionSafeToOutlineFrom(MachineFunction &MF,
bool OutlineFromLinkOnceODRs) const override;
std::optional<outliner::OutlinedFunction> getOutliningCandidateInfo(
std::vector<outliner::Candidate> &RepeatedSequenceLocs) const override;
std::vector<outliner::Candidate> &RepeatedSequenceLocs,
unsigned MinRep) const override;
void mergeOutliningCandidateAttributes(
Function &F, std::vector<outliner::Candidate> &Candidates) const override;
outliner::InstrType
Expand Down

0 comments on commit 70b54f9

Please sign in to comment.