Combine.td revision 360784
1//===- Combine.td - Combine rule definitions ---------------*- tablegen -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Declare GlobalISel combine rules and provide mechanisms to opt-out.
10//
11//===----------------------------------------------------------------------===//
12
13// Common base class for GICombineRule and GICombineGroup.
14class GICombine {
15  // See GICombineGroup. We only declare it here to make the tablegen pass
16  // simpler.
17  list<GICombine> Rules = ?;
18}
19
20// A group of combine rules that can be added to a GICombiner or another group.
21class GICombineGroup<list<GICombine> rules> : GICombine {
22  // The rules contained in this group. The rules in a group are flattened into
23  // a single list and sorted into whatever order is most efficient. However,
24  // they will never be re-ordered such that behaviour differs from the
25  // specified order. It is therefore possible to use the order of rules in this
26  // list to describe priorities.
27  let Rules = rules;
28}
29
30// Declares a combiner helper class
31class GICombinerHelper<string classname, list<GICombine> rules>
32    : GICombineGroup<rules> {
33  // The class name to use in the generated output.
34  string Classname = classname;
35  // The name of a run-time compiler option that will be generated to disable
36  // specific rules within this combiner.
37  string DisableRuleOption = ?;
38}
39class GICombineRule<dag defs, dag match, dag apply> : GICombine {
40  /// Defines the external interface of the match rule. This includes:
41  /// * The names of the root nodes (requires at least one)
42  /// See GIDefKind for details.
43  dag Defs = defs;
44
45  /// Defines the things which must be true for the pattern to match
46  /// See GIMatchKind for details.
47  dag Match = match;
48
49  /// Defines the things which happen after the decision is made to apply a
50  /// combine rule.
51  /// See GIApplyKind for details.
52  dag Apply = apply;
53}
54
55/// The operator at the root of a GICombineRule.Defs dag.
56def defs;
57
58/// All arguments of the defs operator must be subclasses of GIDefKind or
59/// sub-dags whose operator is GIDefKindWithArgs.
60class GIDefKind;
61class GIDefKindWithArgs;
62/// Declare a root node. There must be at least one of these in every combine
63/// rule.
64/// TODO: The plan is to elide `root` definitions and determine it from the DAG
65///       itself with an overide for situations where the usual determination
66///       is incorrect.
67def root : GIDefKind;
68
69/// Declares data that is passed from the match stage to the apply stage.
70class GIDefMatchData<string type> : GIDefKind {
71  /// A C++ type name indicating the storage type.
72  string Type = type;
73}
74
75def extending_load_matchdata : GIDefMatchData<"PreferredTuple">;
76def indexed_load_store_matchdata : GIDefMatchData<"IndexedLoadStoreMatchInfo">;
77
78/// The operator at the root of a GICombineRule.Match dag.
79def match;
80/// All arguments of the match operator must be either:
81/// * A subclass of GIMatchKind
82/// * A subclass of GIMatchKindWithArgs
83/// * A subclass of Instruction
84/// * A MIR code block (deprecated)
85/// The GIMatchKind and GIMatchKindWithArgs cases are described in more detail
86/// in their definitions below.
87/// For the Instruction case, these are collected into a DAG where operand names
88/// that occur multiple times introduce edges.
89class GIMatchKind;
90class GIMatchKindWithArgs;
91
92/// In lieu of having proper macro support. Trivial one-off opcode checks can be
93/// performed with this.
94def wip_match_opcode : GIMatchKindWithArgs;
95
96/// The operator at the root of a GICombineRule.Apply dag.
97def apply;
98/// All arguments of the apply operator must be subclasses of GIApplyKind, or
99/// sub-dags whose operator is GIApplyKindWithArgs, or an MIR block
100/// (deprecated).
101class GIApplyKind;
102class GIApplyKindWithArgs;
103
104def copy_prop : GICombineRule<
105  (defs root:$d),
106  (match (COPY $d, $s):$mi,
107         [{ return Helper.matchCombineCopy(*${mi}); }]),
108  (apply [{ Helper.applyCombineCopy(*${mi}); }])>;
109def trivial_combines : GICombineGroup<[copy_prop]>;
110
111def extending_loads : GICombineRule<
112  (defs root:$root, extending_load_matchdata:$matchinfo),
113  (match (wip_match_opcode G_LOAD, G_SEXTLOAD, G_ZEXTLOAD):$root,
114         [{ return Helper.matchCombineExtendingLoads(*${root}, ${matchinfo}); }]),
115  (apply [{ Helper.applyCombineExtendingLoads(*${root}, ${matchinfo}); }])>;
116def combines_for_extload: GICombineGroup<[extending_loads]>;
117
118def combine_indexed_load_store : GICombineRule<
119  (defs root:$root, indexed_load_store_matchdata:$matchinfo),
120  (match (wip_match_opcode G_LOAD, G_SEXTLOAD, G_ZEXTLOAD, G_STORE):$root,
121         [{ return Helper.matchCombineIndexedLoadStore(*${root}, ${matchinfo}); }]),
122  (apply [{ Helper.applyCombineIndexedLoadStore(*${root}, ${matchinfo}); }])>;
123
124// FIXME: Is there a reason this wasn't in tryCombine? I've left it out of
125//        all_combines because it wasn't there.
126def elide_br_by_inverting_cond : GICombineRule<
127  (defs root:$root),
128  (match (wip_match_opcode G_BR):$root,
129         [{ return Helper.matchElideBrByInvertingCond(*${root}); }]),
130  (apply [{ Helper.applyElideBrByInvertingCond(*${root}); }])>;
131
132def ptr_add_immed_matchdata : GIDefMatchData<"PtrAddChain">;
133def ptr_add_immed_chain : GICombineRule<
134  (defs root:$d, ptr_add_immed_matchdata:$matchinfo),
135  (match (wip_match_opcode G_PTR_ADD):$d,
136         [{ return Helper.matchPtrAddImmedChain(*${d}, ${matchinfo}); }]),
137  (apply [{ Helper.applyPtrAddImmedChain(*${d}, ${matchinfo}); }])>;
138
139def all_combines : GICombineGroup<[trivial_combines, ptr_add_immed_chain,
140    combines_for_extload, combine_indexed_load_store]>;
141