@@ -61,6 +61,24 @@ StringRef insertStrTab(StringRef S) {
61
61
return StrTab.insert (S).first ->first ();
62
62
}
63
63
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
+
64
82
class RootInfo {
65
83
StringRef PatternSymbol;
66
84
@@ -71,6 +89,10 @@ class RootInfo {
71
89
};
72
90
73
91
class CombineRule {
92
+ public:
93
+
94
+ using const_matchdata_iterator = std::vector<MatchDataInfo>::const_iterator;
95
+
74
96
struct VarInfo {
75
97
const GIMatchDagInstr *N;
76
98
const GIMatchDagOperand *Op;
@@ -108,6 +130,33 @@ class CombineRule {
108
130
// / FIXME: This is a temporary measure until we have actual pattern matching
109
131
const CodeInit *MatchingFixupCode = nullptr ;
110
132
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
+
111
160
bool parseInstructionMatcher (const CodeGenTarget &Target, StringInit *ArgName,
112
161
const Init &Arg,
113
162
StringMap<std::vector<VarInfo>> &NamedEdgeDefs,
@@ -139,6 +188,16 @@ class CombineRule {
139
188
return llvm::make_range (Roots.begin (), Roots.end ());
140
189
}
141
190
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
+
142
201
// / The matcher will begin from the roots and will perform the match by
143
202
// / traversing the edges to cover the whole DAG. This function reverses DAG
144
203
// / edges such that everything is reachable from a root. This is part of the
@@ -243,6 +302,11 @@ StringRef makeNameForAnonPredicate(CombineRule &Rule) {
243
302
to_string (format (" __anonpred%d_%d" , Rule.getID (), Rule.allocUID ())));
244
303
}
245
304
305
+ void CombineRule::declareMatchData (StringRef PatternSymbol, StringRef Type,
306
+ StringRef VarName) {
307
+ MatchDataDecls.emplace_back (PatternSymbol, Type, VarName);
308
+ }
309
+
246
310
bool CombineRule::parseDefs () {
247
311
NamedRegionTimer T (" parseDefs" , " Time spent parsing the defs" , " Rule Parsing" ,
248
312
" Time spent on rule parsing" , TimeRegions);
@@ -260,6 +324,17 @@ bool CombineRule::parseDefs() {
260
324
continue ;
261
325
}
262
326
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
+
263
338
// Otherwise emit an appropriate error message.
264
339
if (getDefOfSubClass (*Defs->getArg (I), " GIDefKind" ))
265
340
PrintError (TheDef.getLoc (),
@@ -556,6 +631,8 @@ void GICombinerEmitter::generateCodeForRule(raw_ostream &OS,
556
631
for (const RootInfo &Root : Rule->roots ()) {
557
632
Expansions.declare (Root.getPatternSymbol (), " MI" );
558
633
}
634
+ Rule->declareExpansions (Expansions);
635
+
559
636
DagInit *Applyer = RuleDef.getValueAsDag (" Apply" );
560
637
if (Applyer->getOperatorAsDef (RuleDef.getLoc ())->getName () !=
561
638
" apply" ) {
@@ -695,6 +772,12 @@ void GICombinerEmitter::run(raw_ostream &OS) {
695
772
<< " MachineRegisterInfo &MRI = MF->getRegInfo();\n "
696
773
<< " (void)MBB; (void)MF; (void)MRI;\n\n " ;
697
774
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
+
698
781
for (const auto &Rule : Rules)
699
782
generateCodeForRule (OS, Rule.get (), " " );
700
783
OS << " \n return false;\n "
0 commit comments