Skip to content

Commit

Permalink
[TableGen] Integrate TableGen-based macro fusion
Browse files Browse the repository at this point in the history
`Fusion` is inherited from `SubtargetFuture` now. Each definition
of `Fusion` will define a `SubtargetFuture` accordingly.

Two methods `enableMacroFusion` and `getMacroFusions` are added to
`TargetSubtargetInfo`. `enableMacroFusion` indicates whether macro
fusion shoule be enabled and `getMacroFusions` returns a list of
`MacroFusionPredTy` that will be evaluated by MacroFusionMution.

`enableMacroFusion` and `getMacroFusions` will be auto-generated
if the target has `Fusion` definitions.
  • Loading branch information
wangpc-pp committed Jan 8, 2024
1 parent 2642240 commit c0ce4d9
Show file tree
Hide file tree
Showing 7 changed files with 143 additions and 64 deletions.
7 changes: 7 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,12 @@ class TargetSubtargetInfo : public MCSubtargetInfo {
/// helps removing redundant copies generated by register allocator when
/// handling complex eviction chains.
virtual bool enableSpillageCopyElimination() const { return false; }

/// Enable macro fusion for this subtarget.
virtual bool enableMacroFusion() const { return false; }

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

} // end namespace llvm
Expand Down
92 changes: 46 additions & 46 deletions llvm/include/llvm/Target/Target.td
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,52 @@ class DwarfRegAlias<Register reg> {
Register DwarfAlias = reg;
}

//===----------------------------------------------------------------------===//
// SubtargetFeature - A characteristic of the chip set.
//
class SubtargetFeature<string n, string f, string v, string d,
list<SubtargetFeature> i = []> {
// Name - Feature name. Used by command line (-mattr=) to determine the
// appropriate target chip.
//
string Name = n;

// FieldName - Field in XXXSubtarget to be set by feature.
//
string FieldName = f;

// Value - Value the XXXSubtarget field to be set to by feature.
//
// A value of "true" or "false" implies the field is a bool. Otherwise,
// it is assumed to be an integer. the integer value may be the name of an
// enum constant. If multiple features use the same integer field, the
// field will be set to the maximum value of all enabled features that
// share the field.
//
string Value = v;

// Desc - Feature description. Used by command line (-mattr=) to display help
// information.
//
string Desc = d;

// Implies - Features that this feature implies are present. If one of those
// features isn't set, then this one shouldn't be set either.
//
list<SubtargetFeature> Implies = i;
}

/// Specifies a Subtarget feature that this instruction is deprecated on.
class Deprecated<SubtargetFeature dep> {
SubtargetFeature DeprecatedFeatureMask = dep;
}

/// A custom predicate used to determine if an instruction is
/// deprecated or not.
class ComplexDeprecationPredicate<string dep> {
string ComplexDeprecationPredicate = dep;
}

//===----------------------------------------------------------------------===//
// Pull in the common support for MCPredicate (portable scheduling predicates).
//
Expand Down Expand Up @@ -1680,52 +1726,6 @@ class Target {
int AllowRegisterRenaming = 0;
}

//===----------------------------------------------------------------------===//
// SubtargetFeature - A characteristic of the chip set.
//
class SubtargetFeature<string n, string f, string v, string d,
list<SubtargetFeature> i = []> {
// Name - Feature name. Used by command line (-mattr=) to determine the
// appropriate target chip.
//
string Name = n;

// FieldName - Field in XXXSubtarget to be set by feature.
//
string FieldName = f;

// Value - Value the XXXSubtarget field to be set to by feature.
//
// A value of "true" or "false" implies the field is a bool. Otherwise,
// it is assumed to be an integer. the integer value may be the name of an
// enum constant. If multiple features use the same integer field, the
// field will be set to the maximum value of all enabled features that
// share the field.
//
string Value = v;

// Desc - Feature description. Used by command line (-mattr=) to display help
// information.
//
string Desc = d;

// Implies - Features that this feature implies are present. If one of those
// features isn't set, then this one shouldn't be set either.
//
list<SubtargetFeature> Implies = i;
}

/// Specifies a Subtarget feature that this instruction is deprecated on.
class Deprecated<SubtargetFeature dep> {
SubtargetFeature DeprecatedFeatureMask = dep;
}

/// A custom predicate used to determine if an instruction is
/// deprecated or not.
class ComplexDeprecationPredicate<string dep> {
string ComplexDeprecationPredicate = dep;
}

//===----------------------------------------------------------------------===//
// Processor chip sets - These values represent each of the chip sets supported
// by the scheduler. Each Processor definition requires corresponding
Expand Down
37 changes: 20 additions & 17 deletions llvm/include/llvm/Target/TargetSchedule.td
Original file line number Diff line number Diff line change
Expand Up @@ -658,7 +658,8 @@ def OneUse : OneUsePred;
// return true;
// }
// ```
class Fusion<list<FusionPredicate> predicates> {
class Fusion<string name, string fieldName, string desc, list<FusionPredicate> predicates>
: SubtargetFeature<name, fieldName, "true", desc> {
list<FusionPredicate> Predicates = predicates;
}

Expand All @@ -679,21 +680,23 @@ class Fusion<list<FusionPredicate> predicates> {
// return true;
// }
// ```
class SimpleFusion<MCInstPredicate firstPred, MCInstPredicate secondPred,
class SimpleFusion<string name, string fieldName, string desc,
MCInstPredicate firstPred, MCInstPredicate secondPred,
list<FusionPredicate> prolog = [],
list<FusionPredicate> epilog = []>
: Fusion<!listconcat(
prolog,
[
SecondFusionPredicateWithMCInstPredicate<secondPred>,
WildcardTrue,
FirstFusionPredicateWithMCInstPredicate<firstPred>,
SecondFusionPredicateWithMCInstPredicate<
CheckAny<[
CheckIsVRegOperand<0>,
CheckSameRegOperand<0, 1>
]>>,
OneUse,
TieReg<0, 1>,
],
epilog)>;
: Fusion<name, fieldName, desc,
!listconcat(
prolog,
[
SecondFusionPredicateWithMCInstPredicate<secondPred>,
WildcardTrue,
FirstFusionPredicateWithMCInstPredicate<firstPred>,
SecondFusionPredicateWithMCInstPredicate<
CheckAny<[
CheckIsVRegOperand<0>,
CheckSameRegOperand<0, 1>
]>>,
OneUse,
TieReg<0, 1>,
],
epilog)>;
22 changes: 21 additions & 1 deletion llvm/test/TableGen/MacroFusion.td
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// RUN: llvm-tblgen -gen-macro-fusion-pred -I %p/../../include %s | FileCheck %s --check-prefix=CHECK-PREDICATOR
// RUN: llvm-tblgen -gen-subtarget -I %p/../../include %s | FileCheck %s --check-prefix=CHECK-SUBTARGET

include "llvm/Target/Target.td"

Expand Down Expand Up @@ -33,7 +34,8 @@ let Namespace = "Test" in {
def Inst0 : TestInst<0>;
def Inst1 : TestInst<1>;

def TestFusion: SimpleFusion<CheckOpcode<[Inst0]>,
def TestFusion: SimpleFusion<"test-fusion", "HasTestFusion", "Test Fusion",
CheckOpcode<[Inst0]>,
CheckAll<[
CheckOpcode<[Inst1]>,
CheckRegOperand<0, X0>
Expand Down Expand Up @@ -95,3 +97,21 @@ def TestFusion: SimpleFusion<CheckOpcode<[Inst0]>,
// CHECK-PREDICATOR-NEXT: } // end namespace llvm
// CHECK-PREDICATOR-EMPTY:
// CHECK-PREDICATOR-NEXT: #endif

// Check that we have generated target subfeature.
// CHECK-SUBTARGET: { "test-fusion", "Test Fusion", Test::TestFusion

// Check that we have generated `enableMacroFusion()` and `getMacroFusions()` function.
// CHECK-SUBTARGET: bool enableMacroFusion() const override;
// CHECK-SUBTARGET: std::vector<MacroFusionPredTy> getMacroFusions() const override;

// CHECK-SUBTARGET: bool TestGenSubtargetInfo::enableMacroFusion() const {
// CHECK-SUBTARGET-NEXT: if (hasFeature(Test::TestFusion)) return true;
// CHECK-SUBTARGET-NEXT: return false;
// CHECK-SUBTARGET-NEXT: }

// CHECK-SUBTARGET: std::vector<MacroFusionPredTy> TestGenSubtargetInfo::getMacroFusions() const {
// CHECK-SUBTARGET-NEXT: std::vector<MacroFusionPredTy> Fusions;
// CHECK-SUBTARGET-NEXT: if (hasFeature(Test::TestFusion)) Fusions.push_back(llvm::isTestFusion);
// CHECK-SUBTARGET-NEXT: return Fusions;
// CHECK-SUBTARGET-NEXT: }
1 change: 1 addition & 0 deletions llvm/utils/TableGen/CodeGenTarget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,7 @@ CodeGenTarget::CodeGenTarget(RecordKeeper &records)
if (Targets.size() != 1)
PrintFatalError("Multiple subclasses of Target defined!");
TargetRec = Targets[0];
MacroFusions = Records.getAllDerivedDefinitions("Fusion");
}

CodeGenTarget::~CodeGenTarget() {
Expand Down
6 changes: 6 additions & 0 deletions llvm/utils/TableGen/CodeGenTarget.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ class CodeGenTarget {
mutable std::vector<Record*> RegAltNameIndices;
mutable SmallVector<ValueTypeByHwMode, 8> LegalValueTypes;
CodeGenHwModes CGH;
std::vector<Record *> MacroFusions;

void ReadRegAltNameIndices() const;
void ReadInstructions() const;
void ReadLegalValueTypes() const;
Expand Down Expand Up @@ -149,6 +151,10 @@ class CodeGenTarget {

const CodeGenHwModes &getHwModes() const { return CGH; }

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

const std::vector<Record *> getMacroFusions() const { return MacroFusions; }

private:
DenseMap<const Record*, std::unique_ptr<CodeGenInstruction>> &
getInstructions() const {
Expand Down
42 changes: 42 additions & 0 deletions 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 emitGetMacroFusions(const std::string &ClassName, raw_ostream &OS);
void emitEnableMacroFusion(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 @@ -1786,6 +1788,39 @@ void SubtargetEmitter::EmitHwModeCheck(const std::string &ClassName,
OS << " return 0;\n}\n";
}

void SubtargetEmitter::emitEnableMacroFusion(const std::string &ClassName,
raw_ostream &OS) {
if (!TGT.hasMacroFusion())
return;

OS << "bool " << ClassName << "::enableMacroFusion() const {\n";
for (auto *Fusion : TGT.getMacroFusions())
OS.indent(2) << "if (hasFeature(" << Target
<< "::" << Fusion->getNameInitAsString()
<< ")) return true;\n";

OS.indent(2) << "return false;\n";
OS << "}\n";
}

void SubtargetEmitter::emitGetMacroFusions(const std::string &ClassName,
raw_ostream &OS) {
if (!TGT.hasMacroFusion())
return;

OS << "std::vector<MacroFusionPredTy> " << ClassName
<< "::getMacroFusions() const {\n";
OS.indent(2) << "std::vector<MacroFusionPredTy> Fusions;\n";
for (auto *Fusion : TGT.getMacroFusions()) {
std::string Name = Fusion->getNameInitAsString();
OS.indent(2) << "if (hasFeature(" << Target << "::" << Name
<< ")) Fusions.push_back(llvm::is" << Name << ");\n";
}

OS.indent(2) << "return Fusions;\n";
OS << "}\n";
}

// Produces a subtarget specific function for parsing
// the subtarget features string.
void SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS) {
Expand Down Expand Up @@ -1987,6 +2022,11 @@ void SubtargetEmitter::run(raw_ostream &OS) {
<< " const;\n";
if (TGT.getHwModes().getNumModeIds() > 1)
OS << " unsigned getHwMode() const override;\n";
if (TGT.hasMacroFusion()) {
OS << " bool enableMacroFusion() const override;\n";
OS << " std::vector<MacroFusionPredTy> getMacroFusions() const "
"override;\n";
}

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

EmitSchedModelHelpers(ClassName, OS);
EmitHwModeCheck(ClassName, OS);
emitEnableMacroFusion(ClassName, OS);
emitGetMacroFusions(ClassName, OS);

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

Expand Down

0 comments on commit c0ce4d9

Please sign in to comment.