Skip to content

Commit 55c5740

Browse files
committed
[gicombiner] Add support for arbitrary match data being passed from match to apply
Summary: This is used by the extending_loads combine to tell the apply step which use is the preferred one to fold and the other uses should be re-written to consume. Depends on D69117 Reviewers: volkan, bogner Reviewed By: volkan Subscribers: hiraditya, Petar.Avramovic, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D69147
1 parent 1f3dd83 commit 55c5740

File tree

3 files changed

+112
-15
lines changed

3 files changed

+112
-15
lines changed

llvm/include/llvm/Target/GlobalISel/Combine.td

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,20 @@ class GIDefKindWithArgs;
6666
/// is incorrect.
6767
def root : GIDefKind;
6868

69+
/// Declares data that is passed from the match stage to the apply stage.
70+
class GIDefMatchData<string type> : GIDefKind {
71+
/// A C++ type name indicating the storage type.
72+
string Type = type;
73+
}
74+
75+
def extending_load_matchdata : GIDefMatchData<"PreferredTuple">;
76+
6977
/// The operator at the root of a GICombineRule.Match dag.
7078
def match;
7179
/// All arguments of the match operator must be either:
7280
/// * A subclass of GIMatchKind
7381
/// * A subclass of GIMatchKindWithArgs
82+
/// * A subclass of Instruction
7483
/// * A MIR code block (deprecated)
7584
/// The GIMatchKind and GIMatchKindWithArgs cases are described in more detail
7685
/// in their definitions below.
@@ -93,11 +102,18 @@ def copy_prop : GICombineRule<
93102
(apply [{ Helper.applyCombineCopy(${d}); }])>;
94103
def trivial_combines : GICombineGroup<[copy_prop]>;
95104

105+
def extending_loads : GICombineRule<
106+
(defs root:$root, extending_load_matchdata:$matchinfo),
107+
(match [{ return Helper.matchCombineExtendingLoads(${root}, ${matchinfo}); }]),
108+
(apply [{ Helper.applyCombineExtendingLoads(${root}, ${matchinfo}); }])>;
109+
96110
// FIXME: Is there a reason this wasn't in tryCombine? I've left it out of
97111
// all_combines because it wasn't there.
98112
def elide_br_by_inverting_cond : GICombineRule<
99113
(defs root:$d),
100114
(match [{ return Helper.matchElideBrByInvertingCond(${d}); }]),
101115
(apply [{ Helper.applyElideBrByInvertingCond(${d}); }])>;
102116

103-
def all_combines : GICombineGroup<[trivial_combines]>;
117+
def combines_for_extload: GICombineGroup<[extending_loads]>;
118+
119+
def all_combines : GICombineGroup<[trivial_combines, combines_for_extload]>;

llvm/lib/Target/AArch64/AArch64PreLegalizerCombiner.cpp

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -62,20 +62,6 @@ bool AArch64PreLegalizerCombinerInfo::combine(GISelChangeObserver &Observer,
6262
CombinerHelper Helper(Observer, B, KB, MDT);
6363

6464
switch (MI.getOpcode()) {
65-
case TargetOpcode::G_CONCAT_VECTORS:
66-
return Helper.tryCombineConcatVectors(MI);
67-
case TargetOpcode::G_SHUFFLE_VECTOR:
68-
return Helper.tryCombineShuffleVector(MI);
69-
case TargetOpcode::G_LOAD:
70-
case TargetOpcode::G_SEXTLOAD:
71-
case TargetOpcode::G_ZEXTLOAD: {
72-
bool Changed = false;
73-
Changed |= Helper.tryCombineExtendingLoads(MI);
74-
Changed |= Helper.tryCombineIndexedLoadStore(MI);
75-
return Changed;
76-
}
77-
case TargetOpcode::G_STORE:
78-
return Helper.tryCombineIndexedLoadStore(MI);
7965
case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
8066
switch (MI.getIntrinsicID()) {
8167
case Intrinsic::memcpy:
@@ -96,6 +82,18 @@ bool AArch64PreLegalizerCombinerInfo::combine(GISelChangeObserver &Observer,
9682
if (Generated.tryCombineAll(Observer, MI, B))
9783
return true;
9884

85+
switch (MI.getOpcode()) {
86+
case TargetOpcode::G_CONCAT_VECTORS:
87+
return Helper.tryCombineConcatVectors(MI);
88+
case TargetOpcode::G_SHUFFLE_VECTOR:
89+
return Helper.tryCombineShuffleVector(MI);
90+
case TargetOpcode::G_LOAD:
91+
case TargetOpcode::G_SEXTLOAD:
92+
case TargetOpcode::G_ZEXTLOAD:
93+
case TargetOpcode::G_STORE:
94+
return Helper.tryCombineIndexedLoadStore(MI);
95+
}
96+
9997
return false;
10098
}
10199

llvm/utils/TableGen/GICombinerEmitter.cpp

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,24 @@ StringRef insertStrTab(StringRef S) {
6161
return StrTab.insert(S).first->first();
6262
}
6363

64+
/// Declares data that is passed from the match stage to the apply stage.
65+
class MatchDataInfo {
66+
/// The symbol used in the tablegen patterns
67+
StringRef PatternSymbol;
68+
/// The data type for the variable
69+
StringRef Type;
70+
/// The name of the variable as declared in the generated matcher.
71+
std::string VariableName;
72+
73+
public:
74+
MatchDataInfo(StringRef PatternSymbol, StringRef Type, StringRef VariableName)
75+
: PatternSymbol(PatternSymbol), Type(Type), VariableName(VariableName) {}
76+
77+
StringRef getPatternSymbol() const { return PatternSymbol; };
78+
StringRef getType() const { return Type; };
79+
StringRef getVariableName() const { return VariableName; };
80+
};
81+
6482
class RootInfo {
6583
StringRef PatternSymbol;
6684

@@ -71,6 +89,10 @@ class RootInfo {
7189
};
7290

7391
class CombineRule {
92+
public:
93+
94+
using const_matchdata_iterator = std::vector<MatchDataInfo>::const_iterator;
95+
7496
struct VarInfo {
7597
const GIMatchDagInstr *N;
7698
const GIMatchDagOperand *Op;
@@ -108,6 +130,33 @@ class CombineRule {
108130
/// FIXME: This is a temporary measure until we have actual pattern matching
109131
const CodeInit *MatchingFixupCode = nullptr;
110132

133+
/// The MatchData defined by the match stage and required by the apply stage.
134+
/// This allows the plumbing of arbitrary data from C++ predicates between the
135+
/// stages.
136+
///
137+
/// For example, suppose you have:
138+
/// %A = <some-constant-expr>
139+
/// %0 = G_ADD %1, %A
140+
/// you could define a GIMatchPredicate that walks %A, constant folds as much
141+
/// as possible and returns an APInt containing the discovered constant. You
142+
/// could then declare:
143+
/// def apint : GIDefMatchData<"APInt">;
144+
/// add it to the rule with:
145+
/// (defs root:$root, apint:$constant)
146+
/// evaluate it in the pattern with a C++ function that takes a
147+
/// MachineOperand& and an APInt& with:
148+
/// (match [{MIR %root = G_ADD %0, %A }],
149+
/// (constantfold operand:$A, apint:$constant))
150+
/// and finally use it in the apply stage with:
151+
/// (apply (create_operand
152+
/// [{ MachineOperand::CreateImm(${constant}.getZExtValue());
153+
/// ]}, apint:$constant),
154+
/// [{MIR %root = FOO %0, %constant }])
155+
std::vector<MatchDataInfo> MatchDataDecls;
156+
157+
void declareMatchData(StringRef PatternSymbol, StringRef Type,
158+
StringRef VarName);
159+
111160
bool parseInstructionMatcher(const CodeGenTarget &Target, StringInit *ArgName,
112161
const Init &Arg,
113162
StringMap<std::vector<VarInfo>> &NamedEdgeDefs,
@@ -139,6 +188,16 @@ class CombineRule {
139188
return llvm::make_range(Roots.begin(), Roots.end());
140189
}
141190

191+
iterator_range<const_matchdata_iterator> matchdata_decls() const {
192+
return make_range(MatchDataDecls.begin(), MatchDataDecls.end());
193+
}
194+
195+
/// Export expansions for this rule
196+
void declareExpansions(CodeExpansions &Expansions) const {
197+
for (const auto &I : matchdata_decls())
198+
Expansions.declare(I.getPatternSymbol(), I.getVariableName());
199+
}
200+
142201
/// The matcher will begin from the roots and will perform the match by
143202
/// traversing the edges to cover the whole DAG. This function reverses DAG
144203
/// edges such that everything is reachable from a root. This is part of the
@@ -243,6 +302,11 @@ StringRef makeNameForAnonPredicate(CombineRule &Rule) {
243302
to_string(format("__anonpred%d_%d", Rule.getID(), Rule.allocUID())));
244303
}
245304

305+
void CombineRule::declareMatchData(StringRef PatternSymbol, StringRef Type,
306+
StringRef VarName) {
307+
MatchDataDecls.emplace_back(PatternSymbol, Type, VarName);
308+
}
309+
246310
bool CombineRule::parseDefs() {
247311
NamedRegionTimer T("parseDefs", "Time spent parsing the defs", "Rule Parsing",
248312
"Time spent on rule parsing", TimeRegions);
@@ -260,6 +324,17 @@ bool CombineRule::parseDefs() {
260324
continue;
261325
}
262326

327+
// Subclasses of GIDefMatchData should declare that this rule needs to pass
328+
// data from the match stage to the apply stage, and ensure that the
329+
// generated matcher has a suitable variable for it to do so.
330+
if (Record *MatchDataRec =
331+
getDefOfSubClass(*Defs->getArg(I), "GIDefMatchData")) {
332+
declareMatchData(Defs->getArgNameStr(I),
333+
MatchDataRec->getValueAsString("Type"),
334+
llvm::to_string(llvm::format("MatchData%d", ID)));
335+
continue;
336+
}
337+
263338
// Otherwise emit an appropriate error message.
264339
if (getDefOfSubClass(*Defs->getArg(I), "GIDefKind"))
265340
PrintError(TheDef.getLoc(),
@@ -556,6 +631,8 @@ void GICombinerEmitter::generateCodeForRule(raw_ostream &OS,
556631
for (const RootInfo &Root : Rule->roots()) {
557632
Expansions.declare(Root.getPatternSymbol(), "MI");
558633
}
634+
Rule->declareExpansions(Expansions);
635+
559636
DagInit *Applyer = RuleDef.getValueAsDag("Apply");
560637
if (Applyer->getOperatorAsDef(RuleDef.getLoc())->getName() !=
561638
"apply") {
@@ -695,6 +772,12 @@ void GICombinerEmitter::run(raw_ostream &OS) {
695772
<< " MachineRegisterInfo &MRI = MF->getRegInfo();\n"
696773
<< " (void)MBB; (void)MF; (void)MRI;\n\n";
697774

775+
OS << " // Match data\n";
776+
for (const auto &Rule : Rules)
777+
for (const auto &I : Rule->matchdata_decls())
778+
OS << " " << I.getType() << " " << I.getVariableName() << ";\n";
779+
OS << "\n";
780+
698781
for (const auto &Rule : Rules)
699782
generateCodeForRule(OS, Rule.get(), " ");
700783
OS << "\n return false;\n"

0 commit comments

Comments
 (0)