Skip to content

Commit f4cd61c

Browse files
committed
[TableGen] Add MacroFusions to SchedMachineModel
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.
1 parent 3787fed commit f4cd61c

9 files changed

+133
-1
lines changed

llvm/include/llvm/CodeGen/TargetSubtargetInfo.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "llvm/ADT/ArrayRef.h"
1717
#include "llvm/ADT/SmallVector.h"
1818
#include "llvm/ADT/StringRef.h"
19+
#include "llvm/CodeGen/MacroFusion.h"
1920
#include "llvm/CodeGen/PBQPRAConstraint.h"
2021
#include "llvm/CodeGen/SchedulerRegistry.h"
2122
#include "llvm/IR/GlobalValue.h"
@@ -323,6 +324,9 @@ class TargetSubtargetInfo : public MCSubtargetInfo {
323324
/// helps removing redundant copies generated by register allocator when
324325
/// handling complex eviction chains.
325326
virtual bool enableSpillageCopyElimination() const { return false; }
327+
328+
/// Get the list of MacroFusion predicates.
329+
virtual std::vector<MacroFusionPredTy> getMacroFusions() const { return {}; }
326330
};
327331

328332
} // end namespace llvm

llvm/include/llvm/MC/MCSchedule.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#ifndef LLVM_MC_MCSCHEDULE_H
1515
#define LLVM_MC_MCSCHEDULE_H
1616

17+
#include "llvm/ADT/Bitset.h"
1718
#include "llvm/Config/llvm-config.h"
1819
#include "llvm/Support/DataTypes.h"
1920
#include <cassert>
@@ -196,6 +197,9 @@ struct MCExtraProcessorInfo {
196197
unsigned StoreQueueID;
197198
};
198199

200+
const unsigned MaxMacroFusions = 256;
201+
using MacroFusionBitset = Bitset<MaxMacroFusions>;
202+
199203
/// Machine model for scheduling, bundling, and heuristics.
200204
///
201205
/// The machine model directly provides basic information about the
@@ -325,9 +329,14 @@ struct MCSchedModel {
325329
const InstrItinerary *InstrItineraries;
326330

327331
const MCExtraProcessorInfo *ExtraProcessorInfo;
332+
const MacroFusionBitset *MacroFusionBits;
328333

329334
bool hasExtraProcessorInfo() const { return ExtraProcessorInfo; }
330335

336+
const MacroFusionBitset *getMacroFusionBits() const {
337+
return MacroFusionBits;
338+
}
339+
331340
unsigned getProcessorID() const { return ProcID; }
332341

333342
/// Does this machine model include instruction-level scheduling.

llvm/include/llvm/MC/MCSubtargetInfo.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,12 @@ class MCSubtargetInfo {
120120
return FeatureBits[Feature];
121121
}
122122

123+
bool hasMacroFusion(unsigned MacroFusion) const {
124+
const MacroFusionBitset *MacroFusionBits =
125+
CPUSchedModel->getMacroFusionBits();
126+
return MacroFusionBits && MacroFusionBits->test(MacroFusion);
127+
}
128+
123129
protected:
124130
/// Initialize the scheduling model and feature bits.
125131
///
@@ -295,6 +301,13 @@ class MCSubtargetInfo {
295301

296302
/// \return if target want to issue a prefetch in address space \p AS.
297303
virtual bool shouldPrefetchAddressSpace(unsigned AS) const;
304+
305+
/// Enable macro fusion for this subtarget.
306+
virtual bool enableMacroFusion() const {
307+
const MacroFusionBitset *MacroFusionBits =
308+
CPUSchedModel->getMacroFusionBits();
309+
return MacroFusionBits && MacroFusionBits->any();
310+
}
298311
};
299312

300313
} // end namespace llvm

llvm/include/llvm/Target/TargetSchedule.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
include "llvm/Target/TargetItinerary.td"
5454

5555
class Predicate; // Forward def
56+
class Fusion;
5657

5758
// DAG operator that interprets the DAG args as Instruction defs.
5859
def instrs;
@@ -122,6 +123,9 @@ class SchedMachineModel {
122123
// using intervals via ResourceSegments (see
123124
// llvm/include/llvm/CodeGen/MachineScheduler.h).
124125
bit EnableIntervals = false;
126+
127+
// List of Fusion.
128+
list<Fusion> MacroFusions = [];
125129
}
126130

127131
def NoSchedModel : SchedMachineModel {

llvm/lib/MC/MCSchedule.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ const MCSchedModel MCSchedModel::Default = {DefaultIssueWidth,
3737
0,
3838
0,
3939
nullptr,
40+
nullptr,
4041
nullptr};
4142

4243
int MCSchedModel::computeInstrLatency(const MCSubtargetInfo &STI,

llvm/utils/TableGen/CodeGenSchedule.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,9 @@ CodeGenSchedModels::CodeGenSchedModels(RecordKeeper &RK,
226226
// (For per-operand resources mapped to itinerary classes).
227227
collectProcUnsupportedFeatures();
228228

229+
// Find MacroFusion records for each processor.
230+
collectMacroFusions();
231+
229232
// Infer new SchedClasses from SchedVariant.
230233
inferSchedClasses();
231234

@@ -1168,6 +1171,12 @@ bool CodeGenSchedModels::hasItineraries() const {
11681171
return false;
11691172
}
11701173

1174+
bool CodeGenSchedModels::hasMacroFusions() const {
1175+
return llvm::any_of(ProcModels, [](const CodeGenProcModel &PM) {
1176+
return PM.hasMacroFusions();
1177+
});
1178+
}
1179+
11711180
// Gather the processor itineraries.
11721181
void CodeGenSchedModels::collectProcItins() {
11731182
LLVM_DEBUG(dbgs() << "\n+++ PROBLEM ITINERARIES (collectProcItins) +++\n");
@@ -1238,6 +1247,12 @@ void CodeGenSchedModels::collectProcUnsupportedFeatures() {
12381247
ProcModel.ModelDef->getValueAsListOfDefs("UnsupportedFeatures"));
12391248
}
12401249

1250+
void CodeGenSchedModels::collectMacroFusions() {
1251+
for (CodeGenProcModel &ProcModel : ProcModels)
1252+
append_range(ProcModel.MacroFusions,
1253+
ProcModel.ModelDef->getValueAsListOfDefs("MacroFusions"));
1254+
}
1255+
12411256
/// Infer new classes from existing classes. In the process, this may create new
12421257
/// SchedWrites from sequences of existing SchedWrites.
12431258
void CodeGenSchedModels::inferSchedClasses() {

llvm/utils/TableGen/CodeGenSchedule.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,10 @@ struct CodeGenProcModel {
238238
// This list is empty if the Processor has no UnsupportedFeatures.
239239
RecVec UnsupportedFeaturesDefs;
240240

241+
// List of MacroFusion.
242+
// This list is empty if the Processor has no MacroFusion.
243+
RecVec MacroFusions;
244+
241245
// All read/write resources associated with this processor.
242246
RecVec WriteResDefs;
243247
RecVec ReadAdvanceDefs;
@@ -260,6 +264,8 @@ struct CodeGenProcModel {
260264
Index(Idx), ModelName(std::move(Name)), ModelDef(MDef), ItinsDef(IDef),
261265
RetireControlUnit(nullptr), LoadQueue(nullptr), StoreQueue(nullptr) {}
262266

267+
bool hasMacroFusions() const { return !MacroFusions.empty(); }
268+
263269
bool hasItineraries() const {
264270
return !ItinsDef->getValueAsListOfDefs("IID").empty();
265271
}
@@ -508,6 +514,9 @@ class CodeGenSchedModels {
508514
// Return true if any processors have itineraries.
509515
bool hasItineraries() const;
510516

517+
// Return true if any processors have MacroFusions.
518+
bool hasMacroFusions() const;
519+
511520
// Get a SchedWrite from its index.
512521
const CodeGenSchedRW &getSchedWrite(unsigned Idx) const {
513522
assert(Idx < SchedWrites.size() && "bad SchedWrite index");
@@ -610,6 +619,8 @@ class CodeGenSchedModels {
610619

611620
void collectProcUnsupportedFeatures();
612621

622+
void collectMacroFusions();
623+
613624
void inferSchedClasses();
614625

615626
void checkMCInstPredicates() const;

llvm/utils/TableGen/MacroFusionPredicatorEmitter.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ class MacroFusionPredicatorEmitter {
3030
RecordKeeper &Records;
3131
CodeGenTarget Target;
3232

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

55+
void MacroFusionPredicatorEmitter::emitMacroFusionEnum(
56+
std::vector<Record *> Fusions, PredicateExpander &PE, raw_ostream &OS) {
57+
unsigned N = Fusions.size();
58+
if (N == 0)
59+
return;
60+
// 256 is `MaxMacroFusions` defined in MCSchedule.h
61+
if (N > 256)
62+
PrintFatalError("Too many macro fusions! Please bump MaxMacroFusions!");
63+
64+
OS << "#ifdef GET_MACRO_FUSION_ENUM\n\n";
65+
OS << "namespace llvm {\n";
66+
OS << "namespace " << Target.getName() << " {\n";
67+
OS << "enum {\n";
68+
69+
for (unsigned Index = 0; Index < N; Index++) {
70+
Record *Fusion = Fusions[Index];
71+
// Get and emit name
72+
OS << " " << Fusion->getName() << " = " << Index << ",\n";
73+
}
74+
75+
OS << "};\n";
76+
OS << "} // end namespace " << Target.getName() << "\n";
77+
OS << "} // end namespace llvm\n\n";
78+
OS << "#endif\n";
79+
OS << "#undef GET_MACRO_FUSION_ENUM\n\n";
80+
}
81+
5382
void MacroFusionPredicatorEmitter::emitMacroFusionDecl(
5483
std::vector<Record *> Fusions, PredicateExpander &PE, raw_ostream &OS) {
5584
OS << "#ifdef GET_" << Target.getName() << "_MACRO_FUSION_PRED_DECL\n\n";
@@ -196,6 +225,7 @@ void MacroFusionPredicatorEmitter::run(raw_ostream &OS) {
196225
std::vector<Record *> Fusions = Records.getAllDerivedDefinitions("Fusion");
197226
// Sort macro fusions by name.
198227
sort(Fusions, LessRecord());
228+
emitMacroFusionEnum(Fusions, PE, OS);
199229
emitMacroFusionDecl(Fusions, PE, OS);
200230
emitMacroFusionImpl(Fusions, PE, OS);
201231
}

llvm/utils/TableGen/SubtargetEmitter.cpp

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,8 @@ class SubtargetEmitter {
133133
void EmitMCInstrAnalysisPredicateFunctions(raw_ostream &OS);
134134

135135
void EmitSchedModel(raw_ostream &OS);
136+
void emitMacroFusionBits(const CodeGenProcModel &ProcModel, raw_ostream &OS);
137+
void emitGetMacroFusions(const std::string &ClassName, raw_ostream &OS);
136138
void EmitHwModeCheck(const std::string &ClassName, raw_ostream &OS);
137139
void ParseFeaturesFunction(raw_ostream &OS);
138140

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

874+
void SubtargetEmitter::emitMacroFusionBits(const CodeGenProcModel &ProcModel,
875+
raw_ostream &OS) {
876+
OS << "\nstatic const MacroFusionBitset " << ProcModel.ModelName
877+
<< "MacroFusionBits = {\n";
878+
std::vector<std::string> Predicates;
879+
for (auto *R : ProcModel.MacroFusions)
880+
Predicates.push_back(" " + Target + "::" + R->getNameInitAsString());
881+
OS << llvm::join(Predicates, ",\n");
882+
OS << "\n};\n";
883+
}
884+
872885
// Find the WriteRes Record that defines processor resources for this
873886
// SchedWrite.
874887
Record *SubtargetEmitter::FindWriteResources(
@@ -1441,6 +1454,8 @@ void SubtargetEmitter::EmitProcessorModels(raw_ostream &OS) {
14411454
else if(!PM.ProcResourceDefs.empty())
14421455
PrintFatalError(PM.ModelDef->getLoc(), "SchedMachineModel defines "
14431456
"ProcResources without defining WriteRes SchedWriteRes");
1457+
if (PM.hasMacroFusions())
1458+
emitMacroFusionBits(PM, OS);
14441459

14451460
// Begin processor itinerary properties
14461461
OS << "\n";
@@ -1487,7 +1502,11 @@ void SubtargetEmitter::EmitProcessorModels(raw_ostream &OS) {
14871502
if (PM.hasExtraProcessorInfo())
14881503
OS << " &" << PM.ModelName << "ExtraInfo,\n";
14891504
else
1490-
OS << " nullptr // No extra processor descriptor\n";
1505+
OS << " nullptr, // No extra processor descriptor\n";
1506+
if (PM.hasMacroFusions()) {
1507+
OS << " &" << PM.ModelName << "MacroFusionBits,\n";
1508+
} else
1509+
OS << " nullptr, // No macro fusions\n";
14911510
OS << "};\n";
14921511
}
14931512
}
@@ -1770,6 +1789,27 @@ void SubtargetEmitter::EmitSchedModelHelpers(const std::string &ClassName,
17701789
PE.expandSTIPredicate(OS, Fn);
17711790
}
17721791

1792+
void SubtargetEmitter::emitGetMacroFusions(const std::string &ClassName,
1793+
raw_ostream &OS) {
1794+
OS << "std::vector<MacroFusionPredTy> " << ClassName
1795+
<< "::getMacroFusions() const {\n";
1796+
OS.indent(2) << "switch(getSchedModel().getProcessorID()) {\n";
1797+
for (auto &Proc : TGT.getSchedModels().procModels()) {
1798+
if (Proc.hasMacroFusions()) {
1799+
OS.indent(4) << "case " << Proc.Index << ": // " << Proc.ModelName
1800+
<< "\n";
1801+
OS.indent(4) << " return {";
1802+
std::vector<std::string> Predicates;
1803+
for (auto *R : Proc.MacroFusions)
1804+
Predicates.push_back("is" + R->getNameInitAsString());
1805+
OS << llvm::join(Predicates, ", ");
1806+
OS << "};\n";
1807+
}
1808+
}
1809+
OS.indent(2) << "}\n";
1810+
OS.indent(2) << "return {};\n}\n";
1811+
}
1812+
17731813
void SubtargetEmitter::EmitHwModeCheck(const std::string &ClassName,
17741814
raw_ostream &OS) {
17751815
const CodeGenHwModes &CGH = TGT.getHwModes();
@@ -1987,6 +2027,9 @@ void SubtargetEmitter::run(raw_ostream &OS) {
19872027
<< " const;\n";
19882028
if (TGT.getHwModes().getNumModeIds() > 1)
19892029
OS << " unsigned getHwMode() const override;\n";
2030+
if (TGT.getSchedModels().hasMacroFusions())
2031+
OS << " std::vector<MacroFusionPredTy> getMacroFusions() const "
2032+
"override;\n";
19902033

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

20452088
EmitSchedModelHelpers(ClassName, OS);
20462089
EmitHwModeCheck(ClassName, OS);
2090+
if (TGT.getSchedModels().hasMacroFusions())
2091+
emitGetMacroFusions(ClassName, OS);
20472092

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

0 commit comments

Comments
 (0)