Skip to content

Commit 37484cf

Browse files
committed
[TableGen] Enhance testability of TableGen-based macro fusion
We add an option `-mfusion` like `-mattr` to add/remove supported macro fusions, so that we can test each macro fusion separately via `llc`. This PR is stacked on llvm#72219, llvm#72222, llvm#72223
1 parent f4cd61c commit 37484cf

File tree

7 files changed

+145
-58
lines changed

7 files changed

+145
-58
lines changed

llvm/include/llvm/CodeGen/TargetSubtargetInfo.h

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,21 +54,43 @@ class TargetRegisterInfo;
5454
class TargetSchedModel;
5555
class Triple;
5656

57+
//===----------------------------------------------------------------------===//
58+
59+
/// Used to provide information for macro fusion.
60+
struct MacroFusionEntry {
61+
const char *Name; ///< Name of macro fusion
62+
MacroFusionPredTy Pred; ///< Predicator function of macro fusion
63+
64+
/// Compare routine for std::lower_bound
65+
bool operator<(StringRef S) const { return StringRef(Name) < S; }
66+
67+
/// Compare routine for std::is_sorted.
68+
bool operator<(const MacroFusionEntry &Other) const {
69+
return StringRef(Name) < StringRef(Other.Name);
70+
}
71+
};
72+
5773
//===----------------------------------------------------------------------===//
5874
///
5975
/// TargetSubtargetInfo - Generic base class for all target subtargets. All
6076
/// Target-specific options that control code generation and printing should
6177
/// be exposed through a TargetSubtargetInfo-derived class.
6278
///
6379
class TargetSubtargetInfo : public MCSubtargetInfo {
80+
private:
81+
ArrayRef<MacroFusionEntry> MacroFusionTable;
82+
6483
protected: // Can only create subclasses...
6584
TargetSubtargetInfo(const Triple &TT, StringRef CPU, StringRef TuneCPU,
6685
StringRef FS, ArrayRef<SubtargetFeatureKV> PF,
6786
ArrayRef<SubtargetSubTypeKV> PD,
6887
const MCWriteProcResEntry *WPR,
6988
const MCWriteLatencyEntry *WL,
7089
const MCReadAdvanceEntry *RA, const InstrStage *IS,
71-
const unsigned *OC, const unsigned *FP);
90+
const unsigned *OC, const unsigned *FP,
91+
ArrayRef<MacroFusionEntry> MF);
92+
93+
void overrideFusionBits();
7294

7395
public:
7496
// AntiDepBreakMode - Type of anti-dependence breaking that should
@@ -326,7 +348,7 @@ class TargetSubtargetInfo : public MCSubtargetInfo {
326348
virtual bool enableSpillageCopyElimination() const { return false; }
327349

328350
/// Get the list of MacroFusion predicates.
329-
virtual std::vector<MacroFusionPredTy> getMacroFusions() const { return {}; }
351+
virtual std::vector<MacroFusionPredTy> getMacroFusions() const;
330352
};
331353

332354
} // end namespace llvm

llvm/include/llvm/MC/MCSubtargetInfo.h

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@ class MCSubtargetInfo {
9292
FeatureBitset FeatureBits; // Feature bits for current CPU + FS
9393
std::string FeatureString; // Feature string
9494

95+
MacroFusionBitset FusionBits; // Fusion bits
96+
9597
public:
9698
MCSubtargetInfo(const MCSubtargetInfo &) = default;
9799
MCSubtargetInfo(const Triple &TT, StringRef CPU, StringRef TuneCPU,
@@ -120,10 +122,13 @@ class MCSubtargetInfo {
120122
return FeatureBits[Feature];
121123
}
122124

125+
const MacroFusionBitset &getMacroFusionBits() const { return FusionBits; }
126+
void enableMacroFusion(unsigned MacroFusion) { FusionBits.set(MacroFusion); }
127+
void disableMacroFusion(unsigned MacroFusion) {
128+
FusionBits.reset(MacroFusion);
129+
}
123130
bool hasMacroFusion(unsigned MacroFusion) const {
124-
const MacroFusionBitset *MacroFusionBits =
125-
CPUSchedModel->getMacroFusionBits();
126-
return MacroFusionBits && MacroFusionBits->test(MacroFusion);
131+
return FusionBits.test(MacroFusion);
127132
}
128133

129134
protected:
@@ -303,11 +308,7 @@ class MCSubtargetInfo {
303308
virtual bool shouldPrefetchAddressSpace(unsigned AS) const;
304309

305310
/// Enable macro fusion for this subtarget.
306-
virtual bool enableMacroFusion() const {
307-
const MacroFusionBitset *MacroFusionBits =
308-
CPUSchedModel->getMacroFusionBits();
309-
return MacroFusionBits && MacroFusionBits->any();
310-
}
311+
virtual bool enableMacroFusion() const { return FusionBits.any(); }
311312
};
312313

313314
} // end namespace llvm

llvm/include/llvm/Target/TargetSchedule.td

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -662,7 +662,8 @@ def OneUse : OneUsePred;
662662
// return true;
663663
// }
664664
// ```
665-
class Fusion<list<FusionPredicate> predicates> {
665+
class Fusion<string name, list<FusionPredicate> predicates> {
666+
string Name = name;
666667
list<FusionPredicate> Predicates = predicates;
667668
}
668669

@@ -683,21 +684,21 @@ class Fusion<list<FusionPredicate> predicates> {
683684
// return true;
684685
// }
685686
// ```
686-
class SimpleFusion<MCInstPredicate firstPred, MCInstPredicate secondPred,
687+
class SimpleFusion<string name, MCInstPredicate firstPred, MCInstPredicate secondPred,
687688
list<FusionPredicate> prolog = [],
688689
list<FusionPredicate> epilog = []>
689-
: Fusion<!listconcat(
690-
prolog,
691-
[
692-
SecondFusionPredicateWithMCInstPredicate<secondPred>,
693-
WildcardTrue,
694-
FirstFusionPredicateWithMCInstPredicate<firstPred>,
695-
SecondFusionPredicateWithMCInstPredicate<
696-
CheckAny<[
697-
CheckIsVRegOperand<0>,
698-
CheckSameRegOperand<0, 1>
699-
]>>,
700-
OneUse,
701-
TieReg<0, 1>,
702-
],
703-
epilog)>;
690+
: Fusion<name, !listconcat(
691+
prolog,
692+
[
693+
SecondFusionPredicateWithMCInstPredicate<secondPred>,
694+
WildcardTrue,
695+
FirstFusionPredicateWithMCInstPredicate<firstPred>,
696+
SecondFusionPredicateWithMCInstPredicate<
697+
CheckAny<[
698+
CheckIsVRegOperand<0>,
699+
CheckSameRegOperand<0, 1>
700+
]>>,
701+
OneUse,
702+
TieReg<0, 1>,
703+
],
704+
epilog)>;

llvm/lib/CodeGen/TargetSubtargetInfo.cpp

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,62 @@
1414

1515
using namespace llvm;
1616

17+
static cl::list<std::string> MFusions("mfusion", cl::CommaSeparated,
18+
cl::desc("Target specific macro fusions"),
19+
cl::value_desc("a1,+a2,-a3,..."));
20+
1721
TargetSubtargetInfo::TargetSubtargetInfo(
1822
const Triple &TT, StringRef CPU, StringRef TuneCPU, StringRef FS,
1923
ArrayRef<SubtargetFeatureKV> PF, ArrayRef<SubtargetSubTypeKV> PD,
2024
const MCWriteProcResEntry *WPR, const MCWriteLatencyEntry *WL,
2125
const MCReadAdvanceEntry *RA, const InstrStage *IS, const unsigned *OC,
22-
const unsigned *FP)
23-
: MCSubtargetInfo(TT, CPU, TuneCPU, FS, PF, PD, WPR, WL, RA, IS, OC, FP) {}
26+
const unsigned *FP, ArrayRef<MacroFusionEntry> MF)
27+
: MCSubtargetInfo(TT, CPU, TuneCPU, FS, PF, PD, WPR, WL, RA, IS, OC, FP),
28+
MacroFusionTable(MF) {
29+
// assert if MacroFusionTable is not sorted.
30+
assert(llvm::is_sorted(MacroFusionTable));
31+
overrideFusionBits();
32+
}
2433

2534
TargetSubtargetInfo::~TargetSubtargetInfo() = default;
2635

36+
void TargetSubtargetInfo::overrideFusionBits() {
37+
if (MFusions.getNumOccurrences() != 0) {
38+
for (std::string &MFusion : MFusions) {
39+
char Prefix = MFusion[0];
40+
bool Disable = Prefix == '-';
41+
if (Prefix == '+' || Prefix == '-')
42+
MFusion = MFusion.substr(1);
43+
44+
// MacroFusionTable is sorted.
45+
const auto *Pos = std::lower_bound(
46+
MacroFusionTable.begin(), MacroFusionTable.end(), MFusion,
47+
[](const MacroFusionEntry &LHS, const std::string &RHS) {
48+
int CmpName = StringRef(LHS.Name).compare(RHS);
49+
if (CmpName < 0)
50+
return true;
51+
if (CmpName > 0)
52+
return false;
53+
return false;
54+
});
55+
56+
if (Pos == MacroFusionTable.end()) {
57+
errs() << "'" << MFusion
58+
<< "' is not a recognized macro fusion for this "
59+
<< "target (ignoring it)\n";
60+
continue;
61+
}
62+
63+
// The index is the same as the enum value.
64+
unsigned Idx = Pos - MacroFusionTable.begin();
65+
if (Disable)
66+
disableMacroFusion(Idx);
67+
else
68+
enableMacroFusion(Idx);
69+
}
70+
}
71+
}
72+
2773
bool TargetSubtargetInfo::enableAtomicExpand() const {
2874
return true;
2975
}
@@ -58,3 +104,13 @@ bool TargetSubtargetInfo::useAA() const {
58104
}
59105

60106
void TargetSubtargetInfo::mirFileLoaded(MachineFunction &MF) const { }
107+
108+
std::vector<MacroFusionPredTy> TargetSubtargetInfo::getMacroFusions() const {
109+
std::vector<MacroFusionPredTy> Fusions;
110+
const MacroFusionBitset &Bits = getMacroFusionBits();
111+
for (unsigned I = 0; I < MacroFusionTable.size(); I++)
112+
if (Bits[I])
113+
Fusions.push_back(MacroFusionTable[I].Pred);
114+
115+
return Fusions;
116+
}

llvm/lib/MC/MCSubtargetInfo.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,8 @@ void MCSubtargetInfo::InitMCProcessorInfo(StringRef CPU, StringRef TuneCPU,
215215
CPUSchedModel = &getSchedModelForCPU(TuneCPU);
216216
else
217217
CPUSchedModel = &MCSchedModel::GetDefaultSchedModel();
218+
if (CPUSchedModel->getMacroFusionBits())
219+
FusionBits = *CPUSchedModel->getMacroFusionBits();
218220
}
219221

220222
void MCSubtargetInfo::setDefaultFeatures(StringRef CPU, StringRef TuneCPU,

llvm/unittests/CodeGen/MFCommon.inc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ class BogusSubtarget : public TargetSubtargetInfo {
7676
public:
7777
BogusSubtarget(TargetMachine &TM)
7878
: TargetSubtargetInfo(Triple(""), "", "", "", {}, {}, nullptr, nullptr,
79-
nullptr, nullptr, nullptr, nullptr),
79+
nullptr, nullptr, nullptr, nullptr, {}),
8080
FL(), TL(TM) {}
8181
~BogusSubtarget() override {}
8282

llvm/utils/TableGen/SubtargetEmitter.cpp

Lines changed: 33 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "PredicateExpander.h"
1717
#include "llvm/ADT/STLExtras.h"
1818
#include "llvm/ADT/SmallPtrSet.h"
19+
#include "llvm/ADT/SmallSet.h"
1920
#include "llvm/ADT/StringExtras.h"
2021
#include "llvm/ADT/StringRef.h"
2122
#include "llvm/MC/MCInstrItineraries.h"
@@ -134,7 +135,7 @@ class SubtargetEmitter {
134135

135136
void EmitSchedModel(raw_ostream &OS);
136137
void emitMacroFusionBits(const CodeGenProcModel &ProcModel, raw_ostream &OS);
137-
void emitGetMacroFusions(const std::string &ClassName, raw_ostream &OS);
138+
void emitMacroFusionTable(RecVec Fusions, raw_ostream &OS);
138139
void EmitHwModeCheck(const std::string &ClassName, raw_ostream &OS);
139140
void ParseFeaturesFunction(raw_ostream &OS);
140141

@@ -1789,25 +1790,23 @@ void SubtargetEmitter::EmitSchedModelHelpers(const std::string &ClassName,
17891790
PE.expandSTIPredicate(OS, Fn);
17901791
}
17911792

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-
}
1793+
void SubtargetEmitter::emitMacroFusionTable(RecVec Fusions, raw_ostream &OS) {
1794+
OS << "const llvm::MacroFusionEntry " << Target << "MacroFusionTable[] = {\n";
1795+
1796+
SmallSet<StringRef, 32> Names;
1797+
for (auto &Fusion : Fusions) {
1798+
StringRef Name = Fusion->getValueAsString("Name");
1799+
if (Name.empty())
1800+
PrintFatalError(Fusion->getLoc(),
1801+
"The name of macro fusion cannot be empty");
1802+
if (Names.contains(Name))
1803+
PrintFatalError(Fusion->getLoc(),
1804+
"The name of macro fusion already exists");
1805+
OS.indent(2) << "{\"" << Name << "\", "
1806+
<< "llvm::is" + Fusion->getNameInitAsString() << "},\n";
18081807
}
1809-
OS.indent(2) << "}\n";
1810-
OS.indent(2) << "return {};\n}\n";
1808+
1809+
OS << "};\n\n";
18111810
}
18121811

18131812
void SubtargetEmitter::EmitHwModeCheck(const std::string &ClassName,
@@ -2027,9 +2026,6 @@ void SubtargetEmitter::run(raw_ostream &OS) {
20272026
<< " const;\n";
20282027
if (TGT.getHwModes().getNumModeIds() > 1)
20292028
OS << " unsigned getHwMode() const override;\n";
2030-
if (TGT.getSchedModels().hasMacroFusions())
2031-
OS << " std::vector<MacroFusionPredTy> getMacroFusions() const "
2032-
"override;\n";
20332029

20342030
STIPredicateExpander PE(Target);
20352031
PE.setByRef(false);
@@ -2044,6 +2040,13 @@ void SubtargetEmitter::run(raw_ostream &OS) {
20442040
OS << "\n#ifdef GET_SUBTARGETINFO_CTOR\n";
20452041
OS << "#undef GET_SUBTARGETINFO_CTOR\n\n";
20462042

2043+
std::vector<Record *> Fusions = Records.getAllDerivedDefinitions("Fusion");
2044+
// Sort macro fusions by name.
2045+
llvm::sort(Fusions, LessRecord());
2046+
2047+
if (!Fusions.empty())
2048+
emitMacroFusionTable(Fusions, OS);
2049+
20472050
OS << "#include \"llvm/CodeGen/TargetSchedule.h\"\n\n";
20482051
OS << "namespace llvm {\n";
20492052
OS << "extern const llvm::SubtargetFeatureKV " << Target << "FeatureKV[];\n";
@@ -2078,17 +2081,19 @@ void SubtargetEmitter::run(raw_ostream &OS) {
20782081
<< Target << "ReadAdvanceTable, ";
20792082
OS << '\n'; OS.indent(24);
20802083
if (SchedModels.hasItineraries()) {
2081-
OS << Target << "Stages, "
2082-
<< Target << "OperandCycles, "
2083-
<< Target << "ForwardingPaths";
2084+
OS << Target << "Stages, " << Target << "OperandCycles, " << Target
2085+
<< "ForwardingPaths, ";
20842086
} else
2085-
OS << "nullptr, nullptr, nullptr";
2087+
OS << "nullptr, nullptr, nullptr, ";
2088+
if (!Fusions.empty()) {
2089+
OS << "ArrayRef(" << Target << "MacroFusionTable, " << Fusions.size()
2090+
<< ")";
2091+
} else
2092+
OS << "std::nullopt";
20862093
OS << ") {}\n\n";
20872094

20882095
EmitSchedModelHelpers(ClassName, OS);
20892096
EmitHwModeCheck(ClassName, OS);
2090-
if (TGT.getSchedModels().hasMacroFusions())
2091-
emitGetMacroFusions(ClassName, OS);
20922097

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

0 commit comments

Comments
 (0)