1 //===- Combine.td - Combine rule definitions ---------------*- tablegen -*-===//
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
7 //===----------------------------------------------------------------------===//
9 // Declare GlobalISel combine rules and provide mechanisms to opt-out.
11 //===----------------------------------------------------------------------===//
13 // Common base class for GICombineRule and GICombineGroup.
15 // See GICombineGroup. We only declare it here to make the tablegen pass
17 list<GICombine> Rules = ?;
20 // A group of combine rules that can be added to a GICombiner or another group.
21 class 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.
30 // Declares a combiner helper class
31 class 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 = ?;
39 class 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.
45 /// Defines the things which must be true for the pattern to match
46 /// See GIMatchKind for details.
49 /// Defines the things which happen after the decision is made to apply a
51 /// See GIApplyKind for details.
55 /// The operator at the root of a GICombineRule.Defs dag.
58 /// All arguments of the defs operator must be subclasses of GIDefKind or
59 /// sub-dags whose operator is GIDefKindWithArgs.
61 class GIDefKindWithArgs;
62 /// Declare a root node. There must be at least one of these in every combine
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
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.
75 def extending_load_matchdata : GIDefMatchData<"PreferredTuple">;
76 def indexed_load_store_matchdata : GIDefMatchData<"IndexedLoadStoreMatchInfo">;
78 /// The operator at the root of a GICombineRule.Match dag.
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.
90 class GIMatchKindWithArgs;
92 /// In lieu of having proper macro support. Trivial one-off opcode checks can be
93 /// performed with this.
94 def wip_match_opcode : GIMatchKindWithArgs;
96 /// The operator at the root of a GICombineRule.Apply dag.
98 /// All arguments of the apply operator must be subclasses of GIApplyKind, or
99 /// sub-dags whose operator is GIApplyKindWithArgs, or an MIR block
102 class GIApplyKindWithArgs;
104 def copy_prop : GICombineRule<
106 (match (COPY $d, $s):$mi,
107 [{ return Helper.matchCombineCopy(*${mi}); }]),
108 (apply [{ Helper.applyCombineCopy(*${mi}); }])>;
110 def extending_loads : GICombineRule<
111 (defs root:$root, extending_load_matchdata:$matchinfo),
112 (match (wip_match_opcode G_LOAD, G_SEXTLOAD, G_ZEXTLOAD):$root,
113 [{ return Helper.matchCombineExtendingLoads(*${root}, ${matchinfo}); }]),
114 (apply [{ Helper.applyCombineExtendingLoads(*${root}, ${matchinfo}); }])>;
115 def combines_for_extload: GICombineGroup<[extending_loads]>;
117 def combine_indexed_load_store : GICombineRule<
118 (defs root:$root, indexed_load_store_matchdata:$matchinfo),
119 (match (wip_match_opcode G_LOAD, G_SEXTLOAD, G_ZEXTLOAD, G_STORE):$root,
120 [{ return Helper.matchCombineIndexedLoadStore(*${root}, ${matchinfo}); }]),
121 (apply [{ Helper.applyCombineIndexedLoadStore(*${root}, ${matchinfo}); }])>;
123 // FIXME: Is there a reason this wasn't in tryCombine? I've left it out of
124 // all_combines because it wasn't there.
125 def elide_br_by_inverting_cond : GICombineRule<
127 (match (wip_match_opcode G_BR):$root,
128 [{ return Helper.matchElideBrByInvertingCond(*${root}); }]),
129 (apply [{ Helper.applyElideBrByInvertingCond(*${root}); }])>;
131 def ptr_add_immed_matchdata : GIDefMatchData<"PtrAddChain">;
132 def ptr_add_immed_chain : GICombineRule<
133 (defs root:$d, ptr_add_immed_matchdata:$matchinfo),
134 (match (wip_match_opcode G_PTR_ADD):$d,
135 [{ return Helper.matchPtrAddImmedChain(*${d}, ${matchinfo}); }]),
136 (apply [{ Helper.applyPtrAddImmedChain(*${d}, ${matchinfo}); }])>;
138 def mul_to_shl_matchdata : GIDefMatchData<"unsigned">;
139 def mul_to_shl : GICombineRule<
140 (defs root:$d, mul_to_shl_matchdata:$matchinfo),
141 (match (G_MUL $d, $op1, $op2):$mi,
142 [{ return Helper.matchCombineMulToShl(*${mi}, ${matchinfo}); }]),
143 (apply [{ Helper.applyCombineMulToShl(*${mi}, ${matchinfo}); }])>;
145 // [us]itofp(undef) = 0, because the result value is bounded.
146 def undef_to_fp_zero : GICombineRule<
148 (match (wip_match_opcode G_UITOFP, G_SITOFP):$root,
149 [{ return Helper.matchAnyExplicitUseIsUndef(*${root}); }]),
150 (apply [{ Helper.replaceInstWithFConstant(*${root}, 0.0); }])>;
152 def undef_to_int_zero: GICombineRule<
154 (match (wip_match_opcode G_AND, G_MUL):$root,
155 [{ return Helper.matchAnyExplicitUseIsUndef(*${root}); }]),
156 (apply [{ Helper.replaceInstWithConstant(*${root}, 0); }])>;
158 def undef_to_negative_one: GICombineRule<
160 (match (wip_match_opcode G_OR):$root,
161 [{ return Helper.matchAnyExplicitUseIsUndef(*${root}); }]),
162 (apply [{ Helper.replaceInstWithConstant(*${root}, -1); }])>;
164 // Instructions where if any source operand is undef, the instruction can be
165 // replaced with undef.
166 def propagate_undef_any_op: GICombineRule<
168 (match (wip_match_opcode G_ADD, G_FPTOSI, G_FPTOUI, G_SUB, G_XOR):$root,
169 [{ return Helper.matchAnyExplicitUseIsUndef(*${root}); }]),
170 (apply [{ Helper.replaceInstWithUndef(*${root}); }])>;
172 // Instructions where if all source operands are undef, the instruction can be
173 // replaced with undef.
174 def propagate_undef_all_ops: GICombineRule<
176 (match (wip_match_opcode G_SHUFFLE_VECTOR):$root,
177 [{ return Helper.matchAllExplicitUsesAreUndef(*${root}); }]),
178 (apply [{ Helper.replaceInstWithUndef(*${root}); }])>;
180 // Replace a G_SHUFFLE_VECTOR with an undef mask with a G_IMPLICIT_DEF.
181 def propagate_undef_shuffle_mask: GICombineRule<
183 (match (wip_match_opcode G_SHUFFLE_VECTOR):$root,
184 [{ return Helper.matchUndefShuffleVectorMask(*${root}); }]),
185 (apply [{ Helper.replaceInstWithUndef(*${root}); }])>;
187 // Fold (cond ? x : x) -> x
188 def select_same_val: GICombineRule<
190 (match (wip_match_opcode G_SELECT):$root,
191 [{ return Helper.matchSelectSameVal(*${root}); }]),
192 (apply [{ return Helper.replaceSingleDefInstWithOperand(*${root}, 2); }])
196 def right_identity_zero: GICombineRule<
198 (match (wip_match_opcode G_SUB, G_ADD, G_OR, G_XOR, G_SHL, G_ASHR, G_LSHR):$root,
199 [{ return Helper.matchConstantOp(${root}->getOperand(2), 0); }]),
200 (apply [{ return Helper.replaceSingleDefInstWithOperand(*${root}, 1); }])
203 // Fold (x op x) - > x
204 def binop_same_val: GICombineRule<
206 (match (wip_match_opcode G_AND, G_OR):$root,
207 [{ return Helper.matchBinOpSameVal(*${root}); }]),
208 (apply [{ return Helper.replaceSingleDefInstWithOperand(*${root}, 1); }])
211 // Fold (0 op x) - > 0
212 def binop_left_to_zero: GICombineRule<
214 (match (wip_match_opcode G_SDIV, G_UDIV, G_SREM, G_UREM):$root,
215 [{ return Helper.matchOperandIsZero(*${root}, 1); }]),
216 (apply [{ return Helper.replaceSingleDefInstWithOperand(*${root}, 1); }])
219 // Fold (x op 0) - > 0
220 def binop_right_to_zero: GICombineRule<
222 (match (wip_match_opcode G_MUL):$root,
223 [{ return Helper.matchOperandIsZero(*${root}, 2); }]),
224 (apply [{ return Helper.replaceSingleDefInstWithOperand(*${root}, 2); }])
227 // Erase stores of undef values.
228 def erase_undef_store : GICombineRule<
230 (match (wip_match_opcode G_STORE):$root,
231 [{ return Helper.matchUndefStore(*${root}); }]),
232 (apply [{ return Helper.eraseInst(*${root}); }])
235 // FIXME: These should use the custom predicate feature once it lands.
236 def undef_combines : GICombineGroup<[undef_to_fp_zero, undef_to_int_zero,
237 undef_to_negative_one,
238 propagate_undef_any_op,
239 propagate_undef_all_ops,
240 propagate_undef_shuffle_mask,
243 def identity_combines : GICombineGroup<[select_same_val, right_identity_zero,
244 binop_same_val, binop_left_to_zero,
245 binop_right_to_zero]>;
247 def trivial_combines : GICombineGroup<[copy_prop, mul_to_shl]>;
248 def all_combines : GICombineGroup<[trivial_combines, ptr_add_immed_chain,
249 combines_for_extload, combine_indexed_load_store, undef_combines,