1353940Sdim//===- Combine.td - Combine rule definitions ---------------*- tablegen -*-===//
2353940Sdim//
3353940Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353940Sdim// See https://llvm.org/LICENSE.txt for license information.
5353940Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6353940Sdim//
7353940Sdim//===----------------------------------------------------------------------===//
8353940Sdim//
9353940Sdim// Declare GlobalISel combine rules and provide mechanisms to opt-out.
10353940Sdim//
11353940Sdim//===----------------------------------------------------------------------===//
12353940Sdim
13353940Sdim// Common base class for GICombineRule and GICombineGroup.
14353940Sdimclass GICombine {
15353940Sdim  // See GICombineGroup. We only declare it here to make the tablegen pass
16353940Sdim  // simpler.
17353940Sdim  list<GICombine> Rules = ?;
18353940Sdim}
19353940Sdim
20353940Sdim// A group of combine rules that can be added to a GICombiner or another group.
21353940Sdimclass GICombineGroup<list<GICombine> rules> : GICombine {
22353940Sdim  // The rules contained in this group. The rules in a group are flattened into
23353940Sdim  // a single list and sorted into whatever order is most efficient. However,
24353940Sdim  // they will never be re-ordered such that behaviour differs from the
25353940Sdim  // specified order. It is therefore possible to use the order of rules in this
26353940Sdim  // list to describe priorities.
27353940Sdim  let Rules = rules;
28353940Sdim}
29353940Sdim
30353940Sdim// Declares a combiner helper class
31353940Sdimclass GICombinerHelper<string classname, list<GICombine> rules>
32353940Sdim    : GICombineGroup<rules> {
33353940Sdim  // The class name to use in the generated output.
34353940Sdim  string Classname = classname;
35353940Sdim  // The name of a run-time compiler option that will be generated to disable
36353940Sdim  // specific rules within this combiner.
37353940Sdim  string DisableRuleOption = ?;
38353940Sdim}
39353940Sdimclass GICombineRule<dag defs, dag match, dag apply> : GICombine {
40353940Sdim  /// Defines the external interface of the match rule. This includes:
41353940Sdim  /// * The names of the root nodes (requires at least one)
42353940Sdim  /// See GIDefKind for details.
43353940Sdim  dag Defs = defs;
44353940Sdim
45353940Sdim  /// Defines the things which must be true for the pattern to match
46353940Sdim  /// See GIMatchKind for details.
47353940Sdim  dag Match = match;
48353940Sdim
49353940Sdim  /// Defines the things which happen after the decision is made to apply a
50353940Sdim  /// combine rule.
51353940Sdim  /// See GIApplyKind for details.
52353940Sdim  dag Apply = apply;
53353940Sdim}
54353940Sdim
55353940Sdim/// The operator at the root of a GICombineRule.Defs dag.
56353940Sdimdef defs;
57353940Sdim
58353940Sdim/// All arguments of the defs operator must be subclasses of GIDefKind or
59353940Sdim/// sub-dags whose operator is GIDefKindWithArgs.
60353940Sdimclass GIDefKind;
61353940Sdimclass GIDefKindWithArgs;
62353940Sdim/// Declare a root node. There must be at least one of these in every combine
63353940Sdim/// rule.
64353940Sdim/// TODO: The plan is to elide `root` definitions and determine it from the DAG
65353940Sdim///       itself with an overide for situations where the usual determination
66353940Sdim///       is incorrect.
67353940Sdimdef root : GIDefKind;
68353940Sdim
69357095Sdim/// Declares data that is passed from the match stage to the apply stage.
70357095Sdimclass GIDefMatchData<string type> : GIDefKind {
71357095Sdim  /// A C++ type name indicating the storage type.
72357095Sdim  string Type = type;
73357095Sdim}
74357095Sdim
75357095Sdimdef extending_load_matchdata : GIDefMatchData<"PreferredTuple">;
76357095Sdimdef indexed_load_store_matchdata : GIDefMatchData<"IndexedLoadStoreMatchInfo">;
77357095Sdim
78353940Sdim/// The operator at the root of a GICombineRule.Match dag.
79353940Sdimdef match;
80353940Sdim/// All arguments of the match operator must be either:
81353940Sdim/// * A subclass of GIMatchKind
82353940Sdim/// * A subclass of GIMatchKindWithArgs
83357095Sdim/// * A subclass of Instruction
84353940Sdim/// * A MIR code block (deprecated)
85353940Sdim/// The GIMatchKind and GIMatchKindWithArgs cases are described in more detail
86353940Sdim/// in their definitions below.
87353940Sdim/// For the Instruction case, these are collected into a DAG where operand names
88353940Sdim/// that occur multiple times introduce edges.
89353940Sdimclass GIMatchKind;
90353940Sdimclass GIMatchKindWithArgs;
91353940Sdim
92357095Sdim/// In lieu of having proper macro support. Trivial one-off opcode checks can be
93357095Sdim/// performed with this.
94357095Sdimdef wip_match_opcode : GIMatchKindWithArgs;
95357095Sdim
96353940Sdim/// The operator at the root of a GICombineRule.Apply dag.
97353940Sdimdef apply;
98353940Sdim/// All arguments of the apply operator must be subclasses of GIApplyKind, or
99353940Sdim/// sub-dags whose operator is GIApplyKindWithArgs, or an MIR block
100353940Sdim/// (deprecated).
101353940Sdimclass GIApplyKind;
102353940Sdimclass GIApplyKindWithArgs;
103353940Sdim
104353940Sdimdef copy_prop : GICombineRule<
105353940Sdim  (defs root:$d),
106357095Sdim  (match (COPY $d, $s):$mi,
107357095Sdim         [{ return Helper.matchCombineCopy(*${mi}); }]),
108357095Sdim  (apply [{ Helper.applyCombineCopy(*${mi}); }])>;
109353940Sdimdef trivial_combines : GICombineGroup<[copy_prop]>;
110353940Sdim
111357095Sdimdef extending_loads : GICombineRule<
112357095Sdim  (defs root:$root, extending_load_matchdata:$matchinfo),
113357095Sdim  (match (wip_match_opcode G_LOAD, G_SEXTLOAD, G_ZEXTLOAD):$root,
114357095Sdim         [{ return Helper.matchCombineExtendingLoads(*${root}, ${matchinfo}); }]),
115357095Sdim  (apply [{ Helper.applyCombineExtendingLoads(*${root}, ${matchinfo}); }])>;
116357095Sdimdef combines_for_extload: GICombineGroup<[extending_loads]>;
117357095Sdim
118357095Sdimdef combine_indexed_load_store : GICombineRule<
119357095Sdim  (defs root:$root, indexed_load_store_matchdata:$matchinfo),
120357095Sdim  (match (wip_match_opcode G_LOAD, G_SEXTLOAD, G_ZEXTLOAD, G_STORE):$root,
121357095Sdim         [{ return Helper.matchCombineIndexedLoadStore(*${root}, ${matchinfo}); }]),
122357095Sdim  (apply [{ Helper.applyCombineIndexedLoadStore(*${root}, ${matchinfo}); }])>;
123357095Sdim
124353940Sdim// FIXME: Is there a reason this wasn't in tryCombine? I've left it out of
125353940Sdim//        all_combines because it wasn't there.
126353940Sdimdef elide_br_by_inverting_cond : GICombineRule<
127357095Sdim  (defs root:$root),
128357095Sdim  (match (wip_match_opcode G_BR):$root,
129357095Sdim         [{ return Helper.matchElideBrByInvertingCond(*${root}); }]),
130357095Sdim  (apply [{ Helper.applyElideBrByInvertingCond(*${root}); }])>;
131353940Sdim
132357095Sdimdef ptr_add_immed_matchdata : GIDefMatchData<"PtrAddChain">;
133357095Sdimdef ptr_add_immed_chain : GICombineRule<
134357095Sdim  (defs root:$d, ptr_add_immed_matchdata:$matchinfo),
135357095Sdim  (match (wip_match_opcode G_PTR_ADD):$d,
136357095Sdim         [{ return Helper.matchPtrAddImmedChain(*${d}, ${matchinfo}); }]),
137357095Sdim  (apply [{ Helper.applyPtrAddImmedChain(*${d}, ${matchinfo}); }])>;
138357095Sdim
139357095Sdimdef all_combines : GICombineGroup<[trivial_combines, ptr_add_immed_chain,
140357095Sdim    combines_for_extload, combine_indexed_load_store]>;
141