Skip to content

Commit

Permalink
[TableGen] Add MacroFusions to SchedMachineModel
Browse files Browse the repository at this point in the history
A list of `MacroFusion` is added to `SchedMachineModel` to indicate
supported macro fusions of this processor model.

For visibility, C++ enums of all MacroFusion are generated and new
`hasMacroFusion` is added to Subtarget to test if a MacroFusion is
supported.
  • Loading branch information
wangpc-pp committed Nov 21, 2023
1 parent 3787fed commit f4cd61c
Show file tree
Hide file tree
Showing 9 changed files with 133 additions and 1 deletion.
4 changes: 4 additions & 0 deletions llvm/include/llvm/CodeGen/TargetSubtargetInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/CodeGen/MacroFusion.h"
#include "llvm/CodeGen/PBQPRAConstraint.h"
#include "llvm/CodeGen/SchedulerRegistry.h"
#include "llvm/IR/GlobalValue.h"
Expand Down Expand Up @@ -323,6 +324,9 @@ class TargetSubtargetInfo : public MCSubtargetInfo {
/// helps removing redundant copies generated by register allocator when
/// handling complex eviction chains.
virtual bool enableSpillageCopyElimination() const { return false; }

/// Get the list of MacroFusion predicates.
virtual std::vector<MacroFusionPredTy> getMacroFusions() const { return {}; }
};

} // end namespace llvm
Expand Down
9 changes: 9 additions & 0 deletions llvm/include/llvm/MC/MCSchedule.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#ifndef LLVM_MC_MCSCHEDULE_H
#define LLVM_MC_MCSCHEDULE_H

#include "llvm/ADT/Bitset.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/Support/DataTypes.h"
#include <cassert>
Expand Down Expand Up @@ -196,6 +197,9 @@ struct MCExtraProcessorInfo {
unsigned StoreQueueID;
};

const unsigned MaxMacroFusions = 256;
using MacroFusionBitset = Bitset<MaxMacroFusions>;

/// Machine model for scheduling, bundling, and heuristics.
///
/// The machine model directly provides basic information about the
Expand Down Expand Up @@ -325,9 +329,14 @@ struct MCSchedModel {
const InstrItinerary *InstrItineraries;

const MCExtraProcessorInfo *ExtraProcessorInfo;
const MacroFusionBitset *MacroFusionBits;

bool hasExtraProcessorInfo() const { return ExtraProcessorInfo; }

const MacroFusionBitset *getMacroFusionBits() const {
return MacroFusionBits;
}

unsigned getProcessorID() const { return ProcID; }

/// Does this machine model include instruction-level scheduling.
Expand Down
13 changes: 13 additions & 0 deletions llvm/include/llvm/MC/MCSubtargetInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,12 @@ class MCSubtargetInfo {
return FeatureBits[Feature];
}

bool hasMacroFusion(unsigned MacroFusion) const {
const MacroFusionBitset *MacroFusionBits =
CPUSchedModel->getMacroFusionBits();
return MacroFusionBits && MacroFusionBits->test(MacroFusion);
}

protected:
/// Initialize the scheduling model and feature bits.
///
Expand Down Expand Up @@ -295,6 +301,13 @@ class MCSubtargetInfo {

/// \return if target want to issue a prefetch in address space \p AS.
virtual bool shouldPrefetchAddressSpace(unsigned AS) const;

/// Enable macro fusion for this subtarget.
virtual bool enableMacroFusion() const {
const MacroFusionBitset *MacroFusionBits =
CPUSchedModel->getMacroFusionBits();
return MacroFusionBits && MacroFusionBits->any();
}
};

} // end namespace llvm
Expand Down
4 changes: 4 additions & 0 deletions llvm/include/llvm/Target/TargetSchedule.td
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
include "llvm/Target/TargetItinerary.td"

class Predicate; // Forward def
class Fusion;

// DAG operator that interprets the DAG args as Instruction defs.
def instrs;
Expand Down Expand Up @@ -122,6 +123,9 @@ class SchedMachineModel {
// using intervals via ResourceSegments (see
// llvm/include/llvm/CodeGen/MachineScheduler.h).
bit EnableIntervals = false;

// List of Fusion.
list<Fusion> MacroFusions = [];
}

def NoSchedModel : SchedMachineModel {
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/MC/MCSchedule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ const MCSchedModel MCSchedModel::Default = {DefaultIssueWidth,
0,
0,
nullptr,
nullptr,
nullptr};

int MCSchedModel::computeInstrLatency(const MCSubtargetInfo &STI,
Expand Down
15 changes: 15 additions & 0 deletions llvm/utils/TableGen/CodeGenSchedule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,9 @@ CodeGenSchedModels::CodeGenSchedModels(RecordKeeper &RK,
// (For per-operand resources mapped to itinerary classes).
collectProcUnsupportedFeatures();

// Find MacroFusion records for each processor.
collectMacroFusions();

// Infer new SchedClasses from SchedVariant.
inferSchedClasses();

Expand Down Expand Up @@ -1168,6 +1171,12 @@ bool CodeGenSchedModels::hasItineraries() const {
return false;
}

bool CodeGenSchedModels::hasMacroFusions() const {
return llvm::any_of(ProcModels, [](const CodeGenProcModel &PM) {
return PM.hasMacroFusions();
});
}

// Gather the processor itineraries.
void CodeGenSchedModels::collectProcItins() {
LLVM_DEBUG(dbgs() << "\n+++ PROBLEM ITINERARIES (collectProcItins) +++\n");
Expand Down Expand Up @@ -1238,6 +1247,12 @@ void CodeGenSchedModels::collectProcUnsupportedFeatures() {
ProcModel.ModelDef->getValueAsListOfDefs("UnsupportedFeatures"));
}

void CodeGenSchedModels::collectMacroFusions() {
for (CodeGenProcModel &ProcModel : ProcModels)
append_range(ProcModel.MacroFusions,
ProcModel.ModelDef->getValueAsListOfDefs("MacroFusions"));
}

/// Infer new classes from existing classes. In the process, this may create new
/// SchedWrites from sequences of existing SchedWrites.
void CodeGenSchedModels::inferSchedClasses() {
Expand Down
11 changes: 11 additions & 0 deletions llvm/utils/TableGen/CodeGenSchedule.h
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,10 @@ struct CodeGenProcModel {
// This list is empty if the Processor has no UnsupportedFeatures.
RecVec UnsupportedFeaturesDefs;

// List of MacroFusion.
// This list is empty if the Processor has no MacroFusion.
RecVec MacroFusions;

// All read/write resources associated with this processor.
RecVec WriteResDefs;
RecVec ReadAdvanceDefs;
Expand All @@ -260,6 +264,8 @@ struct CodeGenProcModel {
Index(Idx), ModelName(std::move(Name)), ModelDef(MDef), ItinsDef(IDef),
RetireControlUnit(nullptr), LoadQueue(nullptr), StoreQueue(nullptr) {}

bool hasMacroFusions() const { return !MacroFusions.empty(); }

bool hasItineraries() const {
return !ItinsDef->getValueAsListOfDefs("IID").empty();
}
Expand Down Expand Up @@ -508,6 +514,9 @@ class CodeGenSchedModels {
// Return true if any processors have itineraries.
bool hasItineraries() const;

// Return true if any processors have MacroFusions.
bool hasMacroFusions() const;

// Get a SchedWrite from its index.
const CodeGenSchedRW &getSchedWrite(unsigned Idx) const {
assert(Idx < SchedWrites.size() && "bad SchedWrite index");
Expand Down Expand Up @@ -610,6 +619,8 @@ class CodeGenSchedModels {

void collectProcUnsupportedFeatures();

void collectMacroFusions();

void inferSchedClasses();

void checkMCInstPredicates() const;
Expand Down
30 changes: 30 additions & 0 deletions llvm/utils/TableGen/MacroFusionPredicatorEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ class MacroFusionPredicatorEmitter {
RecordKeeper &Records;
CodeGenTarget Target;

void emitMacroFusionEnum(std::vector<Record *> Fusions, PredicateExpander &PE,
raw_ostream &OS);
void emitMacroFusionDecl(std::vector<Record *> Fusions, PredicateExpander &PE,
raw_ostream &OS);
void emitMacroFusionImpl(std::vector<Record *> Fusions, PredicateExpander &PE,
Expand All @@ -50,6 +52,33 @@ class MacroFusionPredicatorEmitter {
};
} // End anonymous namespace.

void MacroFusionPredicatorEmitter::emitMacroFusionEnum(
std::vector<Record *> Fusions, PredicateExpander &PE, raw_ostream &OS) {
unsigned N = Fusions.size();
if (N == 0)
return;
// 256 is `MaxMacroFusions` defined in MCSchedule.h
if (N > 256)
PrintFatalError("Too many macro fusions! Please bump MaxMacroFusions!");

OS << "#ifdef GET_MACRO_FUSION_ENUM\n\n";
OS << "namespace llvm {\n";
OS << "namespace " << Target.getName() << " {\n";
OS << "enum {\n";

for (unsigned Index = 0; Index < N; Index++) {
Record *Fusion = Fusions[Index];
// Get and emit name
OS << " " << Fusion->getName() << " = " << Index << ",\n";
}

OS << "};\n";
OS << "} // end namespace " << Target.getName() << "\n";
OS << "} // end namespace llvm\n\n";
OS << "#endif\n";
OS << "#undef GET_MACRO_FUSION_ENUM\n\n";
}

void MacroFusionPredicatorEmitter::emitMacroFusionDecl(
std::vector<Record *> Fusions, PredicateExpander &PE, raw_ostream &OS) {
OS << "#ifdef GET_" << Target.getName() << "_MACRO_FUSION_PRED_DECL\n\n";
Expand Down Expand Up @@ -196,6 +225,7 @@ void MacroFusionPredicatorEmitter::run(raw_ostream &OS) {
std::vector<Record *> Fusions = Records.getAllDerivedDefinitions("Fusion");
// Sort macro fusions by name.
sort(Fusions, LessRecord());
emitMacroFusionEnum(Fusions, PE, OS);
emitMacroFusionDecl(Fusions, PE, OS);
emitMacroFusionImpl(Fusions, PE, OS);
}
Expand Down
47 changes: 46 additions & 1 deletion llvm/utils/TableGen/SubtargetEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@ class SubtargetEmitter {
void EmitMCInstrAnalysisPredicateFunctions(raw_ostream &OS);

void EmitSchedModel(raw_ostream &OS);
void emitMacroFusionBits(const CodeGenProcModel &ProcModel, raw_ostream &OS);
void emitGetMacroFusions(const std::string &ClassName, raw_ostream &OS);
void EmitHwModeCheck(const std::string &ClassName, raw_ostream &OS);
void ParseFeaturesFunction(raw_ostream &OS);

Expand Down Expand Up @@ -869,6 +871,17 @@ void SubtargetEmitter::EmitProcessorResources(const CodeGenProcModel &ProcModel,
OS << "};\n";
}

void SubtargetEmitter::emitMacroFusionBits(const CodeGenProcModel &ProcModel,
raw_ostream &OS) {
OS << "\nstatic const MacroFusionBitset " << ProcModel.ModelName
<< "MacroFusionBits = {\n";
std::vector<std::string> Predicates;
for (auto *R : ProcModel.MacroFusions)
Predicates.push_back(" " + Target + "::" + R->getNameInitAsString());
OS << llvm::join(Predicates, ",\n");
OS << "\n};\n";
}

// Find the WriteRes Record that defines processor resources for this
// SchedWrite.
Record *SubtargetEmitter::FindWriteResources(
Expand Down Expand Up @@ -1441,6 +1454,8 @@ void SubtargetEmitter::EmitProcessorModels(raw_ostream &OS) {
else if(!PM.ProcResourceDefs.empty())
PrintFatalError(PM.ModelDef->getLoc(), "SchedMachineModel defines "
"ProcResources without defining WriteRes SchedWriteRes");
if (PM.hasMacroFusions())
emitMacroFusionBits(PM, OS);

// Begin processor itinerary properties
OS << "\n";
Expand Down Expand Up @@ -1487,7 +1502,11 @@ void SubtargetEmitter::EmitProcessorModels(raw_ostream &OS) {
if (PM.hasExtraProcessorInfo())
OS << " &" << PM.ModelName << "ExtraInfo,\n";
else
OS << " nullptr // No extra processor descriptor\n";
OS << " nullptr, // No extra processor descriptor\n";
if (PM.hasMacroFusions()) {
OS << " &" << PM.ModelName << "MacroFusionBits,\n";
} else
OS << " nullptr, // No macro fusions\n";
OS << "};\n";
}
}
Expand Down Expand Up @@ -1770,6 +1789,27 @@ void SubtargetEmitter::EmitSchedModelHelpers(const std::string &ClassName,
PE.expandSTIPredicate(OS, Fn);
}

void SubtargetEmitter::emitGetMacroFusions(const std::string &ClassName,
raw_ostream &OS) {
OS << "std::vector<MacroFusionPredTy> " << ClassName
<< "::getMacroFusions() const {\n";
OS.indent(2) << "switch(getSchedModel().getProcessorID()) {\n";
for (auto &Proc : TGT.getSchedModels().procModels()) {
if (Proc.hasMacroFusions()) {
OS.indent(4) << "case " << Proc.Index << ": // " << Proc.ModelName
<< "\n";
OS.indent(4) << " return {";
std::vector<std::string> Predicates;
for (auto *R : Proc.MacroFusions)
Predicates.push_back("is" + R->getNameInitAsString());
OS << llvm::join(Predicates, ", ");
OS << "};\n";
}
}
OS.indent(2) << "}\n";
OS.indent(2) << "return {};\n}\n";
}

void SubtargetEmitter::EmitHwModeCheck(const std::string &ClassName,
raw_ostream &OS) {
const CodeGenHwModes &CGH = TGT.getHwModes();
Expand Down Expand Up @@ -1987,6 +2027,9 @@ void SubtargetEmitter::run(raw_ostream &OS) {
<< " const;\n";
if (TGT.getHwModes().getNumModeIds() > 1)
OS << " unsigned getHwMode() const override;\n";
if (TGT.getSchedModels().hasMacroFusions())
OS << " std::vector<MacroFusionPredTy> getMacroFusions() const "
"override;\n";

STIPredicateExpander PE(Target);
PE.setByRef(false);
Expand Down Expand Up @@ -2044,6 +2087,8 @@ void SubtargetEmitter::run(raw_ostream &OS) {

EmitSchedModelHelpers(ClassName, OS);
EmitHwModeCheck(ClassName, OS);
if (TGT.getSchedModels().hasMacroFusions())
emitGetMacroFusions(ClassName, OS);

OS << "} // end namespace llvm\n\n";

Expand Down

0 comments on commit f4cd61c

Please sign in to comment.