Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
14 | pmbaty | 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. |
||
14 | class 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. |
||
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. |
||
27 | let Rules = rules; |
||
28 | } |
||
29 | |||
30 | class GICombinerHelperArg<string type, string name> { |
||
31 | string Type = type; |
||
32 | string Name = name; |
||
33 | } |
||
34 | |||
35 | // Declares a combiner helper class |
||
36 | class GICombinerHelper<string classname, list<GICombine> rules> |
||
37 | : GICombineGroup<rules> { |
||
38 | // The class name to use in the generated output. |
||
39 | string Classname = classname; |
||
40 | // The name of a run-time compiler option that will be generated to disable |
||
41 | // specific rules within this combiner. |
||
42 | string DisableRuleOption = ?; |
||
43 | // The state class to inherit from (if any). The generated helper will inherit |
||
44 | // from this class and will forward arguments to its constructors. |
||
45 | string StateClass = ""; |
||
46 | // Any additional arguments that should be appended to the tryCombine*(). |
||
47 | list<GICombinerHelperArg> AdditionalArguments = |
||
48 | [GICombinerHelperArg<"CombinerHelper &", "Helper">]; |
||
49 | } |
||
50 | class GICombineRule<dag defs, dag match, dag apply> : GICombine { |
||
51 | /// Defines the external interface of the match rule. This includes: |
||
52 | /// * The names of the root nodes (requires at least one) |
||
53 | /// See GIDefKind for details. |
||
54 | dag Defs = defs; |
||
55 | |||
56 | /// Defines the things which must be true for the pattern to match |
||
57 | /// See GIMatchKind for details. |
||
58 | dag Match = match; |
||
59 | |||
60 | /// Defines the things which happen after the decision is made to apply a |
||
61 | /// combine rule. |
||
62 | /// See GIApplyKind for details. |
||
63 | dag Apply = apply; |
||
64 | |||
65 | /// Defines the predicates that are checked before the match function |
||
66 | /// is called. Targets can use this to, for instance, check Subtarget |
||
67 | /// features. |
||
68 | list<Predicate> Predicates = []; |
||
69 | } |
||
70 | |||
71 | /// The operator at the root of a GICombineRule.Defs dag. |
||
72 | def defs; |
||
73 | |||
74 | /// All arguments of the defs operator must be subclasses of GIDefKind or |
||
75 | /// sub-dags whose operator is GIDefKindWithArgs. |
||
76 | class GIDefKind; |
||
77 | class GIDefKindWithArgs; |
||
78 | /// Declare a root node. There must be at least one of these in every combine |
||
79 | /// rule. |
||
80 | /// TODO: The plan is to elide `root` definitions and determine it from the DAG |
||
81 | /// itself with an overide for situations where the usual determination |
||
82 | /// is incorrect. |
||
83 | def root : GIDefKind; |
||
84 | |||
85 | /// Declares data that is passed from the match stage to the apply stage. |
||
86 | class GIDefMatchData<string type> : GIDefKind { |
||
87 | /// A C++ type name indicating the storage type. |
||
88 | string Type = type; |
||
89 | } |
||
90 | |||
91 | def extending_load_matchdata : GIDefMatchData<"PreferredTuple">; |
||
92 | def indexed_load_store_matchdata : GIDefMatchData<"IndexedLoadStoreMatchInfo">; |
||
93 | def instruction_steps_matchdata: GIDefMatchData<"InstructionStepsMatchInfo">; |
||
94 | |||
95 | /// The operator at the root of a GICombineRule.Match dag. |
||
96 | def match; |
||
97 | /// All arguments of the match operator must be either: |
||
98 | /// * A subclass of GIMatchKind |
||
99 | /// * A subclass of GIMatchKindWithArgs |
||
100 | /// * A subclass of Instruction |
||
101 | /// * A MIR code block (deprecated) |
||
102 | /// The GIMatchKind and GIMatchKindWithArgs cases are described in more detail |
||
103 | /// in their definitions below. |
||
104 | /// For the Instruction case, these are collected into a DAG where operand names |
||
105 | /// that occur multiple times introduce edges. |
||
106 | class GIMatchKind; |
||
107 | class GIMatchKindWithArgs; |
||
108 | |||
109 | /// In lieu of having proper macro support. Trivial one-off opcode checks can be |
||
110 | /// performed with this. |
||
111 | def wip_match_opcode : GIMatchKindWithArgs; |
||
112 | |||
113 | /// The operator at the root of a GICombineRule.Apply dag. |
||
114 | def apply; |
||
115 | /// All arguments of the apply operator must be subclasses of GIApplyKind, or |
||
116 | /// sub-dags whose operator is GIApplyKindWithArgs, or an MIR block |
||
117 | /// (deprecated). |
||
118 | class GIApplyKind; |
||
119 | class GIApplyKindWithArgs; |
||
120 | |||
121 | def register_matchinfo: GIDefMatchData<"Register">; |
||
122 | def int64_matchinfo: GIDefMatchData<"int64_t">; |
||
123 | def apint_matchinfo : GIDefMatchData<"APInt">; |
||
124 | def build_fn_matchinfo : |
||
125 | GIDefMatchData<"std::function<void(MachineIRBuilder &)>">; |
||
126 | def unsigned_matchinfo: GIDefMatchData<"unsigned">; |
||
127 | |||
128 | def copy_prop : GICombineRule< |
||
129 | (defs root:$d), |
||
130 | (match (COPY $d, $s):$mi, |
||
131 | [{ return Helper.matchCombineCopy(*${mi}); }]), |
||
132 | (apply [{ Helper.applyCombineCopy(*${mi}); }])>; |
||
133 | |||
134 | // idempotent operations |
||
135 | // Fold (freeze (freeze x)) -> (freeze x). |
||
136 | // Fold (fabs (fabs x)) -> (fabs x). |
||
137 | // Fold (fcanonicalize (fcanonicalize x)) -> (fcanonicalize x). |
||
138 | def idempotent_prop : GICombineRule< |
||
139 | (defs root:$mi), |
||
140 | (match (wip_match_opcode G_FREEZE, G_FABS, G_FCANONICALIZE):$mi, |
||
141 | [{ return MRI.getVRegDef(${mi}->getOperand(1).getReg())->getOpcode() == |
||
142 | ${mi}->getOpcode(); }]), |
||
143 | (apply [{ Helper.replaceSingleDefInstWithOperand(*${mi}, 1); }])>; |
||
144 | |||
145 | |||
146 | def extending_loads : GICombineRule< |
||
147 | (defs root:$root, extending_load_matchdata:$matchinfo), |
||
148 | (match (wip_match_opcode G_LOAD, G_SEXTLOAD, G_ZEXTLOAD):$root, |
||
149 | [{ return Helper.matchCombineExtendingLoads(*${root}, ${matchinfo}); }]), |
||
150 | (apply [{ Helper.applyCombineExtendingLoads(*${root}, ${matchinfo}); }])>; |
||
151 | |||
152 | def load_and_mask : GICombineRule< |
||
153 | (defs root:$root, build_fn_matchinfo:$matchinfo), |
||
154 | (match (wip_match_opcode G_AND):$root, |
||
155 | [{ return Helper.matchCombineLoadWithAndMask(*${root}, ${matchinfo}); }]), |
||
156 | (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>; |
||
157 | def combines_for_extload: GICombineGroup<[extending_loads, load_and_mask]>; |
||
158 | |||
159 | def sext_trunc_sextload : GICombineRule< |
||
160 | (defs root:$d), |
||
161 | (match (wip_match_opcode G_SEXT_INREG):$d, |
||
162 | [{ return Helper.matchSextTruncSextLoad(*${d}); }]), |
||
163 | (apply [{ Helper.applySextTruncSextLoad(*${d}); }])>; |
||
164 | |||
165 | def sext_inreg_of_load_matchdata : GIDefMatchData<"std::tuple<Register, unsigned>">; |
||
166 | def sext_inreg_of_load : GICombineRule< |
||
167 | (defs root:$root, sext_inreg_of_load_matchdata:$matchinfo), |
||
168 | (match (wip_match_opcode G_SEXT_INREG):$root, |
||
169 | [{ return Helper.matchSextInRegOfLoad(*${root}, ${matchinfo}); }]), |
||
170 | (apply [{ Helper.applySextInRegOfLoad(*${root}, ${matchinfo}); }])>; |
||
171 | |||
172 | def sext_inreg_to_zext_inreg : GICombineRule< |
||
173 | (defs root:$dst), |
||
174 | (match |
||
175 | (G_SEXT_INREG $dst, $src, $imm):$root, |
||
176 | [{ |
||
177 | unsigned BitWidth = MRI.getType(${src}.getReg()).getScalarSizeInBits(); |
||
178 | return Helper.getKnownBits()->maskedValueIsZero(${src}.getReg(), |
||
179 | APInt::getOneBitSet(BitWidth, ${imm}.getImm() - 1)); }]), |
||
180 | (apply [{ |
||
181 | Helper.getBuilder().setInstrAndDebugLoc(*${root}); |
||
182 | Helper.getBuilder().buildZExtInReg(${dst}, ${src}, ${imm}.getImm()); |
||
183 | ${root}->eraseFromParent(); |
||
184 | return true; |
||
185 | }]) |
||
186 | >; |
||
187 | |||
188 | def combine_indexed_load_store : GICombineRule< |
||
189 | (defs root:$root, indexed_load_store_matchdata:$matchinfo), |
||
190 | (match (wip_match_opcode G_LOAD, G_SEXTLOAD, G_ZEXTLOAD, G_STORE):$root, |
||
191 | [{ return Helper.matchCombineIndexedLoadStore(*${root}, ${matchinfo}); }]), |
||
192 | (apply [{ Helper.applyCombineIndexedLoadStore(*${root}, ${matchinfo}); }])>; |
||
193 | |||
194 | def opt_brcond_by_inverting_cond_matchdata : GIDefMatchData<"MachineInstr *">; |
||
195 | def opt_brcond_by_inverting_cond : GICombineRule< |
||
196 | (defs root:$root, opt_brcond_by_inverting_cond_matchdata:$matchinfo), |
||
197 | (match (wip_match_opcode G_BR):$root, |
||
198 | [{ return Helper.matchOptBrCondByInvertingCond(*${root}, ${matchinfo}); }]), |
||
199 | (apply [{ Helper.applyOptBrCondByInvertingCond(*${root}, ${matchinfo}); }])>; |
||
200 | |||
201 | def ptr_add_immed_matchdata : GIDefMatchData<"PtrAddChain">; |
||
202 | def ptr_add_immed_chain : GICombineRule< |
||
203 | (defs root:$d, ptr_add_immed_matchdata:$matchinfo), |
||
204 | (match (wip_match_opcode G_PTR_ADD):$d, |
||
205 | [{ return Helper.matchPtrAddImmedChain(*${d}, ${matchinfo}); }]), |
||
206 | (apply [{ Helper.applyPtrAddImmedChain(*${d}, ${matchinfo}); }])>; |
||
207 | |||
208 | // Fold shift (shift base x), y -> shift base, (x+y), if shifts are same |
||
209 | def shift_immed_matchdata : GIDefMatchData<"RegisterImmPair">; |
||
210 | def shift_immed_chain : GICombineRule< |
||
211 | (defs root:$d, shift_immed_matchdata:$matchinfo), |
||
212 | (match (wip_match_opcode G_SHL, G_ASHR, G_LSHR, G_SSHLSAT, G_USHLSAT):$d, |
||
213 | [{ return Helper.matchShiftImmedChain(*${d}, ${matchinfo}); }]), |
||
214 | (apply [{ Helper.applyShiftImmedChain(*${d}, ${matchinfo}); }])>; |
||
215 | |||
216 | // Transform shift (logic (shift X, C0), Y), C1 |
||
217 | // -> logic (shift X, (C0+C1)), (shift Y, C1), if shifts are same |
||
218 | def shift_of_shifted_logic_matchdata : GIDefMatchData<"ShiftOfShiftedLogic">; |
||
219 | def shift_of_shifted_logic_chain : GICombineRule< |
||
220 | (defs root:$d, shift_of_shifted_logic_matchdata:$matchinfo), |
||
221 | (match (wip_match_opcode G_SHL, G_ASHR, G_LSHR, G_USHLSAT, G_SSHLSAT):$d, |
||
222 | [{ return Helper.matchShiftOfShiftedLogic(*${d}, ${matchinfo}); }]), |
||
223 | (apply [{ Helper.applyShiftOfShiftedLogic(*${d}, ${matchinfo}); }])>; |
||
224 | |||
225 | def mul_to_shl_matchdata : GIDefMatchData<"unsigned">; |
||
226 | def mul_to_shl : GICombineRule< |
||
227 | (defs root:$d, mul_to_shl_matchdata:$matchinfo), |
||
228 | (match (G_MUL $d, $op1, $op2):$mi, |
||
229 | [{ return Helper.matchCombineMulToShl(*${mi}, ${matchinfo}); }]), |
||
230 | (apply [{ Helper.applyCombineMulToShl(*${mi}, ${matchinfo}); }])>; |
||
231 | |||
232 | // shl ([asz]ext x), y => zext (shl x, y), if shift does not overflow int |
||
233 | def reduce_shl_of_extend_matchdata : GIDefMatchData<"RegisterImmPair">; |
||
234 | def reduce_shl_of_extend : GICombineRule< |
||
235 | (defs root:$dst, reduce_shl_of_extend_matchdata:$matchinfo), |
||
236 | (match (G_SHL $dst, $src0, $src1):$mi, |
||
237 | [{ return Helper.matchCombineShlOfExtend(*${mi}, ${matchinfo}); }]), |
||
238 | (apply [{ Helper.applyCombineShlOfExtend(*${mi}, ${matchinfo}); }])>; |
||
239 | |||
240 | def narrow_binop_feeding_and : GICombineRule< |
||
241 | (defs root:$root, build_fn_matchinfo:$matchinfo), |
||
242 | (match (wip_match_opcode G_AND):$root, |
||
243 | [{ return Helper.matchNarrowBinopFeedingAnd(*${root}, ${matchinfo}); }]), |
||
244 | (apply [{ Helper.applyBuildFnNoErase(*${root}, ${matchinfo}); }])>; |
||
245 | |||
246 | // [us]itofp(undef) = 0, because the result value is bounded. |
||
247 | def undef_to_fp_zero : GICombineRule< |
||
248 | (defs root:$root), |
||
249 | (match (wip_match_opcode G_UITOFP, G_SITOFP):$root, |
||
250 | [{ return Helper.matchAnyExplicitUseIsUndef(*${root}); }]), |
||
251 | (apply [{ Helper.replaceInstWithFConstant(*${root}, 0.0); }])>; |
||
252 | |||
253 | def undef_to_int_zero: GICombineRule< |
||
254 | (defs root:$root), |
||
255 | (match (wip_match_opcode G_AND, G_MUL):$root, |
||
256 | [{ return Helper.matchAnyExplicitUseIsUndef(*${root}); }]), |
||
257 | (apply [{ Helper.replaceInstWithConstant(*${root}, 0); }])>; |
||
258 | |||
259 | def undef_to_negative_one: GICombineRule< |
||
260 | (defs root:$root), |
||
261 | (match (wip_match_opcode G_OR):$root, |
||
262 | [{ return Helper.matchAnyExplicitUseIsUndef(*${root}); }]), |
||
263 | (apply [{ Helper.replaceInstWithConstant(*${root}, -1); }])>; |
||
264 | |||
265 | def binop_left_undef_to_zero: GICombineRule< |
||
266 | (defs root:$root), |
||
267 | (match (wip_match_opcode G_SHL, G_UDIV, G_UREM):$root, |
||
268 | [{ return Helper.matchOperandIsUndef(*${root}, 1); }]), |
||
269 | (apply [{ Helper.replaceInstWithConstant(*${root}, 0); }])>; |
||
270 | |||
271 | def binop_right_undef_to_undef: GICombineRule< |
||
272 | (defs root:$root), |
||
273 | (match (wip_match_opcode G_SHL, G_ASHR, G_LSHR):$root, |
||
274 | [{ return Helper.matchOperandIsUndef(*${root}, 2); }]), |
||
275 | (apply [{ Helper.replaceInstWithUndef(*${root}); }])>; |
||
276 | |||
277 | def unary_undef_to_zero: GICombineRule< |
||
278 | (defs root:$root), |
||
279 | (match (wip_match_opcode G_ABS):$root, |
||
280 | [{ return Helper.matchOperandIsUndef(*${root}, 1); }]), |
||
281 | (apply [{ Helper.replaceInstWithConstant(*${root}, 0); }])>; |
||
282 | |||
283 | // Instructions where if any source operand is undef, the instruction can be |
||
284 | // replaced with undef. |
||
285 | def propagate_undef_any_op: GICombineRule< |
||
286 | (defs root:$root), |
||
287 | (match (wip_match_opcode G_ADD, G_FPTOSI, G_FPTOUI, G_SUB, G_XOR, G_TRUNC):$root, |
||
288 | [{ return Helper.matchAnyExplicitUseIsUndef(*${root}); }]), |
||
289 | (apply [{ Helper.replaceInstWithUndef(*${root}); }])>; |
||
290 | |||
291 | // Instructions where if all source operands are undef, the instruction can be |
||
292 | // replaced with undef. |
||
293 | def propagate_undef_all_ops: GICombineRule< |
||
294 | (defs root:$root), |
||
295 | (match (wip_match_opcode G_SHUFFLE_VECTOR):$root, |
||
296 | [{ return Helper.matchAllExplicitUsesAreUndef(*${root}); }]), |
||
297 | (apply [{ Helper.replaceInstWithUndef(*${root}); }])>; |
||
298 | |||
299 | // Replace a G_SHUFFLE_VECTOR with an undef mask with a G_IMPLICIT_DEF. |
||
300 | def propagate_undef_shuffle_mask: GICombineRule< |
||
301 | (defs root:$root), |
||
302 | (match (wip_match_opcode G_SHUFFLE_VECTOR):$root, |
||
303 | [{ return Helper.matchUndefShuffleVectorMask(*${root}); }]), |
||
304 | (apply [{ Helper.replaceInstWithUndef(*${root}); }])>; |
||
305 | |||
306 | // Replace an insert/extract element of an out of bounds index with undef. |
||
307 | def insert_extract_vec_elt_out_of_bounds : GICombineRule< |
||
308 | (defs root:$root), |
||
309 | (match (wip_match_opcode G_INSERT_VECTOR_ELT, G_EXTRACT_VECTOR_ELT):$root, |
||
310 | [{ return Helper.matchInsertExtractVecEltOutOfBounds(*${root}); }]), |
||
311 | (apply [{ Helper.replaceInstWithUndef(*${root}); }])>; |
||
312 | |||
313 | // Fold (cond ? x : x) -> x |
||
314 | def select_same_val: GICombineRule< |
||
315 | (defs root:$root), |
||
316 | (match (wip_match_opcode G_SELECT):$root, |
||
317 | [{ return Helper.matchSelectSameVal(*${root}); }]), |
||
318 | (apply [{ return Helper.replaceSingleDefInstWithOperand(*${root}, 2); }]) |
||
319 | >; |
||
320 | |||
321 | // Fold (undef ? x : y) -> y |
||
322 | def select_undef_cmp: GICombineRule< |
||
323 | (defs root:$root), |
||
324 | (match (wip_match_opcode G_SELECT):$root, |
||
325 | [{ return Helper.matchUndefSelectCmp(*${root}); }]), |
||
326 | (apply [{ return Helper.replaceSingleDefInstWithOperand(*${root}, 2); }]) |
||
327 | >; |
||
328 | |||
329 | // Fold (true ? x : y) -> x |
||
330 | // Fold (false ? x : y) -> y |
||
331 | def select_constant_cmp_matchdata : GIDefMatchData<"unsigned">; |
||
332 | def select_constant_cmp: GICombineRule< |
||
333 | (defs root:$root, select_constant_cmp_matchdata:$matchinfo), |
||
334 | (match (wip_match_opcode G_SELECT):$root, |
||
335 | [{ return Helper.matchConstantSelectCmp(*${root}, ${matchinfo}); }]), |
||
336 | (apply [{ return Helper.replaceSingleDefInstWithOperand(*${root}, ${matchinfo}); }]) |
||
337 | >; |
||
338 | |||
339 | def select_to_logical : GICombineRule< |
||
340 | (defs root:$root, build_fn_matchinfo:$matchinfo), |
||
341 | (match (wip_match_opcode G_SELECT):$root, |
||
342 | [{ return Helper.matchSelectToLogical(*${root}, ${matchinfo}); }]), |
||
343 | (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }]) |
||
344 | >; |
||
345 | |||
346 | // Fold (C op x) -> (x op C) |
||
347 | // TODO: handle more isCommutable opcodes |
||
348 | // TODO: handle compares (currently not marked as isCommutable) |
||
349 | def commute_constant_to_rhs : GICombineRule< |
||
350 | (defs root:$root), |
||
351 | (match (wip_match_opcode G_ADD, G_MUL, G_AND, G_OR, G_XOR):$root, [{ |
||
352 | return getIConstantVRegVal(${root}->getOperand(1).getReg(), MRI).has_value(); |
||
353 | }]), |
||
354 | (apply [{ |
||
355 | Observer.changingInstr(*${root}); |
||
356 | Register LHSReg = ${root}->getOperand(1).getReg(); |
||
357 | Register RHSReg = ${root}->getOperand(2).getReg(); |
||
358 | ${root}->getOperand(1).setReg(RHSReg); |
||
359 | ${root}->getOperand(2).setReg(LHSReg); |
||
360 | Observer.changedInstr(*${root}); |
||
361 | }]) |
||
362 | >; |
||
363 | |||
364 | // Fold x op 0 -> x |
||
365 | def right_identity_zero: GICombineRule< |
||
366 | (defs root:$root), |
||
367 | (match (wip_match_opcode G_SUB, G_ADD, G_OR, G_XOR, G_SHL, G_ASHR, G_LSHR, |
||
368 | G_PTR_ADD, G_ROTL, G_ROTR):$root, |
||
369 | [{ return Helper.matchConstantOp(${root}->getOperand(2), 0); }]), |
||
370 | (apply [{ return Helper.replaceSingleDefInstWithOperand(*${root}, 1); }]) |
||
371 | >; |
||
372 | |||
373 | // Fold x op 1 -> x |
||
374 | def right_identity_one: GICombineRule< |
||
375 | (defs root:$root), |
||
376 | (match (wip_match_opcode G_MUL):$root, |
||
377 | [{ return Helper.matchConstantOp(${root}->getOperand(2), 1); }]), |
||
378 | (apply [{ return Helper.replaceSingleDefInstWithOperand(*${root}, 1); }]) |
||
379 | >; |
||
380 | |||
381 | // Fold (x op x) - > x |
||
382 | def binop_same_val: GICombineRule< |
||
383 | (defs root:$root), |
||
384 | (match (wip_match_opcode G_AND, G_OR):$root, |
||
385 | [{ return Helper.matchBinOpSameVal(*${root}); }]), |
||
386 | (apply [{ return Helper.replaceSingleDefInstWithOperand(*${root}, 1); }]) |
||
387 | >; |
||
388 | |||
389 | // Fold (0 op x) - > 0 |
||
390 | def binop_left_to_zero: GICombineRule< |
||
391 | (defs root:$root), |
||
392 | (match (wip_match_opcode G_SDIV, G_UDIV, G_SREM, G_UREM):$root, |
||
393 | [{ return Helper.matchOperandIsZero(*${root}, 1); }]), |
||
394 | (apply [{ return Helper.replaceSingleDefInstWithOperand(*${root}, 1); }]) |
||
395 | >; |
||
396 | |||
397 | def urem_pow2_to_mask : GICombineRule< |
||
398 | (defs root:$root), |
||
399 | (match (wip_match_opcode G_UREM):$root, |
||
400 | [{ return Helper.matchOperandIsKnownToBeAPowerOfTwo(*${root}, 2); }]), |
||
401 | (apply [{ Helper.applySimplifyURemByPow2(*${root}); }]) |
||
402 | >; |
||
403 | |||
404 | // Push a binary operator through a select on constants. |
||
405 | // |
||
406 | // binop (select cond, K0, K1), K2 -> |
||
407 | // select cond, (binop K0, K2), (binop K1, K2) |
||
408 | |||
409 | // Every binary operator that has constant folding. We currently do |
||
410 | // not have constant folding for G_FPOW, G_FMAXNUM_IEEE or |
||
411 | // G_FMINNUM_IEEE. |
||
412 | def fold_binop_into_select : GICombineRule< |
||
413 | (defs root:$root, unsigned_matchinfo:$select_op_no), |
||
414 | (match (wip_match_opcode |
||
415 | G_ADD, G_SUB, G_PTR_ADD, G_AND, G_OR, G_XOR, |
||
416 | G_SDIV, G_SREM, G_UDIV, G_UREM, G_LSHR, G_ASHR, G_SHL, |
||
417 | G_SMIN, G_SMAX, G_UMIN, G_UMAX, |
||
418 | G_FMUL, G_FADD, G_FSUB, G_FDIV, G_FREM, |
||
419 | G_FMINNUM, G_FMAXNUM, G_FMINIMUM, G_FMAXIMUM):$root, |
||
420 | [{ return Helper.matchFoldBinOpIntoSelect(*${root}, ${select_op_no}); }]), |
||
421 | (apply [{ return Helper.applyFoldBinOpIntoSelect(*${root}, ${select_op_no}); }]) |
||
422 | >; |
||
423 | |||
424 | // Transform d = [su]div(x, y) and r = [su]rem(x, y) - > d, r = [su]divrem(x, y) |
||
425 | def div_rem_to_divrem_matchdata : GIDefMatchData<"MachineInstr *">; |
||
426 | def div_rem_to_divrem : GICombineRule< |
||
427 | (defs root:$root, div_rem_to_divrem_matchdata:$matchinfo), |
||
428 | (match (wip_match_opcode G_SDIV, G_UDIV, G_SREM, G_UREM):$root, |
||
429 | [{ return Helper.matchCombineDivRem(*${root}, ${matchinfo}); }]), |
||
430 | (apply [{ Helper.applyCombineDivRem(*${root}, ${matchinfo}); }]) |
||
431 | >; |
||
432 | |||
433 | // Fold (x op 0) - > 0 |
||
434 | def binop_right_to_zero: GICombineRule< |
||
435 | (defs root:$root), |
||
436 | (match (wip_match_opcode G_MUL):$root, |
||
437 | [{ return Helper.matchOperandIsZero(*${root}, 2); }]), |
||
438 | (apply [{ return Helper.replaceSingleDefInstWithOperand(*${root}, 2); }]) |
||
439 | >; |
||
440 | |||
441 | // Erase stores of undef values. |
||
442 | def erase_undef_store : GICombineRule< |
||
443 | (defs root:$root), |
||
444 | (match (wip_match_opcode G_STORE):$root, |
||
445 | [{ return Helper.matchUndefStore(*${root}); }]), |
||
446 | (apply [{ return Helper.eraseInst(*${root}); }]) |
||
447 | >; |
||
448 | |||
449 | def simplify_add_to_sub_matchinfo: GIDefMatchData<"std::tuple<Register, Register>">; |
||
450 | def simplify_add_to_sub: GICombineRule < |
||
451 | (defs root:$root, simplify_add_to_sub_matchinfo:$info), |
||
452 | (match (wip_match_opcode G_ADD):$root, |
||
453 | [{ return Helper.matchSimplifyAddToSub(*${root}, ${info}); }]), |
||
454 | (apply [{ Helper.applySimplifyAddToSub(*${root}, ${info});}]) |
||
455 | >; |
||
456 | |||
457 | // Fold fp_op(cst) to the constant result of the floating point operation. |
||
458 | def constant_fp_op_matchinfo: GIDefMatchData<"std::optional<APFloat>">; |
||
459 | def constant_fp_op: GICombineRule < |
||
460 | (defs root:$root, constant_fp_op_matchinfo:$info), |
||
461 | (match (wip_match_opcode G_FNEG, G_FABS, G_FPTRUNC, G_FSQRT, G_FLOG2):$root, |
||
462 | [{ return Helper.matchCombineConstantFoldFpUnary(*${root}, ${info}); }]), |
||
463 | (apply [{ Helper.applyCombineConstantFoldFpUnary(*${root}, ${info}); }]) |
||
464 | >; |
||
465 | |||
466 | // Fold int2ptr(ptr2int(x)) -> x |
||
467 | def p2i_to_i2p: GICombineRule< |
||
468 | (defs root:$root, register_matchinfo:$info), |
||
469 | (match (wip_match_opcode G_INTTOPTR):$root, |
||
470 | [{ return Helper.matchCombineI2PToP2I(*${root}, ${info}); }]), |
||
471 | (apply [{ Helper.applyCombineI2PToP2I(*${root}, ${info}); }]) |
||
472 | >; |
||
473 | |||
474 | // Fold ptr2int(int2ptr(x)) -> x |
||
475 | def i2p_to_p2i: GICombineRule< |
||
476 | (defs root:$dst, register_matchinfo:$info), |
||
477 | (match (G_INTTOPTR $t, $ptr), |
||
478 | (G_PTRTOINT $dst, $t):$mi, |
||
479 | [{ ${info} = ${ptr}.getReg(); }]), |
||
480 | (apply [{ Helper.applyCombineP2IToI2P(*${mi}, ${info}); }]) |
||
481 | >; |
||
482 | |||
483 | // Fold add ptrtoint(x), y -> ptrtoint (ptr_add x), y |
||
484 | def add_p2i_to_ptradd_matchinfo : GIDefMatchData<"std::pair<Register, bool>">; |
||
485 | def add_p2i_to_ptradd : GICombineRule< |
||
486 | (defs root:$root, add_p2i_to_ptradd_matchinfo:$info), |
||
487 | (match (wip_match_opcode G_ADD):$root, |
||
488 | [{ return Helper.matchCombineAddP2IToPtrAdd(*${root}, ${info}); }]), |
||
489 | (apply [{ Helper.applyCombineAddP2IToPtrAdd(*${root}, ${info}); }]) |
||
490 | >; |
||
491 | |||
492 | // Fold (ptr_add (int2ptr C1), C2) -> C1 + C2 |
||
493 | def const_ptradd_to_i2p_matchinfo : GIDefMatchData<"APInt">; |
||
494 | def const_ptradd_to_i2p: GICombineRule< |
||
495 | (defs root:$root, const_ptradd_to_i2p_matchinfo:$info), |
||
496 | (match (wip_match_opcode G_PTR_ADD):$root, |
||
497 | [{ return Helper.matchCombineConstPtrAddToI2P(*${root}, ${info}); }]), |
||
498 | (apply [{ Helper.applyCombineConstPtrAddToI2P(*${root}, ${info}); }]) |
||
499 | >; |
||
500 | |||
501 | // Simplify: (logic_op (op x...), (op y...)) -> (op (logic_op x, y)) |
||
502 | def hoist_logic_op_with_same_opcode_hands: GICombineRule < |
||
503 | (defs root:$root, instruction_steps_matchdata:$info), |
||
504 | (match (wip_match_opcode G_AND, G_OR, G_XOR):$root, |
||
505 | [{ return Helper.matchHoistLogicOpWithSameOpcodeHands(*${root}, ${info}); }]), |
||
506 | (apply [{ Helper.applyBuildInstructionSteps(*${root}, ${info});}]) |
||
507 | >; |
||
508 | |||
509 | // Fold ashr (shl x, C), C -> sext_inreg (C) |
||
510 | def shl_ashr_to_sext_inreg_matchinfo : GIDefMatchData<"std::tuple<Register, int64_t>">; |
||
511 | def shl_ashr_to_sext_inreg : GICombineRule< |
||
512 | (defs root:$root, shl_ashr_to_sext_inreg_matchinfo:$info), |
||
513 | (match (wip_match_opcode G_ASHR): $root, |
||
514 | [{ return Helper.matchAshrShlToSextInreg(*${root}, ${info}); }]), |
||
515 | (apply [{ Helper.applyAshShlToSextInreg(*${root}, ${info});}]) |
||
516 | >; |
||
517 | |||
518 | // Fold and(and(x, C1), C2) -> C1&C2 ? and(x, C1&C2) : 0 |
||
519 | def overlapping_and: GICombineRule < |
||
520 | (defs root:$root, build_fn_matchinfo:$info), |
||
521 | (match (wip_match_opcode G_AND):$root, |
||
522 | [{ return Helper.matchOverlappingAnd(*${root}, ${info}); }]), |
||
523 | (apply [{ Helper.applyBuildFn(*${root}, ${info}); }]) |
||
524 | >; |
||
525 | |||
526 | // Fold (x & y) -> x or (x & y) -> y when (x & y) is known to equal x or equal y. |
||
527 | def redundant_and: GICombineRule < |
||
528 | (defs root:$root, register_matchinfo:$matchinfo), |
||
529 | (match (wip_match_opcode G_AND):$root, |
||
530 | [{ return Helper.matchRedundantAnd(*${root}, ${matchinfo}); }]), |
||
531 | (apply [{ return Helper.replaceSingleDefInstWithReg(*${root}, ${matchinfo}); }]) |
||
532 | >; |
||
533 | |||
534 | // Fold (x | y) -> x or (x | y) -> y when (x | y) is known to equal x or equal y. |
||
535 | def redundant_or: GICombineRule < |
||
536 | (defs root:$root, register_matchinfo:$matchinfo), |
||
537 | (match (wip_match_opcode G_OR):$root, |
||
538 | [{ return Helper.matchRedundantOr(*${root}, ${matchinfo}); }]), |
||
539 | (apply [{ return Helper.replaceSingleDefInstWithReg(*${root}, ${matchinfo}); }]) |
||
540 | >; |
||
541 | |||
542 | // If the input is already sign extended, just drop the extension. |
||
543 | // sext_inreg x, K -> |
||
544 | // if computeNumSignBits(x) >= (x.getScalarSizeInBits() - K + 1) |
||
545 | def redundant_sext_inreg: GICombineRule < |
||
546 | (defs root:$root), |
||
547 | (match (wip_match_opcode G_SEXT_INREG):$root, |
||
548 | [{ return Helper.matchRedundantSExtInReg(*${root}); }]), |
||
549 | (apply [{ return Helper.replaceSingleDefInstWithOperand(*${root}, 1); }]) |
||
550 | >; |
||
551 | |||
552 | // Fold (anyext (trunc x)) -> x if the source type is same as |
||
553 | // the destination type. |
||
554 | def anyext_trunc_fold: GICombineRule < |
||
555 | (defs root:$root, register_matchinfo:$matchinfo), |
||
556 | (match (wip_match_opcode G_ANYEXT):$root, |
||
557 | [{ return Helper.matchCombineAnyExtTrunc(*${root}, ${matchinfo}); }]), |
||
558 | (apply [{ return Helper.replaceSingleDefInstWithReg(*${root}, ${matchinfo}); }]) |
||
559 | >; |
||
560 | |||
561 | // Fold (zext (trunc x)) -> x if the source type is same as the destination type |
||
562 | // and truncated bits are known to be zero. |
||
563 | def zext_trunc_fold_matchinfo : GIDefMatchData<"Register">; |
||
564 | def zext_trunc_fold: GICombineRule < |
||
565 | (defs root:$root, zext_trunc_fold_matchinfo:$matchinfo), |
||
566 | (match (wip_match_opcode G_ZEXT):$root, |
||
567 | [{ return Helper.matchCombineZextTrunc(*${root}, ${matchinfo}); }]), |
||
568 | (apply [{ return Helper.replaceSingleDefInstWithReg(*${root}, ${matchinfo}); }]) |
||
569 | >; |
||
570 | |||
571 | // Fold ([asz]ext ([asz]ext x)) -> ([asz]ext x). |
||
572 | def ext_ext_fold_matchinfo : GIDefMatchData<"std::tuple<Register, unsigned>">; |
||
573 | def ext_ext_fold: GICombineRule < |
||
574 | (defs root:$root, ext_ext_fold_matchinfo:$matchinfo), |
||
575 | (match (wip_match_opcode G_ANYEXT, G_SEXT, G_ZEXT):$root, |
||
576 | [{ return Helper.matchCombineExtOfExt(*${root}, ${matchinfo}); }]), |
||
577 | (apply [{ Helper.applyCombineExtOfExt(*${root}, ${matchinfo}); }]) |
||
578 | >; |
||
579 | |||
580 | def not_cmp_fold_matchinfo : GIDefMatchData<"SmallVector<Register, 4>">; |
||
581 | def not_cmp_fold : GICombineRule< |
||
582 | (defs root:$d, not_cmp_fold_matchinfo:$info), |
||
583 | (match (wip_match_opcode G_XOR): $d, |
||
584 | [{ return Helper.matchNotCmp(*${d}, ${info}); }]), |
||
585 | (apply [{ Helper.applyNotCmp(*${d}, ${info}); }]) |
||
586 | >; |
||
587 | |||
588 | // Fold (fneg (fneg x)) -> x. |
||
589 | def fneg_fneg_fold: GICombineRule < |
||
590 | (defs root:$dst, register_matchinfo:$matchinfo), |
||
591 | (match (G_FNEG $t, $src), |
||
592 | (G_FNEG $dst, $t):$mi, |
||
593 | [{ ${matchinfo} = ${src}.getReg(); }]), |
||
594 | (apply [{ return Helper.replaceSingleDefInstWithReg(*${mi}, ${matchinfo}); }]) |
||
595 | >; |
||
596 | |||
597 | // Fold (unmerge(merge x, y, z)) -> z, y, z. |
||
598 | def unmerge_merge_matchinfo : GIDefMatchData<"SmallVector<Register, 8>">; |
||
599 | def unmerge_merge : GICombineRule< |
||
600 | (defs root:$d, unmerge_merge_matchinfo:$info), |
||
601 | (match (wip_match_opcode G_UNMERGE_VALUES): $d, |
||
602 | [{ return Helper.matchCombineUnmergeMergeToPlainValues(*${d}, ${info}); }]), |
||
603 | (apply [{ Helper.applyCombineUnmergeMergeToPlainValues(*${d}, ${info}); }]) |
||
604 | >; |
||
605 | |||
606 | // Fold merge(unmerge). |
||
607 | def merge_unmerge : GICombineRule< |
||
608 | (defs root:$d, register_matchinfo:$matchinfo), |
||
609 | (match (wip_match_opcode G_MERGE_VALUES):$d, |
||
610 | [{ return Helper.matchCombineMergeUnmerge(*${d}, ${matchinfo}); }]), |
||
611 | (apply [{ Helper.replaceSingleDefInstWithReg(*${d}, ${matchinfo}); }]) |
||
612 | >; |
||
613 | |||
614 | // Fold (fabs (fneg x)) -> (fabs x). |
||
615 | def fabs_fneg_fold: GICombineRule < |
||
616 | (defs root:$root, build_fn_matchinfo:$matchinfo), |
||
617 | (match (wip_match_opcode G_FABS):$root, |
||
618 | [{ return Helper.matchCombineFAbsOfFNeg(*${root}, ${matchinfo}); }]), |
||
619 | (apply [{ Helper.applyBuildFnNoErase(*${root}, ${matchinfo}); }])>; |
||
620 | |||
621 | // Fold (unmerge cst) -> cst1, cst2, ... |
||
622 | def unmerge_cst_matchinfo : GIDefMatchData<"SmallVector<APInt, 8>">; |
||
623 | def unmerge_cst : GICombineRule< |
||
624 | (defs root:$d, unmerge_cst_matchinfo:$info), |
||
625 | (match (wip_match_opcode G_UNMERGE_VALUES): $d, |
||
626 | [{ return Helper.matchCombineUnmergeConstant(*${d}, ${info}); }]), |
||
627 | (apply [{ Helper.applyCombineUnmergeConstant(*${d}, ${info}); }]) |
||
628 | >; |
||
629 | |||
630 | // Fold (unmerge undef) -> undef, undef, ... |
||
631 | def unmerge_undef : GICombineRule< |
||
632 | (defs root:$root, build_fn_matchinfo:$info), |
||
633 | (match (wip_match_opcode G_UNMERGE_VALUES): $root, |
||
634 | [{ return Helper.matchCombineUnmergeUndef(*${root}, ${info}); }]), |
||
635 | (apply [{ Helper.applyBuildFn(*${root}, ${info}); }]) |
||
636 | >; |
||
637 | |||
638 | // Transform x,y<dead> = unmerge z -> x = trunc z. |
||
639 | def unmerge_dead_to_trunc : GICombineRule< |
||
640 | (defs root:$d), |
||
641 | (match (wip_match_opcode G_UNMERGE_VALUES): $d, |
||
642 | [{ return Helper.matchCombineUnmergeWithDeadLanesToTrunc(*${d}); }]), |
||
643 | (apply [{ Helper.applyCombineUnmergeWithDeadLanesToTrunc(*${d}); }]) |
||
644 | >; |
||
645 | |||
646 | // Transform x,y = unmerge(zext(z)) -> x = zext z; y = 0. |
||
647 | def unmerge_zext_to_zext : GICombineRule< |
||
648 | (defs root:$d), |
||
649 | (match (wip_match_opcode G_UNMERGE_VALUES): $d, |
||
650 | [{ return Helper.matchCombineUnmergeZExtToZExt(*${d}); }]), |
||
651 | (apply [{ Helper.applyCombineUnmergeZExtToZExt(*${d}); }]) |
||
652 | >; |
||
653 | |||
654 | // Fold trunc ([asz]ext x) -> x or ([asz]ext x) or (trunc x). |
||
655 | def trunc_ext_fold_matchinfo : GIDefMatchData<"std::pair<Register, unsigned>">; |
||
656 | def trunc_ext_fold: GICombineRule < |
||
657 | (defs root:$root, trunc_ext_fold_matchinfo:$matchinfo), |
||
658 | (match (wip_match_opcode G_TRUNC):$root, |
||
659 | [{ return Helper.matchCombineTruncOfExt(*${root}, ${matchinfo}); }]), |
||
660 | (apply [{ Helper.applyCombineTruncOfExt(*${root}, ${matchinfo}); }]) |
||
661 | >; |
||
662 | |||
663 | // Under certain conditions, transform: |
||
664 | // trunc (shl x, K) -> shl (trunc x), K// |
||
665 | // trunc ([al]shr x, K) -> (trunc ([al]shr (trunc x), K)) |
||
666 | def trunc_shift_matchinfo : GIDefMatchData<"std::pair<MachineInstr*, LLT>">; |
||
667 | def trunc_shift: GICombineRule < |
||
668 | (defs root:$root, trunc_shift_matchinfo:$matchinfo), |
||
669 | (match (wip_match_opcode G_TRUNC):$root, |
||
670 | [{ return Helper.matchCombineTruncOfShift(*${root}, ${matchinfo}); }]), |
||
671 | (apply [{ Helper.applyCombineTruncOfShift(*${root}, ${matchinfo}); }]) |
||
672 | >; |
||
673 | |||
674 | // Transform (mul x, -1) -> (sub 0, x) |
||
675 | def mul_by_neg_one: GICombineRule < |
||
676 | (defs root:$root), |
||
677 | (match (wip_match_opcode G_MUL):$root, |
||
678 | [{ return Helper.matchConstantOp(${root}->getOperand(2), -1); }]), |
||
679 | (apply [{ Helper.applyCombineMulByNegativeOne(*${root}); }]) |
||
680 | >; |
||
681 | |||
682 | // Fold (xor (and x, y), y) -> (and (not x), y) |
||
683 | def xor_of_and_with_same_reg_matchinfo : |
||
684 | GIDefMatchData<"std::pair<Register, Register>">; |
||
685 | def xor_of_and_with_same_reg: GICombineRule < |
||
686 | (defs root:$root, xor_of_and_with_same_reg_matchinfo:$matchinfo), |
||
687 | (match (wip_match_opcode G_XOR):$root, |
||
688 | [{ return Helper.matchXorOfAndWithSameReg(*${root}, ${matchinfo}); }]), |
||
689 | (apply [{ Helper.applyXorOfAndWithSameReg(*${root}, ${matchinfo}); }]) |
||
690 | >; |
||
691 | |||
692 | // Transform (ptr_add 0, x) -> (int_to_ptr x) |
||
693 | def ptr_add_with_zero: GICombineRule< |
||
694 | (defs root:$root), |
||
695 | (match (wip_match_opcode G_PTR_ADD):$root, |
||
696 | [{ return Helper.matchPtrAddZero(*${root}); }]), |
||
697 | (apply [{ Helper.applyPtrAddZero(*${root}); }])>; |
||
698 | |||
699 | def regs_small_vec : GIDefMatchData<"SmallVector<Register, 4>">; |
||
700 | def combine_insert_vec_elts_build_vector : GICombineRule< |
||
701 | (defs root:$root, regs_small_vec:$info), |
||
702 | (match (wip_match_opcode G_INSERT_VECTOR_ELT):$root, |
||
703 | [{ return Helper.matchCombineInsertVecElts(*${root}, ${info}); }]), |
||
704 | (apply [{ Helper.applyCombineInsertVecElts(*${root}, ${info}); }])>; |
||
705 | |||
706 | def load_or_combine : GICombineRule< |
||
707 | (defs root:$root, build_fn_matchinfo:$info), |
||
708 | (match (wip_match_opcode G_OR):$root, |
||
709 | [{ return Helper.matchLoadOrCombine(*${root}, ${info}); }]), |
||
710 | (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>; |
||
711 | |||
712 | |||
713 | def truncstore_merge_matcdata : GIDefMatchData<"MergeTruncStoresInfo">; |
||
714 | def truncstore_merge : GICombineRule< |
||
715 | (defs root:$root, truncstore_merge_matcdata:$info), |
||
716 | (match (wip_match_opcode G_STORE):$root, |
||
717 | [{ return Helper.matchTruncStoreMerge(*${root}, ${info}); }]), |
||
718 | (apply [{ Helper.applyTruncStoreMerge(*${root}, ${info}); }])>; |
||
719 | |||
720 | def extend_through_phis_matchdata: GIDefMatchData<"MachineInstr*">; |
||
721 | def extend_through_phis : GICombineRule< |
||
722 | (defs root:$root, extend_through_phis_matchdata:$matchinfo), |
||
723 | (match (wip_match_opcode G_PHI):$root, |
||
724 | [{ return Helper.matchExtendThroughPhis(*${root}, ${matchinfo}); }]), |
||
725 | (apply [{ Helper.applyExtendThroughPhis(*${root}, ${matchinfo}); }])>; |
||
726 | |||
727 | // Currently only the one combine above. |
||
728 | def insert_vec_elt_combines : GICombineGroup< |
||
729 | [combine_insert_vec_elts_build_vector]>; |
||
730 | |||
731 | def extract_vec_elt_build_vec : GICombineRule< |
||
732 | (defs root:$root, register_matchinfo:$matchinfo), |
||
733 | (match (wip_match_opcode G_EXTRACT_VECTOR_ELT):$root, |
||
734 | [{ return Helper.matchExtractVecEltBuildVec(*${root}, ${matchinfo}); }]), |
||
735 | (apply [{ Helper.applyExtractVecEltBuildVec(*${root}, ${matchinfo}); }])>; |
||
736 | |||
737 | // Fold away full elt extracts from a build_vector. |
||
738 | def extract_all_elts_from_build_vector_matchinfo : |
||
739 | GIDefMatchData<"SmallVector<std::pair<Register, MachineInstr*>>">; |
||
740 | def extract_all_elts_from_build_vector : GICombineRule< |
||
741 | (defs root:$root, extract_all_elts_from_build_vector_matchinfo:$matchinfo), |
||
742 | (match (wip_match_opcode G_BUILD_VECTOR):$root, |
||
743 | [{ return Helper.matchExtractAllEltsFromBuildVector(*${root}, ${matchinfo}); }]), |
||
744 | (apply [{ Helper.applyExtractAllEltsFromBuildVector(*${root}, ${matchinfo}); }])>; |
||
745 | |||
746 | def extract_vec_elt_combines : GICombineGroup<[ |
||
747 | extract_vec_elt_build_vec, |
||
748 | extract_all_elts_from_build_vector]>; |
||
749 | |||
750 | def funnel_shift_from_or_shift : GICombineRule< |
||
751 | (defs root:$root, build_fn_matchinfo:$info), |
||
752 | (match (wip_match_opcode G_OR):$root, |
||
753 | [{ return Helper.matchOrShiftToFunnelShift(*${root}, ${info}); }]), |
||
754 | (apply [{ Helper.applyBuildFn(*${root}, ${info}); }]) |
||
755 | >; |
||
756 | |||
757 | def funnel_shift_to_rotate : GICombineRule< |
||
758 | (defs root:$root), |
||
759 | (match (wip_match_opcode G_FSHL, G_FSHR):$root, |
||
760 | [{ return Helper.matchFunnelShiftToRotate(*${root}); }]), |
||
761 | (apply [{ Helper.applyFunnelShiftToRotate(*${root}); }]) |
||
762 | >; |
||
763 | |||
764 | def rotate_out_of_range : GICombineRule< |
||
765 | (defs root:$root), |
||
766 | (match (wip_match_opcode G_ROTR, G_ROTL):$root, |
||
767 | [{ return Helper.matchRotateOutOfRange(*${root}); }]), |
||
768 | (apply [{ Helper.applyRotateOutOfRange(*${root}); }]) |
||
769 | >; |
||
770 | |||
771 | def icmp_to_true_false_known_bits : GICombineRule< |
||
772 | (defs root:$d, int64_matchinfo:$matchinfo), |
||
773 | (match (wip_match_opcode G_ICMP):$d, |
||
774 | [{ return Helper.matchICmpToTrueFalseKnownBits(*${d}, ${matchinfo}); }]), |
||
775 | (apply [{ Helper.replaceInstWithConstant(*${d}, ${matchinfo}); }])>; |
||
776 | |||
777 | def icmp_to_lhs_known_bits : GICombineRule< |
||
778 | (defs root:$root, build_fn_matchinfo:$info), |
||
779 | (match (wip_match_opcode G_ICMP):$root, |
||
780 | [{ return Helper.matchICmpToLHSKnownBits(*${root}, ${info}); }]), |
||
781 | (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>; |
||
782 | |||
783 | def redundant_binop_in_equality : GICombineRule< |
||
784 | (defs root:$root, build_fn_matchinfo:$info), |
||
785 | (match (wip_match_opcode G_ICMP):$root, |
||
786 | [{ return Helper.matchRedundantBinOpInEquality(*${root}, ${info}); }]), |
||
787 | (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>; |
||
788 | |||
789 | def and_or_disjoint_mask : GICombineRule< |
||
790 | (defs root:$root, build_fn_matchinfo:$info), |
||
791 | (match (wip_match_opcode G_AND):$root, |
||
792 | [{ return Helper.matchAndOrDisjointMask(*${root}, ${info}); }]), |
||
793 | (apply [{ Helper.applyBuildFnNoErase(*${root}, ${info}); }])>; |
||
794 | |||
795 | def bitfield_extract_from_and : GICombineRule< |
||
796 | (defs root:$root, build_fn_matchinfo:$info), |
||
797 | (match (wip_match_opcode G_AND):$root, |
||
798 | [{ return Helper.matchBitfieldExtractFromAnd(*${root}, ${info}); }]), |
||
799 | (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>; |
||
800 | |||
801 | def funnel_shift_combines : GICombineGroup<[funnel_shift_from_or_shift, |
||
802 | funnel_shift_to_rotate]>; |
||
803 | |||
804 | def bitfield_extract_from_sext_inreg : GICombineRule< |
||
805 | (defs root:$root, build_fn_matchinfo:$info), |
||
806 | (match (wip_match_opcode G_SEXT_INREG):$root, |
||
807 | [{ return Helper.matchBitfieldExtractFromSExtInReg(*${root}, ${info}); }]), |
||
808 | (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>; |
||
809 | |||
810 | def bitfield_extract_from_shr : GICombineRule< |
||
811 | (defs root:$root, build_fn_matchinfo:$info), |
||
812 | (match (wip_match_opcode G_ASHR, G_LSHR):$root, |
||
813 | [{ return Helper.matchBitfieldExtractFromShr(*${root}, ${info}); }]), |
||
814 | (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>; |
||
815 | |||
816 | def bitfield_extract_from_shr_and : GICombineRule< |
||
817 | (defs root:$root, build_fn_matchinfo:$info), |
||
818 | (match (wip_match_opcode G_ASHR, G_LSHR):$root, |
||
819 | [{ return Helper.matchBitfieldExtractFromShrAnd(*${root}, ${info}); }]), |
||
820 | (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>; |
||
821 | |||
822 | def form_bitfield_extract : GICombineGroup<[bitfield_extract_from_sext_inreg, |
||
823 | bitfield_extract_from_and, |
||
824 | bitfield_extract_from_shr, |
||
825 | bitfield_extract_from_shr_and]>; |
||
826 | |||
827 | def udiv_by_const : GICombineRule< |
||
828 | (defs root:$root), |
||
829 | (match (wip_match_opcode G_UDIV):$root, |
||
830 | [{ return Helper.matchUDivByConst(*${root}); }]), |
||
831 | (apply [{ Helper.applyUDivByConst(*${root}); }])>; |
||
832 | |||
833 | def sdiv_by_const : GICombineRule< |
||
834 | (defs root:$root), |
||
835 | (match (wip_match_opcode G_SDIV):$root, |
||
836 | [{ return Helper.matchSDivByConst(*${root}); }]), |
||
837 | (apply [{ Helper.applySDivByConst(*${root}); }])>; |
||
838 | |||
839 | def intdiv_combines : GICombineGroup<[udiv_by_const, sdiv_by_const]>; |
||
840 | |||
841 | def reassoc_ptradd : GICombineRule< |
||
842 | (defs root:$root, build_fn_matchinfo:$matchinfo), |
||
843 | (match (wip_match_opcode G_PTR_ADD):$root, |
||
844 | [{ return Helper.matchReassocPtrAdd(*${root}, ${matchinfo}); }]), |
||
845 | (apply [{ Helper.applyBuildFnNoErase(*${root}, ${matchinfo}); }])>; |
||
846 | |||
847 | def reassocs : GICombineGroup<[reassoc_ptradd]>; |
||
848 | |||
849 | // Constant fold operations. |
||
850 | def constant_fold : GICombineRule< |
||
851 | (defs root:$d, apint_matchinfo:$matchinfo), |
||
852 | (match (wip_match_opcode G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR):$d, |
||
853 | [{ return Helper.matchConstantFold(*${d}, ${matchinfo}); }]), |
||
854 | (apply [{ Helper.replaceInstWithConstant(*${d}, ${matchinfo}); }])>; |
||
855 | |||
856 | def mulo_by_2: GICombineRule< |
||
857 | (defs root:$root, build_fn_matchinfo:$matchinfo), |
||
858 | (match (wip_match_opcode G_UMULO, G_SMULO):$root, |
||
859 | [{ return Helper.matchMulOBy2(*${root}, ${matchinfo}); }]), |
||
860 | (apply [{ Helper.applyBuildFnNoErase(*${root}, ${matchinfo}); }])>; |
||
861 | |||
862 | def mulo_by_0: GICombineRule< |
||
863 | (defs root:$root, build_fn_matchinfo:$matchinfo), |
||
864 | (match (wip_match_opcode G_UMULO, G_SMULO):$root, |
||
865 | [{ return Helper.matchMulOBy0(*${root}, ${matchinfo}); }]), |
||
866 | (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>; |
||
867 | |||
868 | def addo_by_0: GICombineRule< |
||
869 | (defs root:$root, build_fn_matchinfo:$matchinfo), |
||
870 | (match (wip_match_opcode G_UADDO, G_SADDO):$root, |
||
871 | [{ return Helper.matchAddOBy0(*${root}, ${matchinfo}); }]), |
||
872 | (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>; |
||
873 | |||
874 | // Transform (uadde x, y, 0) -> (uaddo x, y) |
||
875 | // (sadde x, y, 0) -> (saddo x, y) |
||
876 | // (usube x, y, 0) -> (usubo x, y) |
||
877 | // (ssube x, y, 0) -> (ssubo x, y) |
||
878 | def adde_to_addo: GICombineRule< |
||
879 | (defs root:$root, build_fn_matchinfo:$matchinfo), |
||
880 | (match (wip_match_opcode G_UADDE, G_SADDE, G_USUBE, G_SSUBE):$root, |
||
881 | [{ return Helper.matchAddEToAddO(*${root}, ${matchinfo}); }]), |
||
882 | (apply [{ Helper.applyBuildFnNoErase(*${root}, ${matchinfo}); }])>; |
||
883 | |||
884 | def mulh_to_lshr : GICombineRule< |
||
885 | (defs root:$root), |
||
886 | (match (wip_match_opcode G_UMULH):$root, |
||
887 | [{ return Helper.matchUMulHToLShr(*${root}); }]), |
||
888 | (apply [{ Helper.applyUMulHToLShr(*${root}); }])>; |
||
889 | |||
890 | def mulh_combines : GICombineGroup<[mulh_to_lshr]>; |
||
891 | |||
892 | def redundant_neg_operands: GICombineRule< |
||
893 | (defs root:$root, build_fn_matchinfo:$matchinfo), |
||
894 | (match (wip_match_opcode G_FADD, G_FSUB, G_FMUL, G_FDIV, G_FMAD, G_FMA):$root, |
||
895 | [{ return Helper.matchRedundantNegOperands(*${root}, ${matchinfo}); }]), |
||
896 | (apply [{ Helper.applyBuildFnNoErase(*${root}, ${matchinfo}); }])>; |
||
897 | |||
898 | // Transform (fsub +-0.0, X) -> (fneg X) |
||
899 | def fsub_to_fneg: GICombineRule< |
||
900 | (defs root:$root, register_matchinfo:$matchinfo), |
||
901 | (match (wip_match_opcode G_FSUB):$root, |
||
902 | [{ return Helper.matchFsubToFneg(*${root}, ${matchinfo}); }]), |
||
903 | (apply [{ Helper.applyFsubToFneg(*${root}, ${matchinfo}); }])>; |
||
904 | |||
905 | // Transform (fadd x, (fmul y, z)) -> (fma y, z, x) |
||
906 | // (fadd x, (fmul y, z)) -> (fmad y, z, x) |
||
907 | // Transform (fadd (fmul x, y), z) -> (fma x, y, z) |
||
908 | // (fadd (fmul x, y), z) -> (fmad x, y, z) |
||
909 | def combine_fadd_fmul_to_fmad_or_fma: GICombineRule< |
||
910 | (defs root:$root, build_fn_matchinfo:$info), |
||
911 | (match (wip_match_opcode G_FADD):$root, |
||
912 | [{ return Helper.matchCombineFAddFMulToFMadOrFMA(*${root}, |
||
913 | ${info}); }]), |
||
914 | (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>; |
||
915 | |||
916 | // Transform (fadd (fpext (fmul x, y)), z) -> (fma (fpext x), (fpext y), z) |
||
917 | // -> (fmad (fpext x), (fpext y), z) |
||
918 | // Transform (fadd x, (fpext (fmul y, z))) -> (fma (fpext y), (fpext z), x) |
||
919 | // -> (fmad (fpext y), (fpext z), x) |
||
920 | def combine_fadd_fpext_fmul_to_fmad_or_fma: GICombineRule< |
||
921 | (defs root:$root, build_fn_matchinfo:$info), |
||
922 | (match (wip_match_opcode G_FADD):$root, |
||
923 | [{ return Helper.matchCombineFAddFpExtFMulToFMadOrFMA(*${root}, |
||
924 | ${info}); }]), |
||
925 | (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>; |
||
926 | |||
927 | // Transform (fadd (fma x, y, (fmul z, u)), v) -> (fma x, y, (fma z, u, v)) |
||
928 | // (fadd (fmad x, y, (fmul z, u)), v) -> (fmad x, y, (fmad z, u, v)) |
||
929 | // Transform (fadd v, (fma x, y, (fmul z, u))) -> (fma x, y, (fma z, u, v)) |
||
930 | // (fadd v, (fmad x, y, (fmul z, u))) -> (fmad x, y, (fmad z, u, v)) |
||
931 | def combine_fadd_fma_fmul_to_fmad_or_fma: GICombineRule< |
||
932 | (defs root:$root, build_fn_matchinfo:$info), |
||
933 | (match (wip_match_opcode G_FADD):$root, |
||
934 | [{ return Helper.matchCombineFAddFMAFMulToFMadOrFMA(*${root}, |
||
935 | ${info}); }]), |
||
936 | (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>; |
||
937 | |||
938 | // Transform (fadd (fma x, y, (fpext (fmul u, v))), z) -> |
||
939 | // (fma x, y, (fma (fpext u), (fpext v), z)) |
||
940 | def combine_fadd_fpext_fma_fmul_to_fmad_or_fma: GICombineRule< |
||
941 | (defs root:$root, build_fn_matchinfo:$info), |
||
942 | (match (wip_match_opcode G_FADD):$root, |
||
943 | [{ return Helper.matchCombineFAddFpExtFMulToFMadOrFMAAggressive( |
||
944 | *${root}, ${info}); }]), |
||
945 | (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>; |
||
946 | |||
947 | // Transform (fsub (fmul x, y), z) -> (fma x, y, -z) |
||
948 | // -> (fmad x, y, -z) |
||
949 | def combine_fsub_fmul_to_fmad_or_fma: GICombineRule< |
||
950 | (defs root:$root, build_fn_matchinfo:$info), |
||
951 | (match (wip_match_opcode G_FSUB):$root, |
||
952 | [{ return Helper.matchCombineFSubFMulToFMadOrFMA(*${root}, |
||
953 | ${info}); }]), |
||
954 | (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>; |
||
955 | |||
956 | // Transform (fsub (fneg (fmul, x, y)), z) -> (fma (fneg x), y, (fneg z)) |
||
957 | // (fsub x, (fneg (fmul, y, z))) -> (fma y, z, x) |
||
958 | def combine_fsub_fneg_fmul_to_fmad_or_fma: GICombineRule< |
||
959 | (defs root:$root, build_fn_matchinfo:$info), |
||
960 | (match (wip_match_opcode G_FSUB):$root, |
||
961 | [{ return Helper.matchCombineFSubFNegFMulToFMadOrFMA(*${root}, |
||
962 | ${info}); }]), |
||
963 | (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>; |
||
964 | |||
965 | // Transform (fsub (fpext (fmul x, y)), z) -> |
||
966 | // (fma (fpext x), (fpext y), (fneg z)) |
||
967 | def combine_fsub_fpext_fmul_to_fmad_or_fma: GICombineRule< |
||
968 | (defs root:$root, build_fn_matchinfo:$info), |
||
969 | (match (wip_match_opcode G_FSUB):$root, |
||
970 | [{ return Helper.matchCombineFSubFpExtFMulToFMadOrFMA(*${root}, |
||
971 | ${info}); }]), |
||
972 | (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>; |
||
973 | |||
974 | // Transform (fsub (fneg (fpext (fmul x, y))), z) -> |
||
975 | // (fneg (fma (fpext x), (fpext y), z)) |
||
976 | def combine_fsub_fpext_fneg_fmul_to_fmad_or_fma: GICombineRule< |
||
977 | (defs root:$root, build_fn_matchinfo:$info), |
||
978 | (match (wip_match_opcode G_FSUB):$root, |
||
979 | [{ return Helper.matchCombineFSubFpExtFNegFMulToFMadOrFMA( |
||
980 | *${root}, ${info}); }]), |
||
981 | (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>; |
||
982 | |||
983 | def combine_minmax_nan: GICombineRule< |
||
984 | (defs root:$root, unsigned_matchinfo:$info), |
||
985 | (match (wip_match_opcode G_FMINNUM, G_FMAXNUM, G_FMINIMUM, G_FMAXIMUM):$root, |
||
986 | [{ return Helper.matchCombineFMinMaxNaN(*${root}, ${info}); }]), |
||
987 | (apply [{ Helper.replaceSingleDefInstWithOperand(*${root}, ${info}); }])>; |
||
988 | |||
989 | // Transform (add x, (sub y, x)) -> y |
||
990 | // Transform (add (sub y, x), x) -> y |
||
991 | def add_sub_reg: GICombineRule < |
||
992 | (defs root:$root, register_matchinfo:$matchinfo), |
||
993 | (match (wip_match_opcode G_ADD):$root, |
||
994 | [{ return Helper.matchAddSubSameReg(*${root}, ${matchinfo}); }]), |
||
995 | (apply [{ return Helper.replaceSingleDefInstWithReg(*${root}, |
||
996 | ${matchinfo}); }])>; |
||
997 | |||
998 | def buildvector_identity_fold : GICombineRule< |
||
999 | (defs root:$build_vector, register_matchinfo:$matchinfo), |
||
1000 | (match (wip_match_opcode G_BUILD_VECTOR_TRUNC, G_BUILD_VECTOR):$build_vector, |
||
1001 | [{ return Helper.matchBuildVectorIdentityFold(*${build_vector}, ${matchinfo}); }]), |
||
1002 | (apply [{ Helper.replaceSingleDefInstWithReg(*${build_vector}, ${matchinfo}); }])>; |
||
1003 | |||
1004 | def trunc_buildvector_fold : GICombineRule< |
||
1005 | (defs root:$op, register_matchinfo:$matchinfo), |
||
1006 | (match (wip_match_opcode G_TRUNC):$op, |
||
1007 | [{ return Helper.matchTruncBuildVectorFold(*${op}, ${matchinfo}); }]), |
||
1008 | (apply [{ Helper.replaceSingleDefInstWithReg(*${op}, ${matchinfo}); }])>; |
||
1009 | |||
1010 | def trunc_lshr_buildvector_fold : GICombineRule< |
||
1011 | (defs root:$op, register_matchinfo:$matchinfo), |
||
1012 | (match (wip_match_opcode G_TRUNC):$op, |
||
1013 | [{ return Helper.matchTruncLshrBuildVectorFold(*${op}, ${matchinfo}); }]), |
||
1014 | (apply [{ Helper.replaceSingleDefInstWithReg(*${op}, ${matchinfo}); }])>; |
||
1015 | |||
1016 | // Transform: |
||
1017 | // (x + y) - y -> x |
||
1018 | // (x + y) - x -> y |
||
1019 | // x - (y + x) -> 0 - y |
||
1020 | // x - (x + z) -> 0 - z |
||
1021 | def sub_add_reg: GICombineRule < |
||
1022 | (defs root:$root, build_fn_matchinfo:$matchinfo), |
||
1023 | (match (wip_match_opcode G_SUB):$root, |
||
1024 | [{ return Helper.matchSubAddSameReg(*${root}, ${matchinfo}); }]), |
||
1025 | (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>; |
||
1026 | |||
1027 | def bitcast_bitcast_fold : GICombineRule< |
||
1028 | (defs root:$dst), |
||
1029 | (match (G_BITCAST $dst, $src1):$op, (G_BITCAST $src1, $src0), |
||
1030 | [{ return MRI.getType(${src0}.getReg()) == MRI.getType(${dst}.getReg()); }]), |
||
1031 | (apply [{ Helper.replaceSingleDefInstWithReg(*${op}, ${src0}.getReg()); }])>; |
||
1032 | |||
1033 | def select_to_minmax: GICombineRule< |
||
1034 | (defs root:$root, build_fn_matchinfo:$info), |
||
1035 | (match (wip_match_opcode G_SELECT):$root, |
||
1036 | [{ return Helper.matchSimplifySelectToMinMax(*${root}, ${info}); }]), |
||
1037 | (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>; |
||
1038 | |||
1039 | // FIXME: These should use the custom predicate feature once it lands. |
||
1040 | def undef_combines : GICombineGroup<[undef_to_fp_zero, undef_to_int_zero, |
||
1041 | undef_to_negative_one, |
||
1042 | binop_left_undef_to_zero, |
||
1043 | binop_right_undef_to_undef, |
||
1044 | unary_undef_to_zero, |
||
1045 | propagate_undef_any_op, |
||
1046 | propagate_undef_all_ops, |
||
1047 | propagate_undef_shuffle_mask, |
||
1048 | erase_undef_store, |
||
1049 | unmerge_undef, |
||
1050 | insert_extract_vec_elt_out_of_bounds]>; |
||
1051 | |||
1052 | def identity_combines : GICombineGroup<[select_same_val, right_identity_zero, |
||
1053 | binop_same_val, binop_left_to_zero, |
||
1054 | binop_right_to_zero, p2i_to_i2p, |
||
1055 | i2p_to_p2i, anyext_trunc_fold, |
||
1056 | fneg_fneg_fold, right_identity_one, |
||
1057 | add_sub_reg, buildvector_identity_fold, |
||
1058 | trunc_buildvector_fold, |
||
1059 | trunc_lshr_buildvector_fold, |
||
1060 | bitcast_bitcast_fold]>; |
||
1061 | |||
1062 | def const_combines : GICombineGroup<[constant_fp_op, const_ptradd_to_i2p, |
||
1063 | overlapping_and, mulo_by_2, mulo_by_0, |
||
1064 | addo_by_0, adde_to_addo, |
||
1065 | combine_minmax_nan]>; |
||
1066 | |||
1067 | def known_bits_simplifications : GICombineGroup<[ |
||
1068 | redundant_and, redundant_sext_inreg, redundant_or, urem_pow2_to_mask, |
||
1069 | zext_trunc_fold, icmp_to_true_false_known_bits, icmp_to_lhs_known_bits, |
||
1070 | sext_inreg_to_zext_inreg]>; |
||
1071 | |||
1072 | def width_reduction_combines : GICombineGroup<[reduce_shl_of_extend, |
||
1073 | narrow_binop_feeding_and]>; |
||
1074 | |||
1075 | def phi_combines : GICombineGroup<[extend_through_phis]>; |
||
1076 | |||
1077 | def select_combines : GICombineGroup<[select_undef_cmp, select_constant_cmp, |
||
1078 | select_to_logical]>; |
||
1079 | |||
1080 | def trivial_combines : GICombineGroup<[copy_prop, mul_to_shl, add_p2i_to_ptradd, |
||
1081 | mul_by_neg_one, idempotent_prop]>; |
||
1082 | |||
1083 | def fma_combines : GICombineGroup<[combine_fadd_fmul_to_fmad_or_fma, |
||
1084 | combine_fadd_fpext_fmul_to_fmad_or_fma, combine_fadd_fma_fmul_to_fmad_or_fma, |
||
1085 | combine_fadd_fpext_fma_fmul_to_fmad_or_fma, combine_fsub_fmul_to_fmad_or_fma, |
||
1086 | combine_fsub_fneg_fmul_to_fmad_or_fma, combine_fsub_fpext_fmul_to_fmad_or_fma, |
||
1087 | combine_fsub_fpext_fneg_fmul_to_fmad_or_fma]>; |
||
1088 | |||
1089 | def all_combines : GICombineGroup<[trivial_combines, insert_vec_elt_combines, |
||
1090 | extract_vec_elt_combines, combines_for_extload, |
||
1091 | combine_indexed_load_store, undef_combines, identity_combines, phi_combines, |
||
1092 | simplify_add_to_sub, hoist_logic_op_with_same_opcode_hands, |
||
1093 | reassocs, ptr_add_immed_chain, |
||
1094 | shl_ashr_to_sext_inreg, sext_inreg_of_load, |
||
1095 | width_reduction_combines, select_combines, |
||
1096 | known_bits_simplifications, ext_ext_fold, |
||
1097 | not_cmp_fold, opt_brcond_by_inverting_cond, |
||
1098 | unmerge_merge, unmerge_cst, unmerge_dead_to_trunc, |
||
1099 | unmerge_zext_to_zext, merge_unmerge, trunc_ext_fold, trunc_shift, |
||
1100 | const_combines, xor_of_and_with_same_reg, ptr_add_with_zero, |
||
1101 | shift_immed_chain, shift_of_shifted_logic_chain, load_or_combine, |
||
1102 | truncstore_merge, div_rem_to_divrem, funnel_shift_combines, |
||
1103 | form_bitfield_extract, constant_fold, fabs_fneg_fold, |
||
1104 | intdiv_combines, mulh_combines, redundant_neg_operands, |
||
1105 | and_or_disjoint_mask, fma_combines, fold_binop_into_select, |
||
1106 | sub_add_reg, select_to_minmax, redundant_binop_in_equality, |
||
1107 | fsub_to_fneg, commute_constant_to_rhs]>; |
||
1108 | |||
1109 | // A combine group used to for prelegalizer combiners at -O0. The combines in |
||
1110 | // this group have been selected based on experiments to balance code size and |
||
1111 | // compile time performance. |
||
1112 | def optnone_combines : GICombineGroup<[trivial_combines, |
||
1113 | ptr_add_immed_chain, combines_for_extload, |
||
1114 | not_cmp_fold, opt_brcond_by_inverting_cond]>; |