xref: /freebsd/contrib/llvm-project/llvm/include/llvm/Target/GlobalISel/Combine.td (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
18bcb0991SDimitry Andric//===- Combine.td - Combine rule definitions ---------------*- tablegen -*-===//
28bcb0991SDimitry Andric//
38bcb0991SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
48bcb0991SDimitry Andric// See https://llvm.org/LICENSE.txt for license information.
58bcb0991SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
68bcb0991SDimitry Andric//
78bcb0991SDimitry Andric//===----------------------------------------------------------------------===//
88bcb0991SDimitry Andric//
98bcb0991SDimitry Andric// Declare GlobalISel combine rules and provide mechanisms to opt-out.
108bcb0991SDimitry Andric//
118bcb0991SDimitry Andric//===----------------------------------------------------------------------===//
128bcb0991SDimitry Andric
135f757f3fSDimitry Andric
145f757f3fSDimitry Andric//===----------------------------------------------------------------------===//
155f757f3fSDimitry Andric// Base Classes
165f757f3fSDimitry Andric//
175f757f3fSDimitry Andric// These are the core classes that the combiner backend relies on.
185f757f3fSDimitry Andric//===----------------------------------------------------------------------===//
195f757f3fSDimitry Andric
205f757f3fSDimitry Andric/// All arguments of the defs operator must be subclasses of GIDefKind or
215f757f3fSDimitry Andric/// sub-dags whose operator is GIDefKindWithArgs.
225f757f3fSDimitry Andricclass GIDefKind;
235f757f3fSDimitry Andricclass GIDefKindWithArgs;
245f757f3fSDimitry Andric
255f757f3fSDimitry Andric/// Declare a root node. There must be at least one of these in every combine
265f757f3fSDimitry Andric/// rule.
275f757f3fSDimitry Andricdef root : GIDefKind;
285f757f3fSDimitry Andric
295f757f3fSDimitry Andricdef defs;
305f757f3fSDimitry Andric
315f757f3fSDimitry Andricdef pattern;
325f757f3fSDimitry Andricdef match;
335f757f3fSDimitry Andricdef apply;
345f757f3fSDimitry Andric
355f757f3fSDimitry Andricdef wip_match_opcode;
365f757f3fSDimitry Andric
378bcb0991SDimitry Andric// Common base class for GICombineRule and GICombineGroup.
388bcb0991SDimitry Andricclass GICombine {
398bcb0991SDimitry Andric  // See GICombineGroup. We only declare it here to make the tablegen pass
408bcb0991SDimitry Andric  // simpler.
418bcb0991SDimitry Andric  list<GICombine> Rules = ?;
428bcb0991SDimitry Andric}
438bcb0991SDimitry Andric
448bcb0991SDimitry Andric// A group of combine rules that can be added to a GICombiner or another group.
458bcb0991SDimitry Andricclass GICombineGroup<list<GICombine> rules> : GICombine {
468bcb0991SDimitry Andric  // The rules contained in this group. The rules in a group are flattened into
478bcb0991SDimitry Andric  // a single list and sorted into whatever order is most efficient. However,
488bcb0991SDimitry Andric  // they will never be re-ordered such that behaviour differs from the
498bcb0991SDimitry Andric  // specified order. It is therefore possible to use the order of rules in this
508bcb0991SDimitry Andric  // list to describe priorities.
518bcb0991SDimitry Andric  let Rules = rules;
528bcb0991SDimitry Andric}
538bcb0991SDimitry Andric
545f757f3fSDimitry Andric// Declares a combiner implementation class
555f757f3fSDimitry Andricclass GICombiner<string classname, list<GICombine> rules>
568bcb0991SDimitry Andric    : GICombineGroup<rules> {
578bcb0991SDimitry Andric  // The class name to use in the generated output.
588bcb0991SDimitry Andric  string Classname = classname;
595f757f3fSDimitry Andric  // Combiners can use this so they're free to define tryCombineAll themselves
605f757f3fSDimitry Andric  // and do extra work before/after calling the TableGen-erated code.
615f757f3fSDimitry Andric  string CombineAllMethodName = "tryCombineAll";
628bcb0991SDimitry Andric}
635f757f3fSDimitry Andric
645f757f3fSDimitry Andric/// Declares data that is passed from the match stage to the apply stage.
655f757f3fSDimitry Andricclass GIDefMatchData<string type>  {
665f757f3fSDimitry Andric  /// A C++ type name indicating the storage type.
675f757f3fSDimitry Andric  string Type = type;
685f757f3fSDimitry Andric}
695f757f3fSDimitry Andric
708bcb0991SDimitry Andricclass GICombineRule<dag defs, dag match, dag apply> : GICombine {
718bcb0991SDimitry Andric  /// Defines the external interface of the match rule. This includes:
728bcb0991SDimitry Andric  /// * The names of the root nodes (requires at least one)
738bcb0991SDimitry Andric  /// See GIDefKind for details.
748bcb0991SDimitry Andric  dag Defs = defs;
758bcb0991SDimitry Andric
768bcb0991SDimitry Andric  /// Defines the things which must be true for the pattern to match
778bcb0991SDimitry Andric  dag Match = match;
788bcb0991SDimitry Andric
798bcb0991SDimitry Andric  /// Defines the things which happen after the decision is made to apply a
808bcb0991SDimitry Andric  /// combine rule.
818bcb0991SDimitry Andric  dag Apply = apply;
82bdd1243dSDimitry Andric
83bdd1243dSDimitry Andric  /// Defines the predicates that are checked before the match function
84bdd1243dSDimitry Andric  /// is called. Targets can use this to, for instance, check Subtarget
85bdd1243dSDimitry Andric  /// features.
86bdd1243dSDimitry Andric  list<Predicate> Predicates = [];
875f757f3fSDimitry Andric
885f757f3fSDimitry Andric  // Maximum number of permutations of this rule that can be emitted.
895f757f3fSDimitry Andric  // Set to -1 to disable the limit.
905f757f3fSDimitry Andric  int MaxPermutations = 16;
918bcb0991SDimitry Andric}
928bcb0991SDimitry Andric
935f757f3fSDimitry Andricdef gi_mo;
945f757f3fSDimitry Andricdef gi_imm;
958bcb0991SDimitry Andric
965f757f3fSDimitry Andric// This is an equivalent of PatFrags but for MIR Patterns.
975f757f3fSDimitry Andric//
985f757f3fSDimitry Andric// GICombinePatFrags can be used in place of instructions for 'match' patterns.
995f757f3fSDimitry Andric// Much like normal instructions, the defs (outs) come first, and the ins second
1005f757f3fSDimitry Andric//
1015f757f3fSDimitry Andric// Out operands can only be of type "root" or "gi_mo", and they must be defined
1025f757f3fSDimitry Andric// by an instruction pattern in all alternatives.
1035f757f3fSDimitry Andric//
1045f757f3fSDimitry Andric// In operands can be gi_imm or gi_mo. They cannot be redefined in any alternative
1055f757f3fSDimitry Andric// pattern and may only appear in the C++ code, or in the output operand of an
1065f757f3fSDimitry Andric// instruction pattern.
1075f757f3fSDimitry Andricclass GICombinePatFrag<dag outs, dag ins, list<dag> alts> {
1085f757f3fSDimitry Andric  dag InOperands = ins;
1095f757f3fSDimitry Andric  dag OutOperands = outs;
1105f757f3fSDimitry Andric  list<dag> Alternatives = alts;
111480093f4SDimitry Andric}
112480093f4SDimitry Andric
1135f757f3fSDimitry Andric//===----------------------------------------------------------------------===//
1145f757f3fSDimitry Andric// Pattern Special Types
1155f757f3fSDimitry Andric//===----------------------------------------------------------------------===//
1165f757f3fSDimitry Andric
1175f757f3fSDimitry Andricclass GISpecialType;
1185f757f3fSDimitry Andric
1195f757f3fSDimitry Andric// In an apply pattern, GITypeOf can be used to set the type of a new temporary
1205f757f3fSDimitry Andric// register to match the type of a matched register.
1215f757f3fSDimitry Andric//
1225f757f3fSDimitry Andric// This can only be used on temporary registers defined by the apply pattern.
1235f757f3fSDimitry Andric//
1245f757f3fSDimitry Andric// TODO: Make this work in matchers as well?
1255f757f3fSDimitry Andric//
1265f757f3fSDimitry Andric// FIXME: Syntax is very ugly.
1275f757f3fSDimitry Andricclass GITypeOf<string opName> : GISpecialType {
1285f757f3fSDimitry Andric  string OpName = opName;
1295f757f3fSDimitry Andric}
1305f757f3fSDimitry Andric
1315f757f3fSDimitry Andric//===----------------------------------------------------------------------===//
1325f757f3fSDimitry Andric// Pattern Builtins
1335f757f3fSDimitry Andric//===----------------------------------------------------------------------===//
1345f757f3fSDimitry Andric
1355f757f3fSDimitry Andric// "Magic" Builtin instructions for MIR patterns.
1365f757f3fSDimitry Andric// The definitions that implement
1375f757f3fSDimitry Andricclass GIBuiltinInst;
1385f757f3fSDimitry Andric
1395f757f3fSDimitry Andric// Replace all references to a register with another one.
1405f757f3fSDimitry Andric//
1415f757f3fSDimitry Andric// Usage:
1425f757f3fSDimitry Andric//    (apply (GIReplaceReg $old, $new))
1435f757f3fSDimitry Andric//
1445f757f3fSDimitry Andric// Operands:
1455f757f3fSDimitry Andric// - $old (out) register defined by a matched instruction
1465f757f3fSDimitry Andric// - $new (in)  register
1475f757f3fSDimitry Andric//
1485f757f3fSDimitry Andric// Semantics:
1495f757f3fSDimitry Andric// - Can only appear in an 'apply' pattern.
1505f757f3fSDimitry Andric// - If both old/new are operands of matched instructions,
1515f757f3fSDimitry Andric//   "canReplaceReg" is checked before applying the rule.
1525f757f3fSDimitry Andricdef GIReplaceReg : GIBuiltinInst;
1535f757f3fSDimitry Andric
1545f757f3fSDimitry Andric// Apply action that erases the match root.
1555f757f3fSDimitry Andric//
1565f757f3fSDimitry Andric// Usage:
1575f757f3fSDimitry Andric//    (apply (GIEraseRoot))
1585f757f3fSDimitry Andric//
1595f757f3fSDimitry Andric// Semantics:
1605f757f3fSDimitry Andric// - Can only appear as the only pattern of an 'apply' pattern list.
1615f757f3fSDimitry Andric// - The root cannot have any output operands.
1625f757f3fSDimitry Andric// - The root must be a CodeGenInstruction
1635f757f3fSDimitry Andric//
1645f757f3fSDimitry Andric// TODO: Allow using this directly, like (apply GIEraseRoot)
1655f757f3fSDimitry Andricdef GIEraseRoot : GIBuiltinInst;
1665f757f3fSDimitry Andric
1675f757f3fSDimitry Andric//===----------------------------------------------------------------------===//
1685f757f3fSDimitry Andric// Pattern MIFlags
1695f757f3fSDimitry Andric//===----------------------------------------------------------------------===//
1705f757f3fSDimitry Andric
1715f757f3fSDimitry Andricclass MIFlagEnum<string enumName> {
1725f757f3fSDimitry Andric  string EnumName = "MachineInstr::" # enumName;
1735f757f3fSDimitry Andric}
1745f757f3fSDimitry Andric
1755f757f3fSDimitry Andricdef FmNoNans    : MIFlagEnum<"FmNoNans">;
1765f757f3fSDimitry Andricdef FmNoInfs    : MIFlagEnum<"FmNoInfs">;
1775f757f3fSDimitry Andricdef FmNsz       : MIFlagEnum<"FmNsz">;
1785f757f3fSDimitry Andricdef FmArcp      : MIFlagEnum<"FmArcp">;
1795f757f3fSDimitry Andricdef FmContract  : MIFlagEnum<"FmContract">;
1805f757f3fSDimitry Andricdef FmAfn       : MIFlagEnum<"FmAfn">;
1815f757f3fSDimitry Andricdef FmReassoc   : MIFlagEnum<"FmReassoc">;
182*0fca6ea1SDimitry Andricdef IsExact     : MIFlagEnum<"IsExact">;
183*0fca6ea1SDimitry Andricdef NoSWrap     : MIFlagEnum<"NoSWrap">;
184*0fca6ea1SDimitry Andricdef NoUWrap     : MIFlagEnum<"NoUWrap">;
185*0fca6ea1SDimitry Andricdef NonNeg      : MIFlagEnum<"NonNeg">;
1865f757f3fSDimitry Andric
1875f757f3fSDimitry Andricdef MIFlags;
1885f757f3fSDimitry Andric// def not; -> Already defined as a SDNode
1895f757f3fSDimitry Andric
1905f757f3fSDimitry Andric//===----------------------------------------------------------------------===//
1915f757f3fSDimitry Andric
192480093f4SDimitry Andricdef extending_load_matchdata : GIDefMatchData<"PreferredTuple">;
193480093f4SDimitry Andricdef indexed_load_store_matchdata : GIDefMatchData<"IndexedLoadStoreMatchInfo">;
194e8d8bef9SDimitry Andricdef instruction_steps_matchdata: GIDefMatchData<"InstructionStepsMatchInfo">;
195480093f4SDimitry Andric
196fe6060f1SDimitry Andricdef register_matchinfo: GIDefMatchData<"Register">;
197fe6060f1SDimitry Andricdef int64_matchinfo: GIDefMatchData<"int64_t">;
198fe6060f1SDimitry Andricdef apint_matchinfo : GIDefMatchData<"APInt">;
1995f757f3fSDimitry Andricdef constantfp_matchinfo : GIDefMatchData<"ConstantFP*">;
200fe6060f1SDimitry Andricdef build_fn_matchinfo :
201fe6060f1SDimitry AndricGIDefMatchData<"std::function<void(MachineIRBuilder &)>">;
20281ad6265SDimitry Andricdef unsigned_matchinfo: GIDefMatchData<"unsigned">;
203fe6060f1SDimitry Andric
2048bcb0991SDimitry Andricdef copy_prop : GICombineRule<
2058bcb0991SDimitry Andric  (defs root:$d),
206480093f4SDimitry Andric  (match (COPY $d, $s):$mi,
207480093f4SDimitry Andric         [{ return Helper.matchCombineCopy(*${mi}); }]),
208480093f4SDimitry Andric  (apply [{ Helper.applyCombineCopy(*${mi}); }])>;
2098bcb0991SDimitry Andric
210bdd1243dSDimitry Andric// idempotent operations
211bdd1243dSDimitry Andric// Fold (freeze (freeze x)) -> (freeze x).
212bdd1243dSDimitry Andric// Fold (fabs (fabs x)) -> (fabs x).
213bdd1243dSDimitry Andric// Fold (fcanonicalize (fcanonicalize x)) -> (fcanonicalize x).
2145f757f3fSDimitry Andricdef idempotent_prop_frags : GICombinePatFrag<
2155f757f3fSDimitry Andric  (outs root:$dst, $src), (ins),
2165f757f3fSDimitry Andric  !foreach(op, [G_FREEZE, G_FABS, G_FCANONICALIZE],
2175f757f3fSDimitry Andric           (pattern (op $dst, $src), (op $src, $x)))>;
2185f757f3fSDimitry Andric
219bdd1243dSDimitry Andricdef idempotent_prop : GICombineRule<
2205f757f3fSDimitry Andric   (defs root:$dst),
2215f757f3fSDimitry Andric   (match (idempotent_prop_frags $dst, $src)),
2225f757f3fSDimitry Andric   (apply (GIReplaceReg $dst, $src))>;
223bdd1243dSDimitry Andric
224*0fca6ea1SDimitry Andric// Convert freeze(Op(Op0, NonPoisonOps...)) to Op(freeze(Op0), NonPoisonOps...)
225*0fca6ea1SDimitry Andric// when Op0 is not guaranteed non-poison
226*0fca6ea1SDimitry Andricdef push_freeze_to_prevent_poison_from_propagating : GICombineRule<
227*0fca6ea1SDimitry Andric  (defs root:$root, build_fn_matchinfo:$matchinfo),
228*0fca6ea1SDimitry Andric  (match (G_FREEZE $dst, $src):$root,
229*0fca6ea1SDimitry Andric         [{ return !isGuaranteedNotToBePoison(${src}.getReg(), MRI) && Helper.matchFreezeOfSingleMaybePoisonOperand(*${root}, ${matchinfo}); }]),
230*0fca6ea1SDimitry Andric  (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>;
231bdd1243dSDimitry Andric
232480093f4SDimitry Andricdef extending_loads : GICombineRule<
233480093f4SDimitry Andric  (defs root:$root, extending_load_matchdata:$matchinfo),
234480093f4SDimitry Andric  (match (wip_match_opcode G_LOAD, G_SEXTLOAD, G_ZEXTLOAD):$root,
235480093f4SDimitry Andric         [{ return Helper.matchCombineExtendingLoads(*${root}, ${matchinfo}); }]),
236480093f4SDimitry Andric  (apply [{ Helper.applyCombineExtendingLoads(*${root}, ${matchinfo}); }])>;
237349cc55cSDimitry Andric
238349cc55cSDimitry Andricdef load_and_mask : GICombineRule<
239349cc55cSDimitry Andric  (defs root:$root, build_fn_matchinfo:$matchinfo),
240349cc55cSDimitry Andric  (match (wip_match_opcode G_AND):$root,
241349cc55cSDimitry Andric        [{ return Helper.matchCombineLoadWithAndMask(*${root}, ${matchinfo}); }]),
242349cc55cSDimitry Andric  (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>;
243349cc55cSDimitry Andricdef combines_for_extload: GICombineGroup<[extending_loads, load_and_mask]>;
244480093f4SDimitry Andric
245e8d8bef9SDimitry Andricdef sext_trunc_sextload : GICombineRule<
2465ffd83dbSDimitry Andric  (defs root:$d),
2475ffd83dbSDimitry Andric  (match (wip_match_opcode G_SEXT_INREG):$d,
248e8d8bef9SDimitry Andric         [{ return Helper.matchSextTruncSextLoad(*${d}); }]),
249e8d8bef9SDimitry Andric  (apply [{ Helper.applySextTruncSextLoad(*${d}); }])>;
250e8d8bef9SDimitry Andric
251e8d8bef9SDimitry Andricdef sext_inreg_of_load_matchdata : GIDefMatchData<"std::tuple<Register, unsigned>">;
252e8d8bef9SDimitry Andricdef sext_inreg_of_load : GICombineRule<
253e8d8bef9SDimitry Andric  (defs root:$root, sext_inreg_of_load_matchdata:$matchinfo),
254e8d8bef9SDimitry Andric  (match (wip_match_opcode G_SEXT_INREG):$root,
255e8d8bef9SDimitry Andric         [{ return Helper.matchSextInRegOfLoad(*${root}, ${matchinfo}); }]),
256fe6060f1SDimitry Andric  (apply [{ Helper.applySextInRegOfLoad(*${root}, ${matchinfo}); }])>;
2575ffd83dbSDimitry Andric
258bdd1243dSDimitry Andricdef sext_inreg_to_zext_inreg : GICombineRule<
259bdd1243dSDimitry Andric  (defs root:$dst),
260bdd1243dSDimitry Andric  (match
261bdd1243dSDimitry Andric    (G_SEXT_INREG $dst, $src, $imm):$root,
262bdd1243dSDimitry Andric      [{
263bdd1243dSDimitry Andric        unsigned BitWidth = MRI.getType(${src}.getReg()).getScalarSizeInBits();
264bdd1243dSDimitry Andric        return Helper.getKnownBits()->maskedValueIsZero(${src}.getReg(),
265bdd1243dSDimitry Andric                 APInt::getOneBitSet(BitWidth, ${imm}.getImm() - 1)); }]),
266bdd1243dSDimitry Andric    (apply [{
267bdd1243dSDimitry Andric      Helper.getBuilder().setInstrAndDebugLoc(*${root});
268bdd1243dSDimitry Andric      Helper.getBuilder().buildZExtInReg(${dst}, ${src}, ${imm}.getImm());
269bdd1243dSDimitry Andric      ${root}->eraseFromParent();
270bdd1243dSDimitry Andric  }])
271bdd1243dSDimitry Andric>;
272bdd1243dSDimitry Andric
2735f757f3fSDimitry Andricdef combine_extracted_vector_load : GICombineRule<
2745f757f3fSDimitry Andric  (defs root:$root, build_fn_matchinfo:$matchinfo),
2755f757f3fSDimitry Andric  (match (wip_match_opcode G_EXTRACT_VECTOR_ELT):$root,
2765f757f3fSDimitry Andric        [{ return Helper.matchCombineExtractedVectorLoad(*${root}, ${matchinfo}); }]),
2775f757f3fSDimitry Andric  (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>;
2785f757f3fSDimitry Andric
279480093f4SDimitry Andricdef combine_indexed_load_store : GICombineRule<
280480093f4SDimitry Andric  (defs root:$root, indexed_load_store_matchdata:$matchinfo),
281480093f4SDimitry Andric  (match (wip_match_opcode G_LOAD, G_SEXTLOAD, G_ZEXTLOAD, G_STORE):$root,
282480093f4SDimitry Andric         [{ return Helper.matchCombineIndexedLoadStore(*${root}, ${matchinfo}); }]),
283480093f4SDimitry Andric  (apply [{ Helper.applyCombineIndexedLoadStore(*${root}, ${matchinfo}); }])>;
284480093f4SDimitry Andric
285fe6060f1SDimitry Andricdef opt_brcond_by_inverting_cond_matchdata : GIDefMatchData<"MachineInstr *">;
286e8d8bef9SDimitry Andricdef opt_brcond_by_inverting_cond : GICombineRule<
287fe6060f1SDimitry Andric  (defs root:$root, opt_brcond_by_inverting_cond_matchdata:$matchinfo),
288480093f4SDimitry Andric  (match (wip_match_opcode G_BR):$root,
289fe6060f1SDimitry Andric         [{ return Helper.matchOptBrCondByInvertingCond(*${root}, ${matchinfo}); }]),
290fe6060f1SDimitry Andric  (apply [{ Helper.applyOptBrCondByInvertingCond(*${root}, ${matchinfo}); }])>;
2918bcb0991SDimitry Andric
292480093f4SDimitry Andricdef ptr_add_immed_matchdata : GIDefMatchData<"PtrAddChain">;
293480093f4SDimitry Andricdef ptr_add_immed_chain : GICombineRule<
294480093f4SDimitry Andric  (defs root:$d, ptr_add_immed_matchdata:$matchinfo),
295480093f4SDimitry Andric  (match (wip_match_opcode G_PTR_ADD):$d,
296480093f4SDimitry Andric         [{ return Helper.matchPtrAddImmedChain(*${d}, ${matchinfo}); }]),
297480093f4SDimitry Andric  (apply [{ Helper.applyPtrAddImmedChain(*${d}, ${matchinfo}); }])>;
298480093f4SDimitry Andric
29906c3fb27SDimitry Andricdef shifts_too_big : GICombineRule<
30006c3fb27SDimitry Andric  (defs root:$root),
30106c3fb27SDimitry Andric  (match (wip_match_opcode G_SHL, G_ASHR, G_LSHR):$root,
30206c3fb27SDimitry Andric         [{ return Helper.matchShiftsTooBig(*${root}); }]),
30306c3fb27SDimitry Andric  (apply [{ Helper.replaceInstWithUndef(*${root}); }])>;
30406c3fb27SDimitry Andric
305e8d8bef9SDimitry Andric// Fold shift (shift base x), y -> shift base, (x+y), if shifts are same
306e8d8bef9SDimitry Andricdef shift_immed_matchdata : GIDefMatchData<"RegisterImmPair">;
307e8d8bef9SDimitry Andricdef shift_immed_chain : GICombineRule<
308e8d8bef9SDimitry Andric  (defs root:$d, shift_immed_matchdata:$matchinfo),
309e8d8bef9SDimitry Andric  (match (wip_match_opcode G_SHL, G_ASHR, G_LSHR, G_SSHLSAT, G_USHLSAT):$d,
310e8d8bef9SDimitry Andric         [{ return Helper.matchShiftImmedChain(*${d}, ${matchinfo}); }]),
311e8d8bef9SDimitry Andric  (apply [{ Helper.applyShiftImmedChain(*${d}, ${matchinfo}); }])>;
312e8d8bef9SDimitry Andric
313e8d8bef9SDimitry Andric// Transform shift (logic (shift X, C0), Y), C1
314e8d8bef9SDimitry Andric//        -> logic (shift X, (C0+C1)), (shift Y, C1), if shifts are same
315e8d8bef9SDimitry Andricdef shift_of_shifted_logic_matchdata : GIDefMatchData<"ShiftOfShiftedLogic">;
316e8d8bef9SDimitry Andricdef shift_of_shifted_logic_chain : GICombineRule<
317e8d8bef9SDimitry Andric  (defs root:$d, shift_of_shifted_logic_matchdata:$matchinfo),
318e8d8bef9SDimitry Andric  (match (wip_match_opcode G_SHL, G_ASHR, G_LSHR, G_USHLSAT, G_SSHLSAT):$d,
319e8d8bef9SDimitry Andric         [{ return Helper.matchShiftOfShiftedLogic(*${d}, ${matchinfo}); }]),
320e8d8bef9SDimitry Andric  (apply [{ Helper.applyShiftOfShiftedLogic(*${d}, ${matchinfo}); }])>;
321e8d8bef9SDimitry Andric
3225ffd83dbSDimitry Andricdef mul_to_shl : GICombineRule<
323*0fca6ea1SDimitry Andric  (defs root:$d, unsigned_matchinfo:$matchinfo),
3245ffd83dbSDimitry Andric  (match (G_MUL $d, $op1, $op2):$mi,
3255ffd83dbSDimitry Andric         [{ return Helper.matchCombineMulToShl(*${mi}, ${matchinfo}); }]),
3265ffd83dbSDimitry Andric  (apply [{ Helper.applyCombineMulToShl(*${mi}, ${matchinfo}); }])>;
3275ffd83dbSDimitry Andric
328e8d8bef9SDimitry Andric// shl ([asz]ext x), y => zext (shl x, y), if shift does not overflow int
329e8d8bef9SDimitry Andricdef reduce_shl_of_extend_matchdata : GIDefMatchData<"RegisterImmPair">;
330e8d8bef9SDimitry Andricdef reduce_shl_of_extend : GICombineRule<
331e8d8bef9SDimitry Andric  (defs root:$dst, reduce_shl_of_extend_matchdata:$matchinfo),
332e8d8bef9SDimitry Andric  (match (G_SHL $dst, $src0, $src1):$mi,
333e8d8bef9SDimitry Andric         [{ return Helper.matchCombineShlOfExtend(*${mi}, ${matchinfo}); }]),
334e8d8bef9SDimitry Andric  (apply [{ Helper.applyCombineShlOfExtend(*${mi}, ${matchinfo}); }])>;
335e8d8bef9SDimitry Andric
336*0fca6ea1SDimitry Andric// Combine bitreverse(shl (bitreverse x), y)) -> (lshr x, y)
337*0fca6ea1SDimitry Andricdef bitreverse_shl : GICombineRule<
338*0fca6ea1SDimitry Andric  (defs root:$d),
339*0fca6ea1SDimitry Andric  (match (G_BITREVERSE $rev, $val),
340*0fca6ea1SDimitry Andric         (G_SHL $src, $rev, $amt):$mi,
341*0fca6ea1SDimitry Andric         (G_BITREVERSE $d, $src),
342*0fca6ea1SDimitry Andric         [{ return Helper.isLegalOrBeforeLegalizer({TargetOpcode::G_LSHR,
343*0fca6ea1SDimitry Andric                                                   {MRI.getType(${val}.getReg()),
344*0fca6ea1SDimitry Andric                                                    MRI.getType(${amt}.getReg())}}); }]),
345*0fca6ea1SDimitry Andric  (apply (G_LSHR $d, $val, $amt))>;
346*0fca6ea1SDimitry Andric
347*0fca6ea1SDimitry Andric// Combine bitreverse(lshr (bitreverse x), y)) -> (shl x, y)
348*0fca6ea1SDimitry Andricdef bitreverse_lshr : GICombineRule<
349*0fca6ea1SDimitry Andric  (defs root:$d),
350*0fca6ea1SDimitry Andric  (match (G_BITREVERSE $rev, $val),
351*0fca6ea1SDimitry Andric         (G_LSHR $src, $rev, $amt):$mi,
352*0fca6ea1SDimitry Andric         (G_BITREVERSE $d, $src),
353*0fca6ea1SDimitry Andric         [{ return Helper.isLegalOrBeforeLegalizer({TargetOpcode::G_SHL,
354*0fca6ea1SDimitry Andric                                                   {MRI.getType(${val}.getReg()),
355*0fca6ea1SDimitry Andric                                                    MRI.getType(${amt}.getReg())}}); }]),
356*0fca6ea1SDimitry Andric  (apply (G_SHL $d, $val, $amt))>;
357*0fca6ea1SDimitry Andric
35806c3fb27SDimitry Andric// Combine (shl (add x, c1), c2) -> (add (shl x, c2), c1 << c2)
35906c3fb27SDimitry Andric// Combine (shl (or x, c1), c2) -> (or (shl x, c2), c1 << c2)
36006c3fb27SDimitry Andricdef commute_shift : GICombineRule<
36106c3fb27SDimitry Andric  (defs root:$d, build_fn_matchinfo:$matchinfo),
36206c3fb27SDimitry Andric  (match (wip_match_opcode G_SHL):$d,
36306c3fb27SDimitry Andric         [{ return Helper.matchCommuteShift(*${d}, ${matchinfo}); }]),
36406c3fb27SDimitry Andric  (apply [{ Helper.applyBuildFn(*${d}, ${matchinfo}); }])>;
36506c3fb27SDimitry Andric
366349cc55cSDimitry Andricdef narrow_binop_feeding_and : GICombineRule<
367349cc55cSDimitry Andric  (defs root:$root, build_fn_matchinfo:$matchinfo),
368349cc55cSDimitry Andric  (match (wip_match_opcode G_AND):$root,
369349cc55cSDimitry Andric         [{ return Helper.matchNarrowBinopFeedingAnd(*${root}, ${matchinfo}); }]),
370349cc55cSDimitry Andric  (apply [{ Helper.applyBuildFnNoErase(*${root}, ${matchinfo}); }])>;
371349cc55cSDimitry Andric
3725ffd83dbSDimitry Andric// [us]itofp(undef) = 0, because the result value is bounded.
3735ffd83dbSDimitry Andricdef undef_to_fp_zero : GICombineRule<
3745ffd83dbSDimitry Andric  (defs root:$root),
3755ffd83dbSDimitry Andric  (match (wip_match_opcode G_UITOFP, G_SITOFP):$root,
3765ffd83dbSDimitry Andric         [{ return Helper.matchAnyExplicitUseIsUndef(*${root}); }]),
3775ffd83dbSDimitry Andric  (apply [{ Helper.replaceInstWithFConstant(*${root}, 0.0); }])>;
3785ffd83dbSDimitry Andric
3795ffd83dbSDimitry Andricdef undef_to_int_zero: GICombineRule<
3805ffd83dbSDimitry Andric  (defs root:$root),
3815ffd83dbSDimitry Andric  (match (wip_match_opcode G_AND, G_MUL):$root,
3825ffd83dbSDimitry Andric         [{ return Helper.matchAnyExplicitUseIsUndef(*${root}); }]),
3835ffd83dbSDimitry Andric  (apply [{ Helper.replaceInstWithConstant(*${root}, 0); }])>;
3845ffd83dbSDimitry Andric
3855ffd83dbSDimitry Andricdef undef_to_negative_one: GICombineRule<
3865ffd83dbSDimitry Andric  (defs root:$root),
3875ffd83dbSDimitry Andric  (match (wip_match_opcode G_OR):$root,
3885ffd83dbSDimitry Andric         [{ return Helper.matchAnyExplicitUseIsUndef(*${root}); }]),
3895ffd83dbSDimitry Andric  (apply [{ Helper.replaceInstWithConstant(*${root}, -1); }])>;
3905ffd83dbSDimitry Andric
391e8d8bef9SDimitry Andricdef binop_left_undef_to_zero: GICombineRule<
392e8d8bef9SDimitry Andric  (defs root:$root),
393bdd1243dSDimitry Andric  (match (wip_match_opcode G_SHL, G_UDIV, G_UREM):$root,
394e8d8bef9SDimitry Andric         [{ return Helper.matchOperandIsUndef(*${root}, 1); }]),
395e8d8bef9SDimitry Andric  (apply [{ Helper.replaceInstWithConstant(*${root}, 0); }])>;
396e8d8bef9SDimitry Andric
39781ad6265SDimitry Andricdef binop_right_undef_to_undef: GICombineRule<
39881ad6265SDimitry Andric  (defs root:$root),
39981ad6265SDimitry Andric  (match (wip_match_opcode G_SHL, G_ASHR, G_LSHR):$root,
40081ad6265SDimitry Andric         [{ return Helper.matchOperandIsUndef(*${root}, 2); }]),
40181ad6265SDimitry Andric  (apply [{ Helper.replaceInstWithUndef(*${root}); }])>;
40281ad6265SDimitry Andric
403bdd1243dSDimitry Andricdef unary_undef_to_zero: GICombineRule<
404bdd1243dSDimitry Andric  (defs root:$root),
405bdd1243dSDimitry Andric  (match (wip_match_opcode G_ABS):$root,
406bdd1243dSDimitry Andric         [{ return Helper.matchOperandIsUndef(*${root}, 1); }]),
407bdd1243dSDimitry Andric  (apply [{ Helper.replaceInstWithConstant(*${root}, 0); }])>;
408bdd1243dSDimitry Andric
4095ffd83dbSDimitry Andric// Instructions where if any source operand is undef, the instruction can be
4105ffd83dbSDimitry Andric// replaced with undef.
4115ffd83dbSDimitry Andricdef propagate_undef_any_op: GICombineRule<
4125ffd83dbSDimitry Andric  (defs root:$root),
413e8d8bef9SDimitry Andric  (match (wip_match_opcode G_ADD, G_FPTOSI, G_FPTOUI, G_SUB, G_XOR, G_TRUNC):$root,
4145ffd83dbSDimitry Andric         [{ return Helper.matchAnyExplicitUseIsUndef(*${root}); }]),
4155ffd83dbSDimitry Andric  (apply [{ Helper.replaceInstWithUndef(*${root}); }])>;
4165ffd83dbSDimitry Andric
4175ffd83dbSDimitry Andric// Instructions where if all source operands are undef, the instruction can be
4185ffd83dbSDimitry Andric// replaced with undef.
4195ffd83dbSDimitry Andricdef propagate_undef_all_ops: GICombineRule<
4205ffd83dbSDimitry Andric  (defs root:$root),
4215ffd83dbSDimitry Andric  (match (wip_match_opcode G_SHUFFLE_VECTOR):$root,
4225ffd83dbSDimitry Andric          [{ return Helper.matchAllExplicitUsesAreUndef(*${root}); }]),
4235ffd83dbSDimitry Andric  (apply [{ Helper.replaceInstWithUndef(*${root}); }])>;
4245ffd83dbSDimitry Andric
4255ffd83dbSDimitry Andric// Replace a G_SHUFFLE_VECTOR with an undef mask with a G_IMPLICIT_DEF.
4265ffd83dbSDimitry Andricdef propagate_undef_shuffle_mask: GICombineRule<
4275ffd83dbSDimitry Andric  (defs root:$root),
4285ffd83dbSDimitry Andric  (match (wip_match_opcode G_SHUFFLE_VECTOR):$root,
4295ffd83dbSDimitry Andric         [{ return Helper.matchUndefShuffleVectorMask(*${root}); }]),
4305ffd83dbSDimitry Andric  (apply [{ Helper.replaceInstWithUndef(*${root}); }])>;
4315ffd83dbSDimitry Andric
4325f757f3fSDimitry Andric// Replace a G_SHUFFLE_VECTOR with a G_EXTRACT_VECTOR_ELT.
4335f757f3fSDimitry Andricdef shuffle_to_extract: GICombineRule<
4345f757f3fSDimitry Andric  (defs root:$root),
4355f757f3fSDimitry Andric  (match (wip_match_opcode G_SHUFFLE_VECTOR):$root,
4365f757f3fSDimitry Andric         [{ return Helper.matchShuffleToExtract(*${root}); }]),
4375f757f3fSDimitry Andric  (apply [{ Helper.applyShuffleToExtract(*${root}); }])>;
4385f757f3fSDimitry Andric
439bdd1243dSDimitry Andric  // Replace an insert/extract element of an out of bounds index with undef.
440bdd1243dSDimitry Andric  def insert_extract_vec_elt_out_of_bounds : GICombineRule<
441bdd1243dSDimitry Andric  (defs root:$root),
442bdd1243dSDimitry Andric  (match (wip_match_opcode G_INSERT_VECTOR_ELT, G_EXTRACT_VECTOR_ELT):$root,
443bdd1243dSDimitry Andric         [{ return Helper.matchInsertExtractVecEltOutOfBounds(*${root}); }]),
444bdd1243dSDimitry Andric  (apply [{ Helper.replaceInstWithUndef(*${root}); }])>;
445bdd1243dSDimitry Andric
4465ffd83dbSDimitry Andric// Fold (cond ? x : x) -> x
4475ffd83dbSDimitry Andricdef select_same_val: GICombineRule<
4485ffd83dbSDimitry Andric  (defs root:$root),
4495ffd83dbSDimitry Andric  (match (wip_match_opcode G_SELECT):$root,
4505ffd83dbSDimitry Andric    [{ return Helper.matchSelectSameVal(*${root}); }]),
45106c3fb27SDimitry Andric  (apply [{ Helper.replaceSingleDefInstWithOperand(*${root}, 2); }])
4525ffd83dbSDimitry Andric>;
4535ffd83dbSDimitry Andric
454e8d8bef9SDimitry Andric// Fold (undef ? x : y) -> y
455e8d8bef9SDimitry Andricdef select_undef_cmp: GICombineRule<
4565f757f3fSDimitry Andric  (defs root:$dst),
4575f757f3fSDimitry Andric  (match (G_IMPLICIT_DEF $undef),
4585f757f3fSDimitry Andric         (G_SELECT $dst, $undef, $x, $y)),
4595f757f3fSDimitry Andric  (apply (GIReplaceReg $dst, $y))
460e8d8bef9SDimitry Andric>;
461e8d8bef9SDimitry Andric
462e8d8bef9SDimitry Andric// Fold (true ? x : y) -> x
463e8d8bef9SDimitry Andric// Fold (false ? x : y) -> y
464e8d8bef9SDimitry Andricdef select_constant_cmp: GICombineRule<
465*0fca6ea1SDimitry Andric  (defs root:$root, unsigned_matchinfo:$matchinfo),
466e8d8bef9SDimitry Andric  (match (wip_match_opcode G_SELECT):$root,
467e8d8bef9SDimitry Andric    [{ return Helper.matchConstantSelectCmp(*${root}, ${matchinfo}); }]),
46806c3fb27SDimitry Andric  (apply [{ Helper.replaceSingleDefInstWithOperand(*${root}, ${matchinfo}); }])
469e8d8bef9SDimitry Andric>;
470e8d8bef9SDimitry Andric
471bdd1243dSDimitry Andric// Fold (C op x) -> (x op C)
472bdd1243dSDimitry Andric// TODO: handle more isCommutable opcodes
473bdd1243dSDimitry Andric// TODO: handle compares (currently not marked as isCommutable)
4745f757f3fSDimitry Andricdef commute_int_constant_to_rhs : GICombineRule<
475bdd1243dSDimitry Andric  (defs root:$root),
476*0fca6ea1SDimitry Andric  (match (wip_match_opcode G_ADD, G_MUL, G_AND, G_OR, G_XOR,
477*0fca6ea1SDimitry Andric                           G_SMIN, G_SMAX, G_UMIN, G_UMAX, G_UADDO, G_SADDO,
478*0fca6ea1SDimitry Andric                           G_UMULO, G_SMULO, G_UMULH, G_SMULH,
479*0fca6ea1SDimitry Andric                           G_UADDSAT, G_SADDSAT, G_SMULFIX, G_UMULFIX,
480*0fca6ea1SDimitry Andric                           G_SMULFIXSAT, G_UMULFIXSAT):$root,
4815f757f3fSDimitry Andric    [{ return Helper.matchCommuteConstantToRHS(*${root}); }]),
4825f757f3fSDimitry Andric  (apply [{ Helper.applyCommuteBinOpOperands(*${root}); }])
483bdd1243dSDimitry Andric>;
484bdd1243dSDimitry Andric
4855f757f3fSDimitry Andricdef commute_fp_constant_to_rhs : GICombineRule<
4865ffd83dbSDimitry Andric  (defs root:$root),
487*0fca6ea1SDimitry Andric  (match (wip_match_opcode G_FADD, G_FMUL, G_FMINNUM, G_FMAXNUM,
488*0fca6ea1SDimitry Andric                           G_FMINNUM_IEEE, G_FMAXNUM_IEEE,
489*0fca6ea1SDimitry Andric                           G_FMINIMUM, G_FMAXIMUM):$root,
4905f757f3fSDimitry Andric    [{ return Helper.matchCommuteFPConstantToRHS(*${root}); }]),
4915f757f3fSDimitry Andric  (apply [{ Helper.applyCommuteBinOpOperands(*${root}); }])
4925f757f3fSDimitry Andric>;
4935f757f3fSDimitry Andric
4945f757f3fSDimitry Andricdef commute_constant_to_rhs : GICombineGroup<[
4955f757f3fSDimitry Andric  commute_int_constant_to_rhs,
4965f757f3fSDimitry Andric  commute_fp_constant_to_rhs
4975f757f3fSDimitry Andric]>;
4985f757f3fSDimitry Andric
4995f757f3fSDimitry Andric// Fold x op 0 -> x
5005f757f3fSDimitry Andricdef right_identity_zero_frags : GICombinePatFrag<
5015f757f3fSDimitry Andric  (outs root:$dst), (ins $x),
5025f757f3fSDimitry Andric  !foreach(op,
5035f757f3fSDimitry Andric           [G_SUB, G_ADD, G_OR, G_XOR, G_SHL, G_ASHR,
5045f757f3fSDimitry Andric            G_LSHR, G_PTR_ADD, G_ROTL, G_ROTR],
5055f757f3fSDimitry Andric           (pattern (op $dst, $x, 0)))>;
5065f757f3fSDimitry Andricdef right_identity_zero: GICombineRule<
5075f757f3fSDimitry Andric  (defs root:$dst),
5085f757f3fSDimitry Andric  (match (right_identity_zero_frags $dst, $lhs)),
5095f757f3fSDimitry Andric  (apply (GIReplaceReg $dst, $lhs))
5105f757f3fSDimitry Andric>;
5115f757f3fSDimitry Andric
5125f757f3fSDimitry Andricdef right_identity_neg_zero_fp: GICombineRule<
5135f757f3fSDimitry Andric  (defs root:$dst),
5145f757f3fSDimitry Andric  (match (G_FADD $dst, $x, $y):$root,
5155f757f3fSDimitry Andric    [{ return Helper.matchConstantFPOp(${y}, -0.0); }]),
5165f757f3fSDimitry Andric  (apply (GIReplaceReg $dst, $x))
5175ffd83dbSDimitry Andric>;
5185ffd83dbSDimitry Andric
519e8d8bef9SDimitry Andric// Fold x op 1 -> x
5205f757f3fSDimitry Andricdef right_identity_one_int: GICombineRule<
5215f757f3fSDimitry Andric  (defs root:$dst),
5225f757f3fSDimitry Andric  (match (G_MUL $dst, $x, 1)),
5235f757f3fSDimitry Andric  (apply (GIReplaceReg $dst, $x))
524e8d8bef9SDimitry Andric>;
525e8d8bef9SDimitry Andric
5265f757f3fSDimitry Andricdef right_identity_one_fp: GICombineRule<
5275f757f3fSDimitry Andric  (defs root:$dst),
5285f757f3fSDimitry Andric  (match (G_FMUL $dst, $x, $y):$root,
5295f757f3fSDimitry Andric    [{ return Helper.matchConstantFPOp(${y}, 1.0); }]),
5305f757f3fSDimitry Andric  (apply (GIReplaceReg $dst, $x))
5315f757f3fSDimitry Andric>;
5325f757f3fSDimitry Andric
533*0fca6ea1SDimitry Andricdef right_identity_neg_one_fp: GICombineRule<
534*0fca6ea1SDimitry Andric  (defs root:$dst),
535*0fca6ea1SDimitry Andric  (match (G_FMUL $dst, $x, $y):$root,
536*0fca6ea1SDimitry Andric    [{ return Helper.matchConstantFPOp(${y}, -1.0); }]),
537*0fca6ea1SDimitry Andric  (apply (G_FNEG $dst, $x))
538*0fca6ea1SDimitry Andric>;
539*0fca6ea1SDimitry Andric
5405f757f3fSDimitry Andricdef right_identity_one : GICombineGroup<[right_identity_one_int, right_identity_one_fp]>;
5415f757f3fSDimitry Andric
5425ffd83dbSDimitry Andric// Fold (x op x) - > x
5435f757f3fSDimitry Andricdef binop_same_val_frags : GICombinePatFrag<
5445f757f3fSDimitry Andric  (outs root:$dst), (ins $x),
5455f757f3fSDimitry Andric  [
5465f757f3fSDimitry Andric    (pattern (G_AND $dst, $x, $x)),
5475f757f3fSDimitry Andric    (pattern (G_OR $dst, $x, $x)),
5485f757f3fSDimitry Andric  ]
5495f757f3fSDimitry Andric>;
5505ffd83dbSDimitry Andricdef binop_same_val: GICombineRule<
5515f757f3fSDimitry Andric  (defs root:$dst),
5525f757f3fSDimitry Andric  (match (binop_same_val_frags $dst, $src)),
5535f757f3fSDimitry Andric  (apply (GIReplaceReg $dst, $src))
5545ffd83dbSDimitry Andric>;
5555ffd83dbSDimitry Andric
5565ffd83dbSDimitry Andric// Fold (0 op x) - > 0
5575ffd83dbSDimitry Andricdef binop_left_to_zero: GICombineRule<
5585ffd83dbSDimitry Andric  (defs root:$root),
5595ffd83dbSDimitry Andric  (match (wip_match_opcode G_SDIV, G_UDIV, G_SREM, G_UREM):$root,
5605ffd83dbSDimitry Andric    [{ return Helper.matchOperandIsZero(*${root}, 1); }]),
56106c3fb27SDimitry Andric  (apply [{ Helper.replaceSingleDefInstWithOperand(*${root}, 1); }])
5625ffd83dbSDimitry Andric>;
5635ffd83dbSDimitry Andric
564e8d8bef9SDimitry Andricdef urem_pow2_to_mask : GICombineRule<
565e8d8bef9SDimitry Andric  (defs root:$root),
566e8d8bef9SDimitry Andric  (match (wip_match_opcode G_UREM):$root,
567e8d8bef9SDimitry Andric    [{ return Helper.matchOperandIsKnownToBeAPowerOfTwo(*${root}, 2); }]),
568fe6060f1SDimitry Andric  (apply [{ Helper.applySimplifyURemByPow2(*${root}); }])
569fe6060f1SDimitry Andric>;
570fe6060f1SDimitry Andric
57181ad6265SDimitry Andric// Push a binary operator through a select on constants.
57281ad6265SDimitry Andric//
57381ad6265SDimitry Andric// binop (select cond, K0, K1), K2 ->
57481ad6265SDimitry Andric//   select cond, (binop K0, K2), (binop K1, K2)
57581ad6265SDimitry Andric
57681ad6265SDimitry Andric// Every binary operator that has constant folding. We currently do
57781ad6265SDimitry Andric// not have constant folding for G_FPOW, G_FMAXNUM_IEEE or
57881ad6265SDimitry Andric// G_FMINNUM_IEEE.
57981ad6265SDimitry Andricdef fold_binop_into_select : GICombineRule<
58081ad6265SDimitry Andric  (defs root:$root, unsigned_matchinfo:$select_op_no),
58181ad6265SDimitry Andric  (match (wip_match_opcode
58281ad6265SDimitry Andric    G_ADD, G_SUB, G_PTR_ADD, G_AND, G_OR, G_XOR,
58381ad6265SDimitry Andric    G_SDIV, G_SREM, G_UDIV, G_UREM, G_LSHR, G_ASHR, G_SHL,
58481ad6265SDimitry Andric    G_SMIN, G_SMAX, G_UMIN, G_UMAX,
58581ad6265SDimitry Andric    G_FMUL, G_FADD, G_FSUB, G_FDIV, G_FREM,
58681ad6265SDimitry Andric    G_FMINNUM, G_FMAXNUM, G_FMINIMUM, G_FMAXIMUM):$root,
58781ad6265SDimitry Andric    [{ return Helper.matchFoldBinOpIntoSelect(*${root}, ${select_op_no}); }]),
58806c3fb27SDimitry Andric  (apply [{ Helper.applyFoldBinOpIntoSelect(*${root}, ${select_op_no}); }])
58981ad6265SDimitry Andric>;
59081ad6265SDimitry Andric
591fe6060f1SDimitry Andric// Transform d = [su]div(x, y) and r = [su]rem(x, y) - > d, r = [su]divrem(x, y)
592fe6060f1SDimitry Andricdef div_rem_to_divrem_matchdata : GIDefMatchData<"MachineInstr *">;
593fe6060f1SDimitry Andricdef div_rem_to_divrem : GICombineRule<
594fe6060f1SDimitry Andric  (defs root:$root, div_rem_to_divrem_matchdata:$matchinfo),
595fe6060f1SDimitry Andric  (match (wip_match_opcode G_SDIV, G_UDIV, G_SREM, G_UREM):$root,
596fe6060f1SDimitry Andric    [{ return Helper.matchCombineDivRem(*${root}, ${matchinfo}); }]),
597fe6060f1SDimitry Andric  (apply [{ Helper.applyCombineDivRem(*${root}, ${matchinfo}); }])
598e8d8bef9SDimitry Andric>;
599e8d8bef9SDimitry Andric
6005ffd83dbSDimitry Andric// Fold (x op 0) - > 0
6015ffd83dbSDimitry Andricdef binop_right_to_zero: GICombineRule<
6025f757f3fSDimitry Andric  (defs root:$dst),
6035f757f3fSDimitry Andric  (match (G_MUL $dst, $lhs, 0:$zero)),
6045f757f3fSDimitry Andric  (apply (GIReplaceReg $dst, $zero))
6055ffd83dbSDimitry Andric>;
6065ffd83dbSDimitry Andric
6075ffd83dbSDimitry Andric// Erase stores of undef values.
6085ffd83dbSDimitry Andricdef erase_undef_store : GICombineRule<
6095ffd83dbSDimitry Andric  (defs root:$root),
6105ffd83dbSDimitry Andric  (match (wip_match_opcode G_STORE):$root,
6115ffd83dbSDimitry Andric    [{ return Helper.matchUndefStore(*${root}); }]),
61206c3fb27SDimitry Andric  (apply [{ Helper.eraseInst(*${root}); }])
6135ffd83dbSDimitry Andric>;
6145ffd83dbSDimitry Andric
6155ffd83dbSDimitry Andricdef simplify_add_to_sub_matchinfo: GIDefMatchData<"std::tuple<Register, Register>">;
6165ffd83dbSDimitry Andricdef simplify_add_to_sub: GICombineRule <
6175ffd83dbSDimitry Andric  (defs root:$root, simplify_add_to_sub_matchinfo:$info),
6185ffd83dbSDimitry Andric  (match (wip_match_opcode G_ADD):$root,
6195ffd83dbSDimitry Andric    [{ return Helper.matchSimplifyAddToSub(*${root}, ${info}); }]),
620fe6060f1SDimitry Andric  (apply [{ Helper.applySimplifyAddToSub(*${root}, ${info});}])
6215ffd83dbSDimitry Andric>;
6225ffd83dbSDimitry Andric
623e8d8bef9SDimitry Andric// Fold fp_op(cst) to the constant result of the floating point operation.
62406c3fb27SDimitry Andricclass constant_fold_unary_fp_op_rule<Instruction opcode> : GICombineRule <
62506c3fb27SDimitry Andric  (defs root:$dst),
62606c3fb27SDimitry Andric  (match (opcode $dst, $src0):$root, (G_FCONSTANT $src0, $cst)),
62706c3fb27SDimitry Andric  (apply [{ Helper.applyCombineConstantFoldFpUnary(*${root}, ${cst}.getFPImm()); }])
628e8d8bef9SDimitry Andric>;
629e8d8bef9SDimitry Andric
63006c3fb27SDimitry Andricdef constant_fold_fneg : constant_fold_unary_fp_op_rule<G_FNEG>;
63106c3fb27SDimitry Andricdef constant_fold_fabs : constant_fold_unary_fp_op_rule<G_FABS>;
63206c3fb27SDimitry Andricdef constant_fold_fsqrt : constant_fold_unary_fp_op_rule<G_FSQRT>;
63306c3fb27SDimitry Andricdef constant_fold_flog2 : constant_fold_unary_fp_op_rule<G_FLOG2>;
63406c3fb27SDimitry Andricdef constant_fold_fptrunc : constant_fold_unary_fp_op_rule<G_FPTRUNC>;
63506c3fb27SDimitry Andric
6365f757f3fSDimitry Andric// Fold constant zero int to fp conversions.
6375f757f3fSDimitry Andricclass itof_const_zero_fold_rule<Instruction opcode> : GICombineRule <
6385f757f3fSDimitry Andric  (defs root:$dst),
6395f757f3fSDimitry Andric  (match (opcode $dst, 0)),
6405f757f3fSDimitry Andric  // Can't use COPY $dst, 0 here because the 0 operand may be a smaller type
6415f757f3fSDimitry Andric  // than the destination for itofp.
6425f757f3fSDimitry Andric  (apply [{ Helper.replaceInstWithFConstant(*${dst}.getParent(), 0.0); }])
6435f757f3fSDimitry Andric>;
6445f757f3fSDimitry Andricdef itof_const_zero_fold_si : itof_const_zero_fold_rule<G_SITOFP>;
6455f757f3fSDimitry Andricdef itof_const_zero_fold_ui : itof_const_zero_fold_rule<G_UITOFP>;
6465f757f3fSDimitry Andric
64706c3fb27SDimitry Andricdef constant_fold_fp_ops : GICombineGroup<[
64806c3fb27SDimitry Andric  constant_fold_fneg,
64906c3fb27SDimitry Andric  constant_fold_fabs,
65006c3fb27SDimitry Andric  constant_fold_fsqrt,
65106c3fb27SDimitry Andric  constant_fold_flog2,
6525f757f3fSDimitry Andric  constant_fold_fptrunc,
6535f757f3fSDimitry Andric  itof_const_zero_fold_si,
6545f757f3fSDimitry Andric  itof_const_zero_fold_ui
65506c3fb27SDimitry Andric]>;
65606c3fb27SDimitry Andric
657e8d8bef9SDimitry Andric// Fold int2ptr(ptr2int(x)) -> x
658e8d8bef9SDimitry Andricdef p2i_to_i2p: GICombineRule<
659fe6060f1SDimitry Andric  (defs root:$root, register_matchinfo:$info),
660e8d8bef9SDimitry Andric  (match (wip_match_opcode G_INTTOPTR):$root,
661e8d8bef9SDimitry Andric    [{ return Helper.matchCombineI2PToP2I(*${root}, ${info}); }]),
662fe6060f1SDimitry Andric  (apply [{ Helper.applyCombineI2PToP2I(*${root}, ${info}); }])
663e8d8bef9SDimitry Andric>;
664e8d8bef9SDimitry Andric
665e8d8bef9SDimitry Andric// Fold ptr2int(int2ptr(x)) -> x
666e8d8bef9SDimitry Andricdef i2p_to_p2i: GICombineRule<
667bdd1243dSDimitry Andric  (defs root:$dst, register_matchinfo:$info),
668bdd1243dSDimitry Andric  (match (G_INTTOPTR $t, $ptr),
669bdd1243dSDimitry Andric         (G_PTRTOINT $dst, $t):$mi,
67006c3fb27SDimitry Andric    [{ ${info} = ${ptr}.getReg(); return true; }]),
671bdd1243dSDimitry Andric  (apply [{ Helper.applyCombineP2IToI2P(*${mi}, ${info}); }])
672e8d8bef9SDimitry Andric>;
673e8d8bef9SDimitry Andric
674e8d8bef9SDimitry Andric// Fold add ptrtoint(x), y -> ptrtoint (ptr_add x), y
675e8d8bef9SDimitry Andricdef add_p2i_to_ptradd_matchinfo : GIDefMatchData<"std::pair<Register, bool>">;
676e8d8bef9SDimitry Andricdef add_p2i_to_ptradd : GICombineRule<
677e8d8bef9SDimitry Andric  (defs root:$root, add_p2i_to_ptradd_matchinfo:$info),
678e8d8bef9SDimitry Andric  (match (wip_match_opcode G_ADD):$root,
679e8d8bef9SDimitry Andric    [{ return Helper.matchCombineAddP2IToPtrAdd(*${root}, ${info}); }]),
680fe6060f1SDimitry Andric  (apply [{ Helper.applyCombineAddP2IToPtrAdd(*${root}, ${info}); }])
681e8d8bef9SDimitry Andric>;
682e8d8bef9SDimitry Andric
683e8d8bef9SDimitry Andric// Fold (ptr_add (int2ptr C1), C2) -> C1 + C2
684e8d8bef9SDimitry Andricdef const_ptradd_to_i2p: GICombineRule<
685*0fca6ea1SDimitry Andric  (defs root:$root, apint_matchinfo:$info),
686e8d8bef9SDimitry Andric  (match (wip_match_opcode G_PTR_ADD):$root,
687e8d8bef9SDimitry Andric    [{ return Helper.matchCombineConstPtrAddToI2P(*${root}, ${info}); }]),
688fe6060f1SDimitry Andric  (apply [{ Helper.applyCombineConstPtrAddToI2P(*${root}, ${info}); }])
689e8d8bef9SDimitry Andric>;
690e8d8bef9SDimitry Andric
691e8d8bef9SDimitry Andric// Simplify: (logic_op (op x...), (op y...)) -> (op (logic_op x, y))
692e8d8bef9SDimitry Andricdef hoist_logic_op_with_same_opcode_hands: GICombineRule <
693e8d8bef9SDimitry Andric  (defs root:$root, instruction_steps_matchdata:$info),
694e8d8bef9SDimitry Andric  (match (wip_match_opcode G_AND, G_OR, G_XOR):$root,
695e8d8bef9SDimitry Andric    [{ return Helper.matchHoistLogicOpWithSameOpcodeHands(*${root}, ${info}); }]),
696fe6060f1SDimitry Andric  (apply [{ Helper.applyBuildInstructionSteps(*${root}, ${info});}])
697e8d8bef9SDimitry Andric>;
698e8d8bef9SDimitry Andric
699e8d8bef9SDimitry Andric// Fold ashr (shl x, C), C -> sext_inreg (C)
700e8d8bef9SDimitry Andricdef shl_ashr_to_sext_inreg_matchinfo : GIDefMatchData<"std::tuple<Register, int64_t>">;
701e8d8bef9SDimitry Andricdef shl_ashr_to_sext_inreg : GICombineRule<
702e8d8bef9SDimitry Andric  (defs root:$root, shl_ashr_to_sext_inreg_matchinfo:$info),
703e8d8bef9SDimitry Andric  (match (wip_match_opcode G_ASHR): $root,
704e8d8bef9SDimitry Andric    [{ return Helper.matchAshrShlToSextInreg(*${root}, ${info}); }]),
705fe6060f1SDimitry Andric  (apply [{ Helper.applyAshShlToSextInreg(*${root}, ${info});}])
706e8d8bef9SDimitry Andric>;
707fe6060f1SDimitry Andric
708fe6060f1SDimitry Andric// Fold and(and(x, C1), C2) -> C1&C2 ? and(x, C1&C2) : 0
709fe6060f1SDimitry Andricdef overlapping_and: GICombineRule <
710fe6060f1SDimitry Andric  (defs root:$root, build_fn_matchinfo:$info),
711fe6060f1SDimitry Andric  (match (wip_match_opcode G_AND):$root,
712fe6060f1SDimitry Andric         [{ return Helper.matchOverlappingAnd(*${root}, ${info}); }]),
713fe6060f1SDimitry Andric  (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])
714fe6060f1SDimitry Andric>;
715fe6060f1SDimitry Andric
716e8d8bef9SDimitry Andric// Fold (x & y) -> x or (x & y) -> y when (x & y) is known to equal x or equal y.
717e8d8bef9SDimitry Andricdef redundant_and: GICombineRule <
718fe6060f1SDimitry Andric  (defs root:$root, register_matchinfo:$matchinfo),
719e8d8bef9SDimitry Andric  (match (wip_match_opcode G_AND):$root,
720e8d8bef9SDimitry Andric         [{ return Helper.matchRedundantAnd(*${root}, ${matchinfo}); }]),
72106c3fb27SDimitry Andric  (apply [{ Helper.replaceSingleDefInstWithReg(*${root}, ${matchinfo}); }])
722e8d8bef9SDimitry Andric>;
723e8d8bef9SDimitry Andric
724e8d8bef9SDimitry Andric// Fold (x | y) -> x or (x | y) -> y when (x | y) is known to equal x or equal y.
725e8d8bef9SDimitry Andricdef redundant_or: GICombineRule <
726fe6060f1SDimitry Andric  (defs root:$root, register_matchinfo:$matchinfo),
727e8d8bef9SDimitry Andric  (match (wip_match_opcode G_OR):$root,
728e8d8bef9SDimitry Andric         [{ return Helper.matchRedundantOr(*${root}, ${matchinfo}); }]),
72906c3fb27SDimitry Andric  (apply [{ Helper.replaceSingleDefInstWithReg(*${root}, ${matchinfo}); }])
730e8d8bef9SDimitry Andric>;
731e8d8bef9SDimitry Andric
732e8d8bef9SDimitry Andric// If the input is already sign extended, just drop the extension.
733e8d8bef9SDimitry Andric// sext_inreg x, K ->
734e8d8bef9SDimitry Andric//   if computeNumSignBits(x) >= (x.getScalarSizeInBits() - K + 1)
735e8d8bef9SDimitry Andricdef redundant_sext_inreg: GICombineRule <
736e8d8bef9SDimitry Andric  (defs root:$root),
737e8d8bef9SDimitry Andric  (match (wip_match_opcode G_SEXT_INREG):$root,
738e8d8bef9SDimitry Andric         [{ return Helper.matchRedundantSExtInReg(*${root}); }]),
73906c3fb27SDimitry Andric     (apply [{ Helper.replaceSingleDefInstWithOperand(*${root}, 1); }])
740e8d8bef9SDimitry Andric>;
741e8d8bef9SDimitry Andric
742e8d8bef9SDimitry Andric// Fold (anyext (trunc x)) -> x if the source type is same as
743e8d8bef9SDimitry Andric// the destination type.
744e8d8bef9SDimitry Andricdef anyext_trunc_fold: GICombineRule <
745fe6060f1SDimitry Andric  (defs root:$root, register_matchinfo:$matchinfo),
746e8d8bef9SDimitry Andric  (match (wip_match_opcode G_ANYEXT):$root,
747e8d8bef9SDimitry Andric         [{ return Helper.matchCombineAnyExtTrunc(*${root}, ${matchinfo}); }]),
74806c3fb27SDimitry Andric  (apply [{ Helper.replaceSingleDefInstWithReg(*${root}, ${matchinfo}); }])
749fe6060f1SDimitry Andric>;
750fe6060f1SDimitry Andric
751fe6060f1SDimitry Andric// Fold (zext (trunc x)) -> x if the source type is same as the destination type
752fe6060f1SDimitry Andric// and truncated bits are known to be zero.
753fe6060f1SDimitry Andricdef zext_trunc_fold: GICombineRule <
754*0fca6ea1SDimitry Andric  (defs root:$root, register_matchinfo:$matchinfo),
755fe6060f1SDimitry Andric  (match (wip_match_opcode G_ZEXT):$root,
756fe6060f1SDimitry Andric         [{ return Helper.matchCombineZextTrunc(*${root}, ${matchinfo}); }]),
75706c3fb27SDimitry Andric  (apply [{ Helper.replaceSingleDefInstWithReg(*${root}, ${matchinfo}); }])
758e8d8bef9SDimitry Andric>;
759e8d8bef9SDimitry Andric
760e8d8bef9SDimitry Andric// Fold ([asz]ext ([asz]ext x)) -> ([asz]ext x).
761e8d8bef9SDimitry Andricdef ext_ext_fold_matchinfo : GIDefMatchData<"std::tuple<Register, unsigned>">;
762e8d8bef9SDimitry Andricdef ext_ext_fold: GICombineRule <
763e8d8bef9SDimitry Andric  (defs root:$root, ext_ext_fold_matchinfo:$matchinfo),
764e8d8bef9SDimitry Andric  (match (wip_match_opcode G_ANYEXT, G_SEXT, G_ZEXT):$root,
765e8d8bef9SDimitry Andric         [{ return Helper.matchCombineExtOfExt(*${root}, ${matchinfo}); }]),
766fe6060f1SDimitry Andric  (apply [{ Helper.applyCombineExtOfExt(*${root}, ${matchinfo}); }])
767e8d8bef9SDimitry Andric>;
768e8d8bef9SDimitry Andric
769e8d8bef9SDimitry Andricdef not_cmp_fold_matchinfo : GIDefMatchData<"SmallVector<Register, 4>">;
770e8d8bef9SDimitry Andricdef not_cmp_fold : GICombineRule<
771e8d8bef9SDimitry Andric  (defs root:$d, not_cmp_fold_matchinfo:$info),
772e8d8bef9SDimitry Andric  (match (wip_match_opcode G_XOR): $d,
773e8d8bef9SDimitry Andric  [{ return Helper.matchNotCmp(*${d}, ${info}); }]),
774fe6060f1SDimitry Andric  (apply [{ Helper.applyNotCmp(*${d}, ${info}); }])
775e8d8bef9SDimitry Andric>;
776e8d8bef9SDimitry Andric
777e8d8bef9SDimitry Andric// Fold (fneg (fneg x)) -> x.
778e8d8bef9SDimitry Andricdef fneg_fneg_fold: GICombineRule <
7795f757f3fSDimitry Andric  (defs root:$dst),
780bdd1243dSDimitry Andric  (match (G_FNEG $t, $src),
7815f757f3fSDimitry Andric         (G_FNEG $dst, $t)),
7825f757f3fSDimitry Andric  (apply (GIReplaceReg $dst, $src))
783e8d8bef9SDimitry Andric>;
784e8d8bef9SDimitry Andric
785e8d8bef9SDimitry Andric// Fold (unmerge(merge x, y, z)) -> z, y, z.
786e8d8bef9SDimitry Andricdef unmerge_merge_matchinfo : GIDefMatchData<"SmallVector<Register, 8>">;
787e8d8bef9SDimitry Andricdef unmerge_merge : GICombineRule<
788e8d8bef9SDimitry Andric  (defs root:$d, unmerge_merge_matchinfo:$info),
789e8d8bef9SDimitry Andric  (match (wip_match_opcode G_UNMERGE_VALUES): $d,
790e8d8bef9SDimitry Andric  [{ return Helper.matchCombineUnmergeMergeToPlainValues(*${d}, ${info}); }]),
791fe6060f1SDimitry Andric  (apply [{ Helper.applyCombineUnmergeMergeToPlainValues(*${d}, ${info}); }])
792fe6060f1SDimitry Andric>;
793fe6060f1SDimitry Andric
794fe6060f1SDimitry Andric// Fold merge(unmerge).
795fe6060f1SDimitry Andricdef merge_unmerge : GICombineRule<
796fe6060f1SDimitry Andric  (defs root:$d, register_matchinfo:$matchinfo),
797fe6060f1SDimitry Andric  (match (wip_match_opcode G_MERGE_VALUES):$d,
798fe6060f1SDimitry Andric  [{ return Helper.matchCombineMergeUnmerge(*${d}, ${matchinfo}); }]),
799fe6060f1SDimitry Andric  (apply [{ Helper.replaceSingleDefInstWithReg(*${d}, ${matchinfo}); }])
800e8d8bef9SDimitry Andric>;
801e8d8bef9SDimitry Andric
802349cc55cSDimitry Andric// Fold (fabs (fneg x)) -> (fabs x).
803349cc55cSDimitry Andricdef fabs_fneg_fold: GICombineRule <
8045f757f3fSDimitry Andric  (defs root:$dst),
8055f757f3fSDimitry Andric  (match  (G_FNEG $tmp, $x),
8065f757f3fSDimitry Andric          (G_FABS $dst, $tmp)),
8075f757f3fSDimitry Andric  (apply (G_FABS $dst, $x))>;
808349cc55cSDimitry Andric
809e8d8bef9SDimitry Andric// Fold (unmerge cst) -> cst1, cst2, ...
810e8d8bef9SDimitry Andricdef unmerge_cst_matchinfo : GIDefMatchData<"SmallVector<APInt, 8>">;
811e8d8bef9SDimitry Andricdef unmerge_cst : GICombineRule<
812e8d8bef9SDimitry Andric  (defs root:$d, unmerge_cst_matchinfo:$info),
813e8d8bef9SDimitry Andric  (match (wip_match_opcode G_UNMERGE_VALUES): $d,
814e8d8bef9SDimitry Andric  [{ return Helper.matchCombineUnmergeConstant(*${d}, ${info}); }]),
815fe6060f1SDimitry Andric  (apply [{ Helper.applyCombineUnmergeConstant(*${d}, ${info}); }])
816e8d8bef9SDimitry Andric>;
817e8d8bef9SDimitry Andric
81804eeddc0SDimitry Andric// Fold (unmerge undef) -> undef, undef, ...
81904eeddc0SDimitry Andricdef unmerge_undef : GICombineRule<
82004eeddc0SDimitry Andric  (defs root:$root, build_fn_matchinfo:$info),
82104eeddc0SDimitry Andric  (match (wip_match_opcode G_UNMERGE_VALUES): $root,
82204eeddc0SDimitry Andric         [{ return Helper.matchCombineUnmergeUndef(*${root}, ${info}); }]),
82304eeddc0SDimitry Andric  (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])
82404eeddc0SDimitry Andric>;
82504eeddc0SDimitry Andric
826e8d8bef9SDimitry Andric// Transform x,y<dead> = unmerge z -> x = trunc z.
827e8d8bef9SDimitry Andricdef unmerge_dead_to_trunc : GICombineRule<
828e8d8bef9SDimitry Andric  (defs root:$d),
829e8d8bef9SDimitry Andric  (match (wip_match_opcode G_UNMERGE_VALUES): $d,
830e8d8bef9SDimitry Andric  [{ return Helper.matchCombineUnmergeWithDeadLanesToTrunc(*${d}); }]),
831fe6060f1SDimitry Andric  (apply [{ Helper.applyCombineUnmergeWithDeadLanesToTrunc(*${d}); }])
832e8d8bef9SDimitry Andric>;
833e8d8bef9SDimitry Andric
834e8d8bef9SDimitry Andric// Transform x,y = unmerge(zext(z)) -> x = zext z; y = 0.
835e8d8bef9SDimitry Andricdef unmerge_zext_to_zext : GICombineRule<
836e8d8bef9SDimitry Andric  (defs root:$d),
837e8d8bef9SDimitry Andric  (match (wip_match_opcode G_UNMERGE_VALUES): $d,
838e8d8bef9SDimitry Andric  [{ return Helper.matchCombineUnmergeZExtToZExt(*${d}); }]),
839fe6060f1SDimitry Andric  (apply [{ Helper.applyCombineUnmergeZExtToZExt(*${d}); }])
840e8d8bef9SDimitry Andric>;
841e8d8bef9SDimitry Andric
842e8d8bef9SDimitry Andric// Fold trunc ([asz]ext x) -> x or ([asz]ext x) or (trunc x).
843e8d8bef9SDimitry Andricdef trunc_ext_fold_matchinfo : GIDefMatchData<"std::pair<Register, unsigned>">;
844e8d8bef9SDimitry Andricdef trunc_ext_fold: GICombineRule <
845e8d8bef9SDimitry Andric  (defs root:$root, trunc_ext_fold_matchinfo:$matchinfo),
846e8d8bef9SDimitry Andric  (match (wip_match_opcode G_TRUNC):$root,
847e8d8bef9SDimitry Andric         [{ return Helper.matchCombineTruncOfExt(*${root}, ${matchinfo}); }]),
848fe6060f1SDimitry Andric  (apply [{ Helper.applyCombineTruncOfExt(*${root}, ${matchinfo}); }])
849e8d8bef9SDimitry Andric>;
850e8d8bef9SDimitry Andric
851bdd1243dSDimitry Andric// Under certain conditions, transform:
852bdd1243dSDimitry Andric//  trunc (shl x, K)     -> shl (trunc x), K//
853bdd1243dSDimitry Andric//  trunc ([al]shr x, K) -> (trunc ([al]shr (trunc x), K))
854bdd1243dSDimitry Andricdef trunc_shift_matchinfo : GIDefMatchData<"std::pair<MachineInstr*, LLT>">;
855bdd1243dSDimitry Andricdef trunc_shift: GICombineRule <
856bdd1243dSDimitry Andric  (defs root:$root, trunc_shift_matchinfo:$matchinfo),
857e8d8bef9SDimitry Andric  (match (wip_match_opcode G_TRUNC):$root,
858bdd1243dSDimitry Andric         [{ return Helper.matchCombineTruncOfShift(*${root}, ${matchinfo}); }]),
859bdd1243dSDimitry Andric  (apply [{ Helper.applyCombineTruncOfShift(*${root}, ${matchinfo}); }])
860e8d8bef9SDimitry Andric>;
861e8d8bef9SDimitry Andric
862e8d8bef9SDimitry Andric// Transform (mul x, -1) -> (sub 0, x)
863e8d8bef9SDimitry Andricdef mul_by_neg_one: GICombineRule <
8645f757f3fSDimitry Andric  (defs root:$dst),
8655f757f3fSDimitry Andric  (match (G_MUL $dst, $x, -1)),
8665f757f3fSDimitry Andric  (apply (G_SUB $dst, 0, $x))
867e8d8bef9SDimitry Andric>;
868e8d8bef9SDimitry Andric
869e8d8bef9SDimitry Andric// Fold (xor (and x, y), y) -> (and (not x), y)
870e8d8bef9SDimitry Andricdef xor_of_and_with_same_reg_matchinfo :
871e8d8bef9SDimitry Andric    GIDefMatchData<"std::pair<Register, Register>">;
872e8d8bef9SDimitry Andricdef xor_of_and_with_same_reg: GICombineRule <
873e8d8bef9SDimitry Andric  (defs root:$root, xor_of_and_with_same_reg_matchinfo:$matchinfo),
874e8d8bef9SDimitry Andric  (match (wip_match_opcode G_XOR):$root,
875e8d8bef9SDimitry Andric         [{ return Helper.matchXorOfAndWithSameReg(*${root}, ${matchinfo}); }]),
876fe6060f1SDimitry Andric  (apply [{ Helper.applyXorOfAndWithSameReg(*${root}, ${matchinfo}); }])
877e8d8bef9SDimitry Andric>;
878e8d8bef9SDimitry Andric
879e8d8bef9SDimitry Andric// Transform (ptr_add 0, x) -> (int_to_ptr x)
880e8d8bef9SDimitry Andricdef ptr_add_with_zero: GICombineRule<
881e8d8bef9SDimitry Andric  (defs root:$root),
882e8d8bef9SDimitry Andric  (match (wip_match_opcode G_PTR_ADD):$root,
883e8d8bef9SDimitry Andric         [{ return Helper.matchPtrAddZero(*${root}); }]),
884fe6060f1SDimitry Andric  (apply [{ Helper.applyPtrAddZero(*${root}); }])>;
885e8d8bef9SDimitry Andric
886e8d8bef9SDimitry Andricdef regs_small_vec : GIDefMatchData<"SmallVector<Register, 4>">;
887e8d8bef9SDimitry Andricdef combine_insert_vec_elts_build_vector : GICombineRule<
888e8d8bef9SDimitry Andric  (defs root:$root, regs_small_vec:$info),
889e8d8bef9SDimitry Andric  (match (wip_match_opcode G_INSERT_VECTOR_ELT):$root,
890e8d8bef9SDimitry Andric    [{ return Helper.matchCombineInsertVecElts(*${root}, ${info}); }]),
891fe6060f1SDimitry Andric  (apply [{ Helper.applyCombineInsertVecElts(*${root}, ${info}); }])>;
892e8d8bef9SDimitry Andric
893e8d8bef9SDimitry Andricdef load_or_combine : GICombineRule<
894fe6060f1SDimitry Andric  (defs root:$root, build_fn_matchinfo:$info),
895e8d8bef9SDimitry Andric  (match (wip_match_opcode G_OR):$root,
896e8d8bef9SDimitry Andric    [{ return Helper.matchLoadOrCombine(*${root}, ${info}); }]),
897fe6060f1SDimitry Andric  (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>;
898fe6060f1SDimitry Andric
899fe6060f1SDimitry Andricdef extend_through_phis_matchdata: GIDefMatchData<"MachineInstr*">;
900fe6060f1SDimitry Andricdef extend_through_phis : GICombineRule<
901fe6060f1SDimitry Andric  (defs root:$root, extend_through_phis_matchdata:$matchinfo),
902fe6060f1SDimitry Andric  (match (wip_match_opcode G_PHI):$root,
903fe6060f1SDimitry Andric    [{ return Helper.matchExtendThroughPhis(*${root}, ${matchinfo}); }]),
904fe6060f1SDimitry Andric  (apply [{ Helper.applyExtendThroughPhis(*${root}, ${matchinfo}); }])>;
905e8d8bef9SDimitry Andric
906e8d8bef9SDimitry Andric// Currently only the one combine above.
907e8d8bef9SDimitry Andricdef insert_vec_elt_combines : GICombineGroup<
908e8d8bef9SDimitry Andric                            [combine_insert_vec_elts_build_vector]>;
909e8d8bef9SDimitry Andric
910fe6060f1SDimitry Andricdef extract_vec_elt_build_vec : GICombineRule<
911fe6060f1SDimitry Andric  (defs root:$root, register_matchinfo:$matchinfo),
912fe6060f1SDimitry Andric  (match (wip_match_opcode G_EXTRACT_VECTOR_ELT):$root,
913fe6060f1SDimitry Andric    [{ return Helper.matchExtractVecEltBuildVec(*${root}, ${matchinfo}); }]),
914fe6060f1SDimitry Andric  (apply [{ Helper.applyExtractVecEltBuildVec(*${root}, ${matchinfo}); }])>;
915fe6060f1SDimitry Andric
916fe6060f1SDimitry Andric// Fold away full elt extracts from a build_vector.
917fe6060f1SDimitry Andricdef extract_all_elts_from_build_vector_matchinfo :
918fe6060f1SDimitry Andric  GIDefMatchData<"SmallVector<std::pair<Register, MachineInstr*>>">;
919fe6060f1SDimitry Andricdef extract_all_elts_from_build_vector : GICombineRule<
920fe6060f1SDimitry Andric  (defs root:$root, extract_all_elts_from_build_vector_matchinfo:$matchinfo),
921fe6060f1SDimitry Andric  (match (wip_match_opcode G_BUILD_VECTOR):$root,
922fe6060f1SDimitry Andric    [{ return Helper.matchExtractAllEltsFromBuildVector(*${root}, ${matchinfo}); }]),
923fe6060f1SDimitry Andric  (apply [{ Helper.applyExtractAllEltsFromBuildVector(*${root}, ${matchinfo}); }])>;
924fe6060f1SDimitry Andric
925fe6060f1SDimitry Andricdef extract_vec_elt_combines : GICombineGroup<[
926fe6060f1SDimitry Andric  extract_vec_elt_build_vec,
927fe6060f1SDimitry Andric  extract_all_elts_from_build_vector]>;
928fe6060f1SDimitry Andric
9294824e7fdSDimitry Andricdef funnel_shift_from_or_shift : GICombineRule<
9304824e7fdSDimitry Andric  (defs root:$root, build_fn_matchinfo:$info),
9314824e7fdSDimitry Andric  (match (wip_match_opcode G_OR):$root,
9324824e7fdSDimitry Andric    [{ return Helper.matchOrShiftToFunnelShift(*${root}, ${info}); }]),
9334824e7fdSDimitry Andric  (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])
9344824e7fdSDimitry Andric>;
9354824e7fdSDimitry Andric
936fe6060f1SDimitry Andricdef funnel_shift_to_rotate : GICombineRule<
937fe6060f1SDimitry Andric  (defs root:$root),
938fe6060f1SDimitry Andric  (match (wip_match_opcode G_FSHL, G_FSHR):$root,
939fe6060f1SDimitry Andric    [{ return Helper.matchFunnelShiftToRotate(*${root}); }]),
940fe6060f1SDimitry Andric  (apply [{ Helper.applyFunnelShiftToRotate(*${root}); }])
941fe6060f1SDimitry Andric>;
942fe6060f1SDimitry Andric
9435f757f3fSDimitry Andric// Fold fshr x, y, 0 -> y
9445f757f3fSDimitry Andricdef funnel_shift_right_zero: GICombineRule<
9455f757f3fSDimitry Andric  (defs root:$root),
9465f757f3fSDimitry Andric  (match (G_FSHR $x, $y, $z, 0):$root),
9475f757f3fSDimitry Andric  (apply (COPY $x, $z))
9485f757f3fSDimitry Andric>;
9495f757f3fSDimitry Andric
9505f757f3fSDimitry Andric// Fold fshl x, y, 0 -> x
9515f757f3fSDimitry Andricdef funnel_shift_left_zero: GICombineRule<
9525f757f3fSDimitry Andric  (defs root:$root),
9535f757f3fSDimitry Andric  (match (G_FSHL $x, $y, $z, 0):$root),
9545f757f3fSDimitry Andric  (apply (COPY $x, $y))
9555f757f3fSDimitry Andric>;
9565f757f3fSDimitry Andric
9575f757f3fSDimitry Andric// Fold fsh(l/r) x, y, C -> fsh(l/r) x, y, C % bw
9585f757f3fSDimitry Andricdef funnel_shift_overshift: GICombineRule<
9595f757f3fSDimitry Andric  (defs root:$root),
9605f757f3fSDimitry Andric  (match (wip_match_opcode G_FSHL, G_FSHR):$root,
9615f757f3fSDimitry Andric    [{ return Helper.matchConstantLargerBitWidth(*${root}, 3); }]),
9625f757f3fSDimitry Andric  (apply [{ Helper.applyFunnelShiftConstantModulo(*${root}); }])
9635f757f3fSDimitry Andric>;
9645f757f3fSDimitry Andric
965fe6060f1SDimitry Andricdef rotate_out_of_range : GICombineRule<
966fe6060f1SDimitry Andric  (defs root:$root),
967fe6060f1SDimitry Andric  (match (wip_match_opcode G_ROTR, G_ROTL):$root,
968fe6060f1SDimitry Andric    [{ return Helper.matchRotateOutOfRange(*${root}); }]),
969fe6060f1SDimitry Andric  (apply [{ Helper.applyRotateOutOfRange(*${root}); }])
970fe6060f1SDimitry Andric>;
971fe6060f1SDimitry Andric
972fe6060f1SDimitry Andricdef icmp_to_true_false_known_bits : GICombineRule<
973fe6060f1SDimitry Andric  (defs root:$d, int64_matchinfo:$matchinfo),
974fe6060f1SDimitry Andric  (match (wip_match_opcode G_ICMP):$d,
975fe6060f1SDimitry Andric         [{ return Helper.matchICmpToTrueFalseKnownBits(*${d}, ${matchinfo}); }]),
976fe6060f1SDimitry Andric  (apply [{ Helper.replaceInstWithConstant(*${d}, ${matchinfo}); }])>;
977fe6060f1SDimitry Andric
978349cc55cSDimitry Andricdef icmp_to_lhs_known_bits : GICombineRule<
979349cc55cSDimitry Andric  (defs root:$root, build_fn_matchinfo:$info),
980349cc55cSDimitry Andric  (match (wip_match_opcode G_ICMP):$root,
981349cc55cSDimitry Andric         [{ return Helper.matchICmpToLHSKnownBits(*${root}, ${info}); }]),
982349cc55cSDimitry Andric  (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>;
983349cc55cSDimitry Andric
984bdd1243dSDimitry Andricdef redundant_binop_in_equality : GICombineRule<
985bdd1243dSDimitry Andric  (defs root:$root, build_fn_matchinfo:$info),
986bdd1243dSDimitry Andric  (match (wip_match_opcode G_ICMP):$root,
987bdd1243dSDimitry Andric         [{ return Helper.matchRedundantBinOpInEquality(*${root}, ${info}); }]),
988bdd1243dSDimitry Andric  (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>;
989bdd1243dSDimitry Andric
990*0fca6ea1SDimitry Andric// Transform: (X == 0 & Y == 0) -> (X | Y) == 0
991*0fca6ea1SDimitry Andricdef double_icmp_zero_and_combine: GICombineRule<
992*0fca6ea1SDimitry Andric  (defs root:$root),
993*0fca6ea1SDimitry Andric  (match (G_ICMP $d1, $p, $s1, 0),
994*0fca6ea1SDimitry Andric         (G_ICMP $d2, $p, $s2, 0),
995*0fca6ea1SDimitry Andric         (G_AND $root, $d1, $d2),
996*0fca6ea1SDimitry Andric         [{ return ${p}.getPredicate() == CmpInst::ICMP_EQ &&
997*0fca6ea1SDimitry Andric                       !MRI.getType(${s1}.getReg()).getScalarType().isPointer() &&
998*0fca6ea1SDimitry Andric                       (MRI.getType(${s1}.getReg()) ==
999*0fca6ea1SDimitry Andric                           MRI.getType(${s2}.getReg())); }]),
1000*0fca6ea1SDimitry Andric  (apply (G_OR $ordst, $s1, $s2),
1001*0fca6ea1SDimitry Andric         (G_ICMP $root, $p, $ordst, 0))
1002*0fca6ea1SDimitry Andric>;
1003*0fca6ea1SDimitry Andric
1004*0fca6ea1SDimitry Andric// Transform: (X != 0 | Y != 0) -> (X | Y) != 0
1005*0fca6ea1SDimitry Andricdef double_icmp_zero_or_combine: GICombineRule<
1006*0fca6ea1SDimitry Andric  (defs root:$root),
1007*0fca6ea1SDimitry Andric  (match (G_ICMP $d1, $p, $s1, 0),
1008*0fca6ea1SDimitry Andric         (G_ICMP $d2, $p, $s2, 0),
1009*0fca6ea1SDimitry Andric         (G_OR $root, $d1, $d2),
1010*0fca6ea1SDimitry Andric         [{ return ${p}.getPredicate() == CmpInst::ICMP_NE &&
1011*0fca6ea1SDimitry Andric                       !MRI.getType(${s1}.getReg()).getScalarType().isPointer() &&
1012*0fca6ea1SDimitry Andric                       (MRI.getType(${s1}.getReg()) ==
1013*0fca6ea1SDimitry Andric                           MRI.getType(${s2}.getReg())); }]),
1014*0fca6ea1SDimitry Andric  (apply (G_OR $ordst, $s1, $s2),
1015*0fca6ea1SDimitry Andric         (G_ICMP $root, $p, $ordst, 0))
1016*0fca6ea1SDimitry Andric>;
1017*0fca6ea1SDimitry Andric
1018*0fca6ea1SDimitry Andricdef double_icmp_zero_and_or_combine : GICombineGroup<[double_icmp_zero_and_combine,
1019*0fca6ea1SDimitry Andric                                                      double_icmp_zero_or_combine]>;
1020*0fca6ea1SDimitry Andric
1021349cc55cSDimitry Andricdef and_or_disjoint_mask : GICombineRule<
1022349cc55cSDimitry Andric  (defs root:$root, build_fn_matchinfo:$info),
1023349cc55cSDimitry Andric  (match (wip_match_opcode G_AND):$root,
1024349cc55cSDimitry Andric         [{ return Helper.matchAndOrDisjointMask(*${root}, ${info}); }]),
1025349cc55cSDimitry Andric  (apply [{ Helper.applyBuildFnNoErase(*${root}, ${info}); }])>;
1026349cc55cSDimitry Andric
1027fe6060f1SDimitry Andricdef bitfield_extract_from_and : GICombineRule<
1028fe6060f1SDimitry Andric  (defs root:$root, build_fn_matchinfo:$info),
1029*0fca6ea1SDimitry Andric  (match (G_CONSTANT $mask, $imm2),
1030*0fca6ea1SDimitry Andric         (G_CONSTANT $lsb, $imm1),
1031*0fca6ea1SDimitry Andric         (G_LSHR $shift, $x, $lsb),
1032*0fca6ea1SDimitry Andric         (G_AND $root, $shift, $mask):$root,
1033fe6060f1SDimitry Andric    [{ return Helper.matchBitfieldExtractFromAnd(*${root}, ${info}); }]),
1034fe6060f1SDimitry Andric  (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>;
1035fe6060f1SDimitry Andric
10364824e7fdSDimitry Andricdef funnel_shift_combines : GICombineGroup<[funnel_shift_from_or_shift,
10375f757f3fSDimitry Andric                                            funnel_shift_to_rotate,
10385f757f3fSDimitry Andric                                            funnel_shift_right_zero,
10395f757f3fSDimitry Andric                                            funnel_shift_left_zero,
10405f757f3fSDimitry Andric                                            funnel_shift_overshift]>;
1041fe6060f1SDimitry Andric
1042fe6060f1SDimitry Andricdef bitfield_extract_from_sext_inreg : GICombineRule<
1043fe6060f1SDimitry Andric  (defs root:$root, build_fn_matchinfo:$info),
1044fe6060f1SDimitry Andric  (match (wip_match_opcode G_SEXT_INREG):$root,
1045fe6060f1SDimitry Andric    [{ return Helper.matchBitfieldExtractFromSExtInReg(*${root}, ${info}); }]),
1046fe6060f1SDimitry Andric  (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>;
1047fe6060f1SDimitry Andric
1048349cc55cSDimitry Andricdef bitfield_extract_from_shr : GICombineRule<
1049349cc55cSDimitry Andric  (defs root:$root, build_fn_matchinfo:$info),
1050349cc55cSDimitry Andric  (match (wip_match_opcode G_ASHR, G_LSHR):$root,
1051349cc55cSDimitry Andric    [{ return Helper.matchBitfieldExtractFromShr(*${root}, ${info}); }]),
1052349cc55cSDimitry Andric  (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>;
1053349cc55cSDimitry Andric
1054349cc55cSDimitry Andricdef bitfield_extract_from_shr_and : GICombineRule<
1055349cc55cSDimitry Andric  (defs root:$root, build_fn_matchinfo:$info),
1056349cc55cSDimitry Andric  (match (wip_match_opcode G_ASHR, G_LSHR):$root,
1057349cc55cSDimitry Andric    [{ return Helper.matchBitfieldExtractFromShrAnd(*${root}, ${info}); }]),
1058349cc55cSDimitry Andric  (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>;
1059349cc55cSDimitry Andric
1060fe6060f1SDimitry Andricdef form_bitfield_extract : GICombineGroup<[bitfield_extract_from_sext_inreg,
1061349cc55cSDimitry Andric                                            bitfield_extract_from_and,
1062349cc55cSDimitry Andric                                            bitfield_extract_from_shr,
1063349cc55cSDimitry Andric                                            bitfield_extract_from_shr_and]>;
1064349cc55cSDimitry Andric
1065349cc55cSDimitry Andricdef udiv_by_const : GICombineRule<
1066349cc55cSDimitry Andric  (defs root:$root),
1067349cc55cSDimitry Andric  (match (wip_match_opcode G_UDIV):$root,
1068349cc55cSDimitry Andric   [{ return Helper.matchUDivByConst(*${root}); }]),
1069349cc55cSDimitry Andric  (apply [{ Helper.applyUDivByConst(*${root}); }])>;
1070349cc55cSDimitry Andric
1071bdd1243dSDimitry Andricdef sdiv_by_const : GICombineRule<
1072bdd1243dSDimitry Andric  (defs root:$root),
1073bdd1243dSDimitry Andric  (match (wip_match_opcode G_SDIV):$root,
1074bdd1243dSDimitry Andric   [{ return Helper.matchSDivByConst(*${root}); }]),
1075bdd1243dSDimitry Andric  (apply [{ Helper.applySDivByConst(*${root}); }])>;
1076bdd1243dSDimitry Andric
1077*0fca6ea1SDimitry Andricdef sdiv_by_pow2 : GICombineRule<
1078*0fca6ea1SDimitry Andric  (defs root:$root),
1079*0fca6ea1SDimitry Andric  (match (G_SDIV $dst, $x, $y, (MIFlags (not IsExact))):$root,
1080*0fca6ea1SDimitry Andric   [{ return Helper.matchDivByPow2(*${root}, /*IsSigned=*/true); }]),
1081*0fca6ea1SDimitry Andric  (apply [{ Helper.applySDivByPow2(*${root}); }])>;
1082*0fca6ea1SDimitry Andric
1083*0fca6ea1SDimitry Andricdef udiv_by_pow2 : GICombineRule<
1084*0fca6ea1SDimitry Andric  (defs root:$root),
1085*0fca6ea1SDimitry Andric  (match (G_UDIV $dst, $x, $y, (MIFlags (not IsExact))):$root,
1086*0fca6ea1SDimitry Andric   [{ return Helper.matchDivByPow2(*${root}, /*IsSigned=*/false); }]),
1087*0fca6ea1SDimitry Andric  (apply [{ Helper.applyUDivByPow2(*${root}); }])>;
1088*0fca6ea1SDimitry Andric
1089*0fca6ea1SDimitry Andricdef intdiv_combines : GICombineGroup<[udiv_by_const, sdiv_by_const,
1090*0fca6ea1SDimitry Andric                                      sdiv_by_pow2, udiv_by_pow2]>;
1091349cc55cSDimitry Andric
1092fe6060f1SDimitry Andricdef reassoc_ptradd : GICombineRule<
1093fe6060f1SDimitry Andric  (defs root:$root, build_fn_matchinfo:$matchinfo),
1094fe6060f1SDimitry Andric  (match (wip_match_opcode G_PTR_ADD):$root,
1095fe6060f1SDimitry Andric    [{ return Helper.matchReassocPtrAdd(*${root}, ${matchinfo}); }]),
1096fe6060f1SDimitry Andric  (apply [{ Helper.applyBuildFnNoErase(*${root}, ${matchinfo}); }])>;
1097fe6060f1SDimitry Andric
109806c3fb27SDimitry Andricdef reassoc_comm_binops : GICombineRule<
109906c3fb27SDimitry Andric  (defs root:$root, build_fn_matchinfo:$matchinfo),
110006c3fb27SDimitry Andric  (match (G_ADD $root, $src1, $src2):$root,
110106c3fb27SDimitry Andric    [{ return Helper.matchReassocCommBinOp(*${root}, ${matchinfo}); }]),
110206c3fb27SDimitry Andric  (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>;
110306c3fb27SDimitry Andric
110406c3fb27SDimitry Andricdef reassocs : GICombineGroup<[reassoc_ptradd, reassoc_comm_binops]>;
1105fe6060f1SDimitry Andric
1106fe6060f1SDimitry Andric// Constant fold operations.
11075f757f3fSDimitry Andricdef constant_fold_binop : GICombineRule<
1108fe6060f1SDimitry Andric  (defs root:$d, apint_matchinfo:$matchinfo),
11095f757f3fSDimitry Andric  (match (wip_match_opcode G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR, G_SHL, G_LSHR, G_ASHR):$d,
11105f757f3fSDimitry Andric   [{ return Helper.matchConstantFoldBinOp(*${d}, ${matchinfo}); }]),
11115f757f3fSDimitry Andric  (apply [{ Helper.replaceInstWithConstant(*${d}, ${matchinfo}); }])>;
11125f757f3fSDimitry Andric
11135f757f3fSDimitry Andricdef constant_fold_fp_binop : GICombineRule<
11145f757f3fSDimitry Andric  (defs root:$d, constantfp_matchinfo:$matchinfo),
11155f757f3fSDimitry Andric  (match (wip_match_opcode G_FADD, G_FSUB, G_FMUL, G_FDIV):$d,
11165f757f3fSDimitry Andric   [{ return Helper.matchConstantFoldFPBinOp(*${d}, ${matchinfo}); }]),
11175f757f3fSDimitry Andric  (apply [{ Helper.replaceInstWithFConstant(*${d}, ${matchinfo}); }])>;
11185f757f3fSDimitry Andric
11195f757f3fSDimitry Andric
11205f757f3fSDimitry Andricdef constant_fold_fma : GICombineRule<
11215f757f3fSDimitry Andric  (defs root:$d, constantfp_matchinfo:$matchinfo),
11225f757f3fSDimitry Andric  (match (wip_match_opcode G_FMAD, G_FMA):$d,
11235f757f3fSDimitry Andric   [{ return Helper.matchConstantFoldFMA(*${d}, ${matchinfo}); }]),
11245f757f3fSDimitry Andric  (apply [{ Helper.replaceInstWithFConstant(*${d}, ${matchinfo}); }])>;
11255f757f3fSDimitry Andric
11265f757f3fSDimitry Andricdef constant_fold_cast_op : GICombineRule<
11275f757f3fSDimitry Andric  (defs root:$d, apint_matchinfo:$matchinfo),
11285f757f3fSDimitry Andric  (match (wip_match_opcode G_ZEXT, G_SEXT, G_ANYEXT):$d,
11295f757f3fSDimitry Andric   [{ return Helper.matchConstantFoldCastOp(*${d}, ${matchinfo}); }]),
1130fe6060f1SDimitry Andric  (apply [{ Helper.replaceInstWithConstant(*${d}, ${matchinfo}); }])>;
1131fe6060f1SDimitry Andric
1132349cc55cSDimitry Andricdef mulo_by_2: GICombineRule<
1133349cc55cSDimitry Andric  (defs root:$root, build_fn_matchinfo:$matchinfo),
1134349cc55cSDimitry Andric  (match (wip_match_opcode G_UMULO, G_SMULO):$root,
1135349cc55cSDimitry Andric         [{ return Helper.matchMulOBy2(*${root}, ${matchinfo}); }]),
1136349cc55cSDimitry Andric  (apply [{ Helper.applyBuildFnNoErase(*${root}, ${matchinfo}); }])>;
1137349cc55cSDimitry Andric
113881ad6265SDimitry Andricdef mulo_by_0: GICombineRule<
113981ad6265SDimitry Andric  (defs root:$root, build_fn_matchinfo:$matchinfo),
114081ad6265SDimitry Andric  (match (wip_match_opcode G_UMULO, G_SMULO):$root,
114181ad6265SDimitry Andric         [{ return Helper.matchMulOBy0(*${root}, ${matchinfo}); }]),
114281ad6265SDimitry Andric  (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>;
114381ad6265SDimitry Andric
1144bdd1243dSDimitry Andric// Transform (uadde x, y, 0) -> (uaddo x, y)
1145bdd1243dSDimitry Andric//           (sadde x, y, 0) -> (saddo x, y)
1146bdd1243dSDimitry Andric//           (usube x, y, 0) -> (usubo x, y)
1147bdd1243dSDimitry Andric//           (ssube x, y, 0) -> (ssubo x, y)
1148bdd1243dSDimitry Andricdef adde_to_addo: GICombineRule<
1149bdd1243dSDimitry Andric  (defs root:$root, build_fn_matchinfo:$matchinfo),
1150bdd1243dSDimitry Andric  (match (wip_match_opcode G_UADDE, G_SADDE, G_USUBE, G_SSUBE):$root,
1151bdd1243dSDimitry Andric         [{ return Helper.matchAddEToAddO(*${root}, ${matchinfo}); }]),
1152bdd1243dSDimitry Andric  (apply [{ Helper.applyBuildFnNoErase(*${root}, ${matchinfo}); }])>;
1153bdd1243dSDimitry Andric
1154349cc55cSDimitry Andricdef mulh_to_lshr : GICombineRule<
1155349cc55cSDimitry Andric  (defs root:$root),
1156349cc55cSDimitry Andric  (match (wip_match_opcode G_UMULH):$root,
1157349cc55cSDimitry Andric         [{ return Helper.matchUMulHToLShr(*${root}); }]),
1158349cc55cSDimitry Andric  (apply [{ Helper.applyUMulHToLShr(*${root}); }])>;
1159349cc55cSDimitry Andric
1160349cc55cSDimitry Andricdef mulh_combines : GICombineGroup<[mulh_to_lshr]>;
1161349cc55cSDimitry Andric
1162349cc55cSDimitry Andricdef redundant_neg_operands: GICombineRule<
1163349cc55cSDimitry Andric  (defs root:$root, build_fn_matchinfo:$matchinfo),
1164349cc55cSDimitry Andric  (match (wip_match_opcode G_FADD, G_FSUB, G_FMUL, G_FDIV, G_FMAD, G_FMA):$root,
1165349cc55cSDimitry Andric    [{ return Helper.matchRedundantNegOperands(*${root}, ${matchinfo}); }]),
1166349cc55cSDimitry Andric  (apply [{ Helper.applyBuildFnNoErase(*${root}, ${matchinfo}); }])>;
1167349cc55cSDimitry Andric
1168bdd1243dSDimitry Andric// Transform (fsub +-0.0, X) -> (fneg X)
1169bdd1243dSDimitry Andricdef fsub_to_fneg: GICombineRule<
1170bdd1243dSDimitry Andric  (defs root:$root, register_matchinfo:$matchinfo),
1171bdd1243dSDimitry Andric  (match (wip_match_opcode G_FSUB):$root,
1172bdd1243dSDimitry Andric    [{ return Helper.matchFsubToFneg(*${root}, ${matchinfo}); }]),
1173bdd1243dSDimitry Andric  (apply [{ Helper.applyFsubToFneg(*${root}, ${matchinfo}); }])>;
1174bdd1243dSDimitry Andric
11754824e7fdSDimitry Andric// Transform (fadd x, (fmul y, z)) -> (fma y, z, x)
11764824e7fdSDimitry Andric//           (fadd x, (fmul y, z)) -> (fmad y, z, x)
11774824e7fdSDimitry Andric// Transform (fadd (fmul x, y), z) -> (fma x, y, z)
11784824e7fdSDimitry Andric//           (fadd (fmul x, y), z) -> (fmad x, y, z)
11794824e7fdSDimitry Andricdef combine_fadd_fmul_to_fmad_or_fma: GICombineRule<
11804824e7fdSDimitry Andric  (defs root:$root, build_fn_matchinfo:$info),
11814824e7fdSDimitry Andric  (match (wip_match_opcode G_FADD):$root,
11824824e7fdSDimitry Andric         [{ return Helper.matchCombineFAddFMulToFMadOrFMA(*${root},
11834824e7fdSDimitry Andric                                                          ${info}); }]),
11844824e7fdSDimitry Andric  (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>;
11854824e7fdSDimitry Andric
11864824e7fdSDimitry Andric// Transform (fadd (fpext (fmul x, y)), z) -> (fma (fpext x), (fpext y), z)
11874824e7fdSDimitry Andric//                                         -> (fmad (fpext x), (fpext y), z)
11884824e7fdSDimitry Andric// Transform (fadd x, (fpext (fmul y, z))) -> (fma (fpext y), (fpext z), x)
11894824e7fdSDimitry Andric//                                         -> (fmad (fpext y), (fpext z), x)
11904824e7fdSDimitry Andricdef combine_fadd_fpext_fmul_to_fmad_or_fma: GICombineRule<
11914824e7fdSDimitry Andric  (defs root:$root, build_fn_matchinfo:$info),
11924824e7fdSDimitry Andric  (match (wip_match_opcode G_FADD):$root,
11934824e7fdSDimitry Andric         [{ return Helper.matchCombineFAddFpExtFMulToFMadOrFMA(*${root},
11944824e7fdSDimitry Andric                                                               ${info}); }]),
11954824e7fdSDimitry Andric  (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>;
11964824e7fdSDimitry Andric
11974824e7fdSDimitry Andric// Transform (fadd (fma x, y, (fmul z, u)), v)  -> (fma x, y, (fma z, u, v))
11984824e7fdSDimitry Andric//           (fadd (fmad x, y, (fmul z, u)), v) -> (fmad x, y, (fmad z, u, v))
11994824e7fdSDimitry Andric// Transform (fadd v, (fma x, y, (fmul z, u)))  -> (fma x, y, (fma z, u, v))
12004824e7fdSDimitry Andric//           (fadd v, (fmad x, y, (fmul z, u))) -> (fmad x, y, (fmad z, u, v))
12014824e7fdSDimitry Andricdef combine_fadd_fma_fmul_to_fmad_or_fma: GICombineRule<
12024824e7fdSDimitry Andric  (defs root:$root, build_fn_matchinfo:$info),
12034824e7fdSDimitry Andric  (match (wip_match_opcode G_FADD):$root,
12044824e7fdSDimitry Andric         [{ return Helper.matchCombineFAddFMAFMulToFMadOrFMA(*${root},
12054824e7fdSDimitry Andric                                                             ${info}); }]),
12064824e7fdSDimitry Andric  (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>;
12074824e7fdSDimitry Andric
12084824e7fdSDimitry Andric// Transform (fadd (fma x, y, (fpext (fmul u, v))), z) ->
12094824e7fdSDimitry Andric//           (fma x, y, (fma (fpext u), (fpext v), z))
12104824e7fdSDimitry Andricdef combine_fadd_fpext_fma_fmul_to_fmad_or_fma: GICombineRule<
12114824e7fdSDimitry Andric  (defs root:$root, build_fn_matchinfo:$info),
12124824e7fdSDimitry Andric  (match (wip_match_opcode G_FADD):$root,
12134824e7fdSDimitry Andric         [{ return Helper.matchCombineFAddFpExtFMulToFMadOrFMAAggressive(
12144824e7fdSDimitry Andric                                                  *${root}, ${info}); }]),
12154824e7fdSDimitry Andric  (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>;
12164824e7fdSDimitry Andric
12174824e7fdSDimitry Andric// Transform (fsub (fmul x, y), z) -> (fma x, y, -z)
12184824e7fdSDimitry Andric//                                 -> (fmad x, y, -z)
12194824e7fdSDimitry Andricdef combine_fsub_fmul_to_fmad_or_fma: GICombineRule<
12204824e7fdSDimitry Andric  (defs root:$root, build_fn_matchinfo:$info),
12214824e7fdSDimitry Andric  (match (wip_match_opcode G_FSUB):$root,
12224824e7fdSDimitry Andric         [{ return Helper.matchCombineFSubFMulToFMadOrFMA(*${root},
12234824e7fdSDimitry Andric                                                          ${info}); }]),
12244824e7fdSDimitry Andric  (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>;
12254824e7fdSDimitry Andric
12264824e7fdSDimitry Andric// Transform (fsub (fneg (fmul, x, y)), z) -> (fma (fneg x), y, (fneg z))
12274824e7fdSDimitry Andric//           (fsub x, (fneg (fmul, y, z))) -> (fma y, z, x)
12284824e7fdSDimitry Andricdef combine_fsub_fneg_fmul_to_fmad_or_fma: GICombineRule<
12294824e7fdSDimitry Andric  (defs root:$root, build_fn_matchinfo:$info),
12304824e7fdSDimitry Andric  (match (wip_match_opcode G_FSUB):$root,
12314824e7fdSDimitry Andric         [{ return Helper.matchCombineFSubFNegFMulToFMadOrFMA(*${root},
12324824e7fdSDimitry Andric                                                              ${info}); }]),
12334824e7fdSDimitry Andric  (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>;
12344824e7fdSDimitry Andric
12354824e7fdSDimitry Andric// Transform (fsub (fpext (fmul x, y)), z) ->
12364824e7fdSDimitry Andric//           (fma (fpext x), (fpext y), (fneg z))
12374824e7fdSDimitry Andricdef combine_fsub_fpext_fmul_to_fmad_or_fma: GICombineRule<
12384824e7fdSDimitry Andric  (defs root:$root, build_fn_matchinfo:$info),
12394824e7fdSDimitry Andric  (match (wip_match_opcode G_FSUB):$root,
12404824e7fdSDimitry Andric         [{ return Helper.matchCombineFSubFpExtFMulToFMadOrFMA(*${root},
12414824e7fdSDimitry Andric                                                               ${info}); }]),
12424824e7fdSDimitry Andric  (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>;
12434824e7fdSDimitry Andric
12444824e7fdSDimitry Andric// Transform (fsub (fneg (fpext (fmul x, y))), z) ->
12454824e7fdSDimitry Andric//           (fneg (fma (fpext x), (fpext y), z))
12464824e7fdSDimitry Andricdef combine_fsub_fpext_fneg_fmul_to_fmad_or_fma: GICombineRule<
12474824e7fdSDimitry Andric  (defs root:$root, build_fn_matchinfo:$info),
12484824e7fdSDimitry Andric  (match (wip_match_opcode G_FSUB):$root,
12494824e7fdSDimitry Andric         [{ return Helper.matchCombineFSubFpExtFNegFMulToFMadOrFMA(
12504824e7fdSDimitry Andric                                            *${root}, ${info}); }]),
12514824e7fdSDimitry Andric  (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>;
12524824e7fdSDimitry Andric
125381ad6265SDimitry Andricdef combine_minmax_nan: GICombineRule<
125481ad6265SDimitry Andric  (defs root:$root, unsigned_matchinfo:$info),
125581ad6265SDimitry Andric  (match (wip_match_opcode G_FMINNUM, G_FMAXNUM, G_FMINIMUM, G_FMAXIMUM):$root,
125681ad6265SDimitry Andric         [{ return Helper.matchCombineFMinMaxNaN(*${root}, ${info}); }]),
125781ad6265SDimitry Andric  (apply [{ Helper.replaceSingleDefInstWithOperand(*${root}, ${info}); }])>;
125881ad6265SDimitry Andric
125981ad6265SDimitry Andric// Transform (add x, (sub y, x)) -> y
126081ad6265SDimitry Andric// Transform (add (sub y, x), x) -> y
12615f757f3fSDimitry Andricdef add_sub_reg_frags : GICombinePatFrag<
12625f757f3fSDimitry Andric  (outs root:$dst), (ins $src),
12635f757f3fSDimitry Andric  [
12645f757f3fSDimitry Andric    (pattern (G_ADD $dst, $x, $tmp), (G_SUB $tmp, $src, $x)),
12655f757f3fSDimitry Andric    (pattern (G_ADD $dst, $tmp, $x), (G_SUB $tmp, $src, $x))
12665f757f3fSDimitry Andric  ]>;
126781ad6265SDimitry Andricdef add_sub_reg: GICombineRule <
12685f757f3fSDimitry Andric  (defs root:$dst),
12695f757f3fSDimitry Andric  (match (add_sub_reg_frags $dst, $src)),
12705f757f3fSDimitry Andric  (apply (GIReplaceReg $dst, $src))>;
127181ad6265SDimitry Andric
1272bdd1243dSDimitry Andricdef buildvector_identity_fold : GICombineRule<
1273bdd1243dSDimitry Andric  (defs root:$build_vector, register_matchinfo:$matchinfo),
1274bdd1243dSDimitry Andric  (match (wip_match_opcode G_BUILD_VECTOR_TRUNC, G_BUILD_VECTOR):$build_vector,
1275bdd1243dSDimitry Andric         [{ return Helper.matchBuildVectorIdentityFold(*${build_vector}, ${matchinfo}); }]),
1276bdd1243dSDimitry Andric  (apply [{ Helper.replaceSingleDefInstWithReg(*${build_vector}, ${matchinfo}); }])>;
1277bdd1243dSDimitry Andric
1278bdd1243dSDimitry Andricdef trunc_buildvector_fold : GICombineRule<
1279bdd1243dSDimitry Andric  (defs root:$op, register_matchinfo:$matchinfo),
1280bdd1243dSDimitry Andric  (match (wip_match_opcode G_TRUNC):$op,
1281bdd1243dSDimitry Andric      [{ return Helper.matchTruncBuildVectorFold(*${op}, ${matchinfo}); }]),
1282bdd1243dSDimitry Andric  (apply [{ Helper.replaceSingleDefInstWithReg(*${op}, ${matchinfo}); }])>;
1283bdd1243dSDimitry Andric
1284bdd1243dSDimitry Andricdef trunc_lshr_buildvector_fold : GICombineRule<
1285bdd1243dSDimitry Andric  (defs root:$op, register_matchinfo:$matchinfo),
1286bdd1243dSDimitry Andric  (match (wip_match_opcode G_TRUNC):$op,
1287bdd1243dSDimitry Andric      [{ return Helper.matchTruncLshrBuildVectorFold(*${op}, ${matchinfo}); }]),
1288bdd1243dSDimitry Andric  (apply [{ Helper.replaceSingleDefInstWithReg(*${op}, ${matchinfo}); }])>;
1289bdd1243dSDimitry Andric
1290bdd1243dSDimitry Andric// Transform:
1291bdd1243dSDimitry Andric//   (x + y) - y -> x
1292bdd1243dSDimitry Andric//   (x + y) - x -> y
1293bdd1243dSDimitry Andric//   x - (y + x) -> 0 - y
1294bdd1243dSDimitry Andric//   x - (x + z) -> 0 - z
1295bdd1243dSDimitry Andricdef sub_add_reg: GICombineRule <
1296bdd1243dSDimitry Andric  (defs root:$root, build_fn_matchinfo:$matchinfo),
1297bdd1243dSDimitry Andric  (match (wip_match_opcode G_SUB):$root,
1298bdd1243dSDimitry Andric         [{ return Helper.matchSubAddSameReg(*${root}, ${matchinfo}); }]),
1299bdd1243dSDimitry Andric  (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>;
1300bdd1243dSDimitry Andric
1301bdd1243dSDimitry Andricdef bitcast_bitcast_fold : GICombineRule<
1302bdd1243dSDimitry Andric  (defs root:$dst),
1303bdd1243dSDimitry Andric  (match (G_BITCAST $dst, $src1):$op, (G_BITCAST $src1, $src0),
1304bdd1243dSDimitry Andric      [{ return MRI.getType(${src0}.getReg()) == MRI.getType(${dst}.getReg()); }]),
1305bdd1243dSDimitry Andric  (apply [{ Helper.replaceSingleDefInstWithReg(*${op}, ${src0}.getReg()); }])>;
1306bdd1243dSDimitry Andric
130706c3fb27SDimitry Andric
130806c3fb27SDimitry Andricdef fptrunc_fpext_fold : GICombineRule<
130906c3fb27SDimitry Andric  (defs root:$dst),
131006c3fb27SDimitry Andric  (match (G_FPTRUNC $dst, $src1):$op, (G_FPEXT $src1, $src0),
131106c3fb27SDimitry Andric      [{ return MRI.getType(${src0}.getReg()) == MRI.getType(${dst}.getReg()); }]),
131206c3fb27SDimitry Andric  (apply [{ Helper.replaceSingleDefInstWithReg(*${op}, ${src0}.getReg()); }])>;
131306c3fb27SDimitry Andric
131406c3fb27SDimitry Andric
1315bdd1243dSDimitry Andricdef select_to_minmax: GICombineRule<
1316bdd1243dSDimitry Andric  (defs root:$root, build_fn_matchinfo:$info),
1317bdd1243dSDimitry Andric  (match (wip_match_opcode G_SELECT):$root,
1318bdd1243dSDimitry Andric         [{ return Helper.matchSimplifySelectToMinMax(*${root}, ${info}); }]),
1319bdd1243dSDimitry Andric  (apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>;
1320bdd1243dSDimitry Andric
1321*0fca6ea1SDimitry Andricdef select_to_iminmax: GICombineRule<
1322*0fca6ea1SDimitry Andric  (defs root:$root, build_fn_matchinfo:$info),
1323*0fca6ea1SDimitry Andric  (match (G_ICMP $tst, $tst1, $a, $b),
1324*0fca6ea1SDimitry Andric         (G_SELECT $root, $tst, $x, $y),
1325*0fca6ea1SDimitry Andric         [{ return Helper.matchSelectIMinMax(${root}, ${info}); }]),
1326*0fca6ea1SDimitry Andric  (apply [{ Helper.applyBuildFnMO(${root}, ${info}); }])>;
1327*0fca6ea1SDimitry Andric
1328647cbc5dSDimitry Andricdef match_selects : GICombineRule<
1329647cbc5dSDimitry Andric  (defs root:$root, build_fn_matchinfo:$matchinfo),
1330647cbc5dSDimitry Andric  (match (wip_match_opcode G_SELECT):$root,
1331647cbc5dSDimitry Andric        [{ return Helper.matchSelect(*${root}, ${matchinfo}); }]),
1332647cbc5dSDimitry Andric  (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>;
1333647cbc5dSDimitry Andric
1334*0fca6ea1SDimitry Andricdef match_ands : GICombineRule<
1335*0fca6ea1SDimitry Andric  (defs root:$root, build_fn_matchinfo:$matchinfo),
1336*0fca6ea1SDimitry Andric  (match (wip_match_opcode G_AND):$root,
1337*0fca6ea1SDimitry Andric        [{ return Helper.matchAnd(*${root}, ${matchinfo}); }]),
1338*0fca6ea1SDimitry Andric  (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>;
1339*0fca6ea1SDimitry Andric
1340*0fca6ea1SDimitry Andricdef match_ors : GICombineRule<
1341*0fca6ea1SDimitry Andric  (defs root:$root, build_fn_matchinfo:$matchinfo),
1342*0fca6ea1SDimitry Andric  (match (wip_match_opcode G_OR):$root,
1343*0fca6ea1SDimitry Andric        [{ return Helper.matchOr(*${root}, ${matchinfo}); }]),
1344*0fca6ea1SDimitry Andric  (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>;
1345*0fca6ea1SDimitry Andric
1346*0fca6ea1SDimitry Andricdef match_addos : GICombineRule<
1347*0fca6ea1SDimitry Andric  (defs root:$root, build_fn_matchinfo:$matchinfo),
1348*0fca6ea1SDimitry Andric  (match (wip_match_opcode G_SADDO, G_UADDO):$root,
1349*0fca6ea1SDimitry Andric        [{ return Helper.matchAddOverflow(*${root}, ${matchinfo}); }]),
1350*0fca6ea1SDimitry Andric  (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>;
1351*0fca6ea1SDimitry Andric
1352*0fca6ea1SDimitry Andricdef match_extract_of_element_undef_vector: GICombineRule <
1353*0fca6ea1SDimitry Andric  (defs root:$root),
1354*0fca6ea1SDimitry Andric  (match (G_IMPLICIT_DEF $vector),
1355*0fca6ea1SDimitry Andric         (G_EXTRACT_VECTOR_ELT $root, $vector, $idx)),
1356*0fca6ea1SDimitry Andric  (apply (G_IMPLICIT_DEF $root))
1357*0fca6ea1SDimitry Andric>;
1358*0fca6ea1SDimitry Andric
1359*0fca6ea1SDimitry Andricdef match_extract_of_element_undef_index: GICombineRule <
1360*0fca6ea1SDimitry Andric  (defs root:$root),
1361*0fca6ea1SDimitry Andric  (match (G_IMPLICIT_DEF $idx),
1362*0fca6ea1SDimitry Andric         (G_EXTRACT_VECTOR_ELT $root, $vector, $idx)),
1363*0fca6ea1SDimitry Andric  (apply (G_IMPLICIT_DEF $root))
1364*0fca6ea1SDimitry Andric>;
1365*0fca6ea1SDimitry Andric
1366*0fca6ea1SDimitry Andricdef match_extract_of_element : GICombineRule<
1367*0fca6ea1SDimitry Andric  (defs root:$root, build_fn_matchinfo:$matchinfo),
1368*0fca6ea1SDimitry Andric  (match (wip_match_opcode G_EXTRACT_VECTOR_ELT):$root,
1369*0fca6ea1SDimitry Andric        [{ return Helper.matchExtractVectorElement(*${root}, ${matchinfo}); }]),
1370*0fca6ea1SDimitry Andric  (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>;
1371*0fca6ea1SDimitry Andric
1372*0fca6ea1SDimitry Andricdef extract_vector_element_not_const : GICombineRule<
1373*0fca6ea1SDimitry Andric   (defs root:$root),
1374*0fca6ea1SDimitry Andric   (match (G_INSERT_VECTOR_ELT $src, $x, $value, $idx),
1375*0fca6ea1SDimitry Andric          (G_EXTRACT_VECTOR_ELT $root, $src, $idx)),
1376*0fca6ea1SDimitry Andric   (apply (GIReplaceReg $root, $value))>;
1377*0fca6ea1SDimitry Andric
1378*0fca6ea1SDimitry Andricdef extract_vector_element_different_indices : GICombineRule<
1379*0fca6ea1SDimitry Andric   (defs root:$root, build_fn_matchinfo:$matchinfo),
1380*0fca6ea1SDimitry Andric   (match (G_INSERT_VECTOR_ELT $src, $x, $value, $idx2),
1381*0fca6ea1SDimitry Andric          (G_EXTRACT_VECTOR_ELT $root, $src, $idx1),
1382*0fca6ea1SDimitry Andric   [{ return Helper.matchExtractVectorElementWithDifferentIndices(${root}, ${matchinfo}); }]),
1383*0fca6ea1SDimitry Andric   (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>;
1384*0fca6ea1SDimitry Andric
1385*0fca6ea1SDimitry Andricdef extract_vector_element_build_vector2 : GICombineRule<
1386*0fca6ea1SDimitry Andric   (defs root:$root, build_fn_matchinfo:$matchinfo),
1387*0fca6ea1SDimitry Andric   (match (G_BUILD_VECTOR $src, $x, $y),
1388*0fca6ea1SDimitry Andric          (G_EXTRACT_VECTOR_ELT $root, $src, $idx),
1389*0fca6ea1SDimitry Andric   [{ return Helper.matchExtractVectorElementWithBuildVector(${root}, ${matchinfo}); }]),
1390*0fca6ea1SDimitry Andric   (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>;
1391*0fca6ea1SDimitry Andric
1392*0fca6ea1SDimitry Andricdef extract_vector_element_build_vector3 : GICombineRule<
1393*0fca6ea1SDimitry Andric   (defs root:$root, build_fn_matchinfo:$matchinfo),
1394*0fca6ea1SDimitry Andric   (match (G_BUILD_VECTOR $src, $x, $y, $z),
1395*0fca6ea1SDimitry Andric          (G_EXTRACT_VECTOR_ELT $root, $src, $idx),
1396*0fca6ea1SDimitry Andric   [{ return Helper.matchExtractVectorElementWithBuildVector(${root}, ${matchinfo}); }]),
1397*0fca6ea1SDimitry Andric   (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>;
1398*0fca6ea1SDimitry Andric
1399*0fca6ea1SDimitry Andricdef extract_vector_element_build_vector4 : GICombineRule<
1400*0fca6ea1SDimitry Andric   (defs root:$root, build_fn_matchinfo:$matchinfo),
1401*0fca6ea1SDimitry Andric   (match (G_BUILD_VECTOR $src, $x, $y, $z, $a),
1402*0fca6ea1SDimitry Andric          (G_EXTRACT_VECTOR_ELT $root, $src, $idx),
1403*0fca6ea1SDimitry Andric   [{ return Helper.matchExtractVectorElementWithBuildVector(${root}, ${matchinfo}); }]),
1404*0fca6ea1SDimitry Andric   (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>;
1405*0fca6ea1SDimitry Andric
1406*0fca6ea1SDimitry Andricdef extract_vector_element_build_vector5 : GICombineRule<
1407*0fca6ea1SDimitry Andric   (defs root:$root, build_fn_matchinfo:$matchinfo),
1408*0fca6ea1SDimitry Andric   (match (G_BUILD_VECTOR $src, $x, $y, $z, $a, $b),
1409*0fca6ea1SDimitry Andric          (G_EXTRACT_VECTOR_ELT $root, $src, $idx),
1410*0fca6ea1SDimitry Andric   [{ return Helper.matchExtractVectorElementWithBuildVector(${root}, ${matchinfo}); }]),
1411*0fca6ea1SDimitry Andric   (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>;
1412*0fca6ea1SDimitry Andric
1413*0fca6ea1SDimitry Andricdef extract_vector_element_build_vector6 : GICombineRule<
1414*0fca6ea1SDimitry Andric   (defs root:$root, build_fn_matchinfo:$matchinfo),
1415*0fca6ea1SDimitry Andric   (match (G_BUILD_VECTOR $src, $x, $y, $z, $a, $b, $c),
1416*0fca6ea1SDimitry Andric          (G_EXTRACT_VECTOR_ELT $root, $src, $idx),
1417*0fca6ea1SDimitry Andric   [{ return Helper.matchExtractVectorElementWithBuildVector(${root}, ${matchinfo}); }]),
1418*0fca6ea1SDimitry Andric   (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>;
1419*0fca6ea1SDimitry Andric
1420*0fca6ea1SDimitry Andricdef extract_vector_element_build_vector7 : GICombineRule<
1421*0fca6ea1SDimitry Andric   (defs root:$root, build_fn_matchinfo:$matchinfo),
1422*0fca6ea1SDimitry Andric   (match (G_BUILD_VECTOR $src, $x, $y, $z, $a, $b, $c, $d),
1423*0fca6ea1SDimitry Andric          (G_EXTRACT_VECTOR_ELT $root, $src, $idx),
1424*0fca6ea1SDimitry Andric   [{ return Helper.matchExtractVectorElementWithBuildVector(${root}, ${matchinfo}); }]),
1425*0fca6ea1SDimitry Andric   (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>;
1426*0fca6ea1SDimitry Andric
1427*0fca6ea1SDimitry Andricdef extract_vector_element_build_vector8 : GICombineRule<
1428*0fca6ea1SDimitry Andric   (defs root:$root, build_fn_matchinfo:$matchinfo),
1429*0fca6ea1SDimitry Andric   (match (G_BUILD_VECTOR $src, $x, $y, $z, $a, $b, $c, $d, $e),
1430*0fca6ea1SDimitry Andric          (G_EXTRACT_VECTOR_ELT $root, $src, $idx),
1431*0fca6ea1SDimitry Andric   [{ return Helper.matchExtractVectorElementWithBuildVector(${root}, ${matchinfo}); }]),
1432*0fca6ea1SDimitry Andric   (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>;
1433*0fca6ea1SDimitry Andric
1434*0fca6ea1SDimitry Andricdef extract_vector_element_build_vector9 : GICombineRule<
1435*0fca6ea1SDimitry Andric   (defs root:$root, build_fn_matchinfo:$matchinfo),
1436*0fca6ea1SDimitry Andric   (match (G_BUILD_VECTOR $src, $x, $y, $z, $a, $b, $c, $d, $e, $f),
1437*0fca6ea1SDimitry Andric          (G_EXTRACT_VECTOR_ELT $root, $src, $idx),
1438*0fca6ea1SDimitry Andric   [{ return Helper.matchExtractVectorElementWithBuildVector(${root}, ${matchinfo}); }]),
1439*0fca6ea1SDimitry Andric   (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>;
1440*0fca6ea1SDimitry Andric
1441*0fca6ea1SDimitry Andricdef extract_vector_element_build_vector10 : GICombineRule<
1442*0fca6ea1SDimitry Andric   (defs root:$root, build_fn_matchinfo:$matchinfo),
1443*0fca6ea1SDimitry Andric   (match (G_BUILD_VECTOR $src, $x, $y, $z, $a, $b, $c, $d, $e, $f, $g),
1444*0fca6ea1SDimitry Andric          (G_EXTRACT_VECTOR_ELT $root, $src, $idx),
1445*0fca6ea1SDimitry Andric   [{ return Helper.matchExtractVectorElementWithBuildVector(${root}, ${matchinfo}); }]),
1446*0fca6ea1SDimitry Andric   (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>;
1447*0fca6ea1SDimitry Andric
1448*0fca6ea1SDimitry Andricdef extract_vector_element_build_vector11 : GICombineRule<
1449*0fca6ea1SDimitry Andric   (defs root:$root, build_fn_matchinfo:$matchinfo),
1450*0fca6ea1SDimitry Andric   (match (G_BUILD_VECTOR $src, $x, $y, $z, $a, $b, $c, $d, $e, $f, $g, $h),
1451*0fca6ea1SDimitry Andric          (G_EXTRACT_VECTOR_ELT $root, $src, $idx),
1452*0fca6ea1SDimitry Andric   [{ return Helper.matchExtractVectorElementWithBuildVector(${root}, ${matchinfo}); }]),
1453*0fca6ea1SDimitry Andric   (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>;
1454*0fca6ea1SDimitry Andric
1455*0fca6ea1SDimitry Andricdef extract_vector_element_build_vector12 : GICombineRule<
1456*0fca6ea1SDimitry Andric   (defs root:$root, build_fn_matchinfo:$matchinfo),
1457*0fca6ea1SDimitry Andric   (match (G_BUILD_VECTOR $src, $x, $y, $z, $a, $b, $c, $d, $e, $f, $g, $h, $i),
1458*0fca6ea1SDimitry Andric          (G_EXTRACT_VECTOR_ELT $root, $src, $idx),
1459*0fca6ea1SDimitry Andric   [{ return Helper.matchExtractVectorElementWithBuildVector(${root}, ${matchinfo}); }]),
1460*0fca6ea1SDimitry Andric   (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>;
1461*0fca6ea1SDimitry Andric
1462*0fca6ea1SDimitry Andricdef extract_vector_element_build_vector13 : GICombineRule<
1463*0fca6ea1SDimitry Andric   (defs root:$root, build_fn_matchinfo:$matchinfo),
1464*0fca6ea1SDimitry Andric   (match (G_BUILD_VECTOR $src, $x, $y, $z, $a, $b, $c, $d, $e, $f, $g, $h, $i, $j),
1465*0fca6ea1SDimitry Andric          (G_EXTRACT_VECTOR_ELT $root, $src, $idx),
1466*0fca6ea1SDimitry Andric   [{ return Helper.matchExtractVectorElementWithBuildVector(${root}, ${matchinfo}); }]),
1467*0fca6ea1SDimitry Andric   (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>;
1468*0fca6ea1SDimitry Andric
1469*0fca6ea1SDimitry Andricdef extract_vector_element_build_vector14 : GICombineRule<
1470*0fca6ea1SDimitry Andric   (defs root:$root, build_fn_matchinfo:$matchinfo),
1471*0fca6ea1SDimitry Andric   (match (G_BUILD_VECTOR $src, $x, $y, $z, $a, $b, $c, $d, $e, $f, $g, $h, $i, $j, $k),
1472*0fca6ea1SDimitry Andric          (G_EXTRACT_VECTOR_ELT $root, $src, $idx),
1473*0fca6ea1SDimitry Andric   [{ return Helper.matchExtractVectorElementWithBuildVector(${root}, ${matchinfo}); }]),
1474*0fca6ea1SDimitry Andric   (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>;
1475*0fca6ea1SDimitry Andric
1476*0fca6ea1SDimitry Andricdef extract_vector_element_build_vector15 : GICombineRule<
1477*0fca6ea1SDimitry Andric   (defs root:$root, build_fn_matchinfo:$matchinfo),
1478*0fca6ea1SDimitry Andric   (match (G_BUILD_VECTOR $src, $x, $y, $z, $a, $b, $c, $d, $e, $f, $g, $h, $i, $j, $k, $l),
1479*0fca6ea1SDimitry Andric          (G_EXTRACT_VECTOR_ELT $root, $src, $idx),
1480*0fca6ea1SDimitry Andric   [{ return Helper.matchExtractVectorElementWithBuildVector(${root}, ${matchinfo}); }]),
1481*0fca6ea1SDimitry Andric   (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>;
1482*0fca6ea1SDimitry Andric
1483*0fca6ea1SDimitry Andricdef extract_vector_element_build_vector16 : GICombineRule<
1484*0fca6ea1SDimitry Andric   (defs root:$root, build_fn_matchinfo:$matchinfo),
1485*0fca6ea1SDimitry Andric   (match (G_BUILD_VECTOR $src, $x, $y, $z, $a, $b, $c, $d, $e, $f, $g, $h, $i, $j, $k, $l, $m),
1486*0fca6ea1SDimitry Andric          (G_EXTRACT_VECTOR_ELT $root, $src, $idx),
1487*0fca6ea1SDimitry Andric   [{ return Helper.matchExtractVectorElementWithBuildVector(${root}, ${matchinfo}); }]),
1488*0fca6ea1SDimitry Andric   (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>;
1489*0fca6ea1SDimitry Andric
1490*0fca6ea1SDimitry Andricdef extract_vector_element_build_vector_trunc2 : GICombineRule<
1491*0fca6ea1SDimitry Andric   (defs root:$root, build_fn_matchinfo:$matchinfo),
1492*0fca6ea1SDimitry Andric   (match (G_BUILD_VECTOR_TRUNC $src, $x, $y),
1493*0fca6ea1SDimitry Andric          (G_EXTRACT_VECTOR_ELT $root, $src, $idx),
1494*0fca6ea1SDimitry Andric   [{ return Helper.matchExtractVectorElementWithBuildVectorTrunc(${root}, ${matchinfo}); }]),
1495*0fca6ea1SDimitry Andric   (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>;
1496*0fca6ea1SDimitry Andric
1497*0fca6ea1SDimitry Andricdef extract_vector_element_build_vector_trunc3 : GICombineRule<
1498*0fca6ea1SDimitry Andric   (defs root:$root, build_fn_matchinfo:$matchinfo),
1499*0fca6ea1SDimitry Andric   (match (G_BUILD_VECTOR_TRUNC $src, $x, $y, $z),
1500*0fca6ea1SDimitry Andric          (G_EXTRACT_VECTOR_ELT $root, $src, $idx),
1501*0fca6ea1SDimitry Andric   [{ return Helper.matchExtractVectorElementWithBuildVectorTrunc(${root}, ${matchinfo}); }]),
1502*0fca6ea1SDimitry Andric   (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>;
1503*0fca6ea1SDimitry Andric
1504*0fca6ea1SDimitry Andricdef extract_vector_element_build_vector_trunc4 : GICombineRule<
1505*0fca6ea1SDimitry Andric   (defs root:$root, build_fn_matchinfo:$matchinfo),
1506*0fca6ea1SDimitry Andric   (match (G_BUILD_VECTOR_TRUNC $src, $x, $y, $z, $a),
1507*0fca6ea1SDimitry Andric          (G_EXTRACT_VECTOR_ELT $root, $src, $idx),
1508*0fca6ea1SDimitry Andric   [{ return Helper.matchExtractVectorElementWithBuildVectorTrunc(${root}, ${matchinfo}); }]),
1509*0fca6ea1SDimitry Andric   (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>;
1510*0fca6ea1SDimitry Andric
1511*0fca6ea1SDimitry Andricdef extract_vector_element_build_vector_trunc5 : GICombineRule<
1512*0fca6ea1SDimitry Andric   (defs root:$root, build_fn_matchinfo:$matchinfo),
1513*0fca6ea1SDimitry Andric   (match (G_BUILD_VECTOR_TRUNC $src, $x, $y, $z, $a, $b),
1514*0fca6ea1SDimitry Andric          (G_EXTRACT_VECTOR_ELT $root, $src, $idx),
1515*0fca6ea1SDimitry Andric   [{ return Helper.matchExtractVectorElementWithBuildVectorTrunc(${root}, ${matchinfo}); }]),
1516*0fca6ea1SDimitry Andric   (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>;
1517*0fca6ea1SDimitry Andric
1518*0fca6ea1SDimitry Andricdef extract_vector_element_build_vector_trunc6 : GICombineRule<
1519*0fca6ea1SDimitry Andric   (defs root:$root, build_fn_matchinfo:$matchinfo),
1520*0fca6ea1SDimitry Andric   (match (G_BUILD_VECTOR_TRUNC $src, $x, $y, $z, $a, $b, $c),
1521*0fca6ea1SDimitry Andric          (G_EXTRACT_VECTOR_ELT $root, $src, $idx),
1522*0fca6ea1SDimitry Andric   [{ return Helper.matchExtractVectorElementWithBuildVectorTrunc(${root}, ${matchinfo}); }]),
1523*0fca6ea1SDimitry Andric   (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>;
1524*0fca6ea1SDimitry Andric
1525*0fca6ea1SDimitry Andricdef extract_vector_element_build_vector_trunc7 : GICombineRule<
1526*0fca6ea1SDimitry Andric   (defs root:$root, build_fn_matchinfo:$matchinfo),
1527*0fca6ea1SDimitry Andric   (match (G_BUILD_VECTOR_TRUNC $src, $x, $y, $z, $a, $b, $c, $d),
1528*0fca6ea1SDimitry Andric          (G_EXTRACT_VECTOR_ELT $root, $src, $idx),
1529*0fca6ea1SDimitry Andric   [{ return Helper.matchExtractVectorElementWithBuildVectorTrunc(${root}, ${matchinfo}); }]),
1530*0fca6ea1SDimitry Andric   (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>;
1531*0fca6ea1SDimitry Andric
1532*0fca6ea1SDimitry Andricdef extract_vector_element_build_vector_trunc8 : GICombineRule<
1533*0fca6ea1SDimitry Andric   (defs root:$root, build_fn_matchinfo:$matchinfo),
1534*0fca6ea1SDimitry Andric   (match (G_BUILD_VECTOR_TRUNC $src, $x, $y, $z, $a, $b, $c, $d, $e),
1535*0fca6ea1SDimitry Andric          (G_EXTRACT_VECTOR_ELT $root, $src, $idx),
1536*0fca6ea1SDimitry Andric   [{ return Helper.matchExtractVectorElementWithBuildVectorTrunc(${root}, ${matchinfo}); }]),
1537*0fca6ea1SDimitry Andric   (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>;
1538*0fca6ea1SDimitry Andric
1539*0fca6ea1SDimitry Andricdef sext_trunc : GICombineRule<
1540*0fca6ea1SDimitry Andric   (defs root:$root, build_fn_matchinfo:$matchinfo),
1541*0fca6ea1SDimitry Andric   (match (G_TRUNC $src, $x, (MIFlags NoSWrap)),
1542*0fca6ea1SDimitry Andric          (G_SEXT $root, $src),
1543*0fca6ea1SDimitry Andric   [{ return Helper.matchSextOfTrunc(${root}, ${matchinfo}); }]),
1544*0fca6ea1SDimitry Andric   (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>;
1545*0fca6ea1SDimitry Andric
1546*0fca6ea1SDimitry Andricdef zext_trunc : GICombineRule<
1547*0fca6ea1SDimitry Andric   (defs root:$root, build_fn_matchinfo:$matchinfo),
1548*0fca6ea1SDimitry Andric   (match (G_TRUNC $src, $x, (MIFlags NoUWrap)),
1549*0fca6ea1SDimitry Andric          (G_ZEXT $root, $src),
1550*0fca6ea1SDimitry Andric   [{ return Helper.matchZextOfTrunc(${root}, ${matchinfo}); }]),
1551*0fca6ea1SDimitry Andric   (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>;
1552*0fca6ea1SDimitry Andric
1553*0fca6ea1SDimitry Andricdef nneg_zext : GICombineRule<
1554*0fca6ea1SDimitry Andric   (defs root:$root, build_fn_matchinfo:$matchinfo),
1555*0fca6ea1SDimitry Andric   (match (G_ZEXT $root, $x, (MIFlags NonNeg)),
1556*0fca6ea1SDimitry Andric   [{ return Helper.matchNonNegZext(${root}, ${matchinfo}); }]),
1557*0fca6ea1SDimitry Andric   (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>;
1558*0fca6ea1SDimitry Andric
1559*0fca6ea1SDimitry Andricdef extract_vector_element_shuffle_vector : GICombineRule<
1560*0fca6ea1SDimitry Andric   (defs root:$root, build_fn_matchinfo:$matchinfo),
1561*0fca6ea1SDimitry Andric   (match (G_SHUFFLE_VECTOR $src, $src1, $src2, $mask),
1562*0fca6ea1SDimitry Andric          (G_EXTRACT_VECTOR_ELT $root, $src, $idx),
1563*0fca6ea1SDimitry Andric   [{ return Helper.matchExtractVectorElementWithShuffleVector(${root}, ${matchinfo}); }]),
1564*0fca6ea1SDimitry Andric   (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>;
1565*0fca6ea1SDimitry Andric
1566*0fca6ea1SDimitry Andric// Combines concat operations
1567*0fca6ea1SDimitry Andricdef concat_matchinfo : GIDefMatchData<"SmallVector<Register>">;
1568*0fca6ea1SDimitry Andricdef combine_concat_vector : GICombineRule<
1569*0fca6ea1SDimitry Andric  (defs root:$root, concat_matchinfo:$matchinfo),
1570*0fca6ea1SDimitry Andric  (match (wip_match_opcode G_CONCAT_VECTORS):$root,
1571*0fca6ea1SDimitry Andric        [{ return Helper.matchCombineConcatVectors(*${root}, ${matchinfo}); }]),
1572*0fca6ea1SDimitry Andric  (apply [{ Helper.applyCombineConcatVectors(*${root}, ${matchinfo}); }])>;
1573*0fca6ea1SDimitry Andric
1574*0fca6ea1SDimitry Andric// Combines Shuffles of Concats
1575*0fca6ea1SDimitry Andric// a = G_CONCAT_VECTORS x, y, undef, undef
1576*0fca6ea1SDimitry Andric// b = G_CONCAT_VECTORS z, undef, undef, undef
1577*0fca6ea1SDimitry Andric// c = G_SHUFFLE_VECTORS a, b, <0, 1, 4, undef>
1578*0fca6ea1SDimitry Andric// ===>
1579*0fca6ea1SDimitry Andric// c = G_CONCAT_VECTORS x, y, z, undef
1580*0fca6ea1SDimitry Andricdef combine_shuffle_concat : GICombineRule<
1581*0fca6ea1SDimitry Andric  (defs root:$root, concat_matchinfo:$matchinfo),
1582*0fca6ea1SDimitry Andric  (match (wip_match_opcode G_SHUFFLE_VECTOR):$root,
1583*0fca6ea1SDimitry Andric        [{ return Helper.matchCombineShuffleConcat(*${root}, ${matchinfo}); }]),
1584*0fca6ea1SDimitry Andric  (apply [{ Helper.applyCombineShuffleConcat(*${root}, ${matchinfo}); }])>;
1585*0fca6ea1SDimitry Andric
1586*0fca6ea1SDimitry Andricdef insert_vector_element_idx_undef : GICombineRule<
1587*0fca6ea1SDimitry Andric   (defs root:$root),
1588*0fca6ea1SDimitry Andric   (match (G_IMPLICIT_DEF $idx),
1589*0fca6ea1SDimitry Andric          (G_INSERT_VECTOR_ELT $root, $src, $elt, $idx)),
1590*0fca6ea1SDimitry Andric   (apply (G_IMPLICIT_DEF $root))>;
1591*0fca6ea1SDimitry Andric
1592*0fca6ea1SDimitry Andricdef insert_vector_element_elt_undef : GICombineRule<
1593*0fca6ea1SDimitry Andric   (defs root:$root),
1594*0fca6ea1SDimitry Andric   (match (G_IMPLICIT_DEF $elt),
1595*0fca6ea1SDimitry Andric          (G_INSERT_VECTOR_ELT $root, $src, $elt, $idx),
1596*0fca6ea1SDimitry Andric          [{ return isGuaranteedNotToBePoison(${src}.getReg(), MRI); }]),
1597*0fca6ea1SDimitry Andric   (apply (GIReplaceReg $root, $src))>;
1598*0fca6ea1SDimitry Andric
1599*0fca6ea1SDimitry Andricdef insert_vector_element_extract_vector_element : GICombineRule<
1600*0fca6ea1SDimitry Andric   (defs root:$root),
1601*0fca6ea1SDimitry Andric   (match (G_EXTRACT_VECTOR_ELT $elt, $src, $idx),
1602*0fca6ea1SDimitry Andric          (G_INSERT_VECTOR_ELT $root, $src, $elt, $idx)),
1603*0fca6ea1SDimitry Andric   (apply (GIReplaceReg $root, $src))>;
1604*0fca6ea1SDimitry Andric
1605*0fca6ea1SDimitry Andricdef insert_vector_elt_oob : GICombineRule<
1606*0fca6ea1SDimitry Andric  (defs root:$root, build_fn_matchinfo:$matchinfo),
1607*0fca6ea1SDimitry Andric  (match (wip_match_opcode G_INSERT_VECTOR_ELT):$root,
1608*0fca6ea1SDimitry Andric         [{ return Helper.matchInsertVectorElementOOB(*${root}, ${matchinfo}); }]),
1609*0fca6ea1SDimitry Andric  (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>;
1610*0fca6ea1SDimitry Andric
1611*0fca6ea1SDimitry Andricdef add_of_vscale : GICombineRule<
1612*0fca6ea1SDimitry Andric   (defs root:$root, build_fn_matchinfo:$matchinfo),
1613*0fca6ea1SDimitry Andric   (match (G_VSCALE $left, $imm1),
1614*0fca6ea1SDimitry Andric          (G_VSCALE $right, $imm2),
1615*0fca6ea1SDimitry Andric          (G_ADD $root, $left, $right, (MIFlags NoSWrap)),
1616*0fca6ea1SDimitry Andric   [{ return Helper.matchAddOfVScale(${root}, ${matchinfo}); }]),
1617*0fca6ea1SDimitry Andric   (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>;
1618*0fca6ea1SDimitry Andric
1619*0fca6ea1SDimitry Andricdef mul_of_vscale : GICombineRule<
1620*0fca6ea1SDimitry Andric   (defs root:$root, build_fn_matchinfo:$matchinfo),
1621*0fca6ea1SDimitry Andric   (match (G_VSCALE $left, $scale),
1622*0fca6ea1SDimitry Andric          (G_CONSTANT $x, $imm1),
1623*0fca6ea1SDimitry Andric          (G_MUL $root, $left, $x, (MIFlags NoSWrap)),
1624*0fca6ea1SDimitry Andric   [{ return Helper.matchMulOfVScale(${root}, ${matchinfo}); }]),
1625*0fca6ea1SDimitry Andric   (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>;
1626*0fca6ea1SDimitry Andric
1627*0fca6ea1SDimitry Andricdef shl_of_vscale : GICombineRule<
1628*0fca6ea1SDimitry Andric   (defs root:$root, build_fn_matchinfo:$matchinfo),
1629*0fca6ea1SDimitry Andric   (match (G_VSCALE $left, $imm),
1630*0fca6ea1SDimitry Andric          (G_CONSTANT $x, $imm1),
1631*0fca6ea1SDimitry Andric          (G_SHL $root, $left, $x, (MIFlags NoSWrap)),
1632*0fca6ea1SDimitry Andric   [{ return Helper.matchShlOfVScale(${root}, ${matchinfo}); }]),
1633*0fca6ea1SDimitry Andric   (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>;
1634*0fca6ea1SDimitry Andric
1635*0fca6ea1SDimitry Andricdef sub_of_vscale : GICombineRule<
1636*0fca6ea1SDimitry Andric   (defs root:$root, build_fn_matchinfo:$matchinfo),
1637*0fca6ea1SDimitry Andric   (match (G_VSCALE $right, $imm),
1638*0fca6ea1SDimitry Andric          (G_SUB $root, $x, $right, (MIFlags NoSWrap)),
1639*0fca6ea1SDimitry Andric   [{ return Helper.matchSubOfVScale(${root}, ${matchinfo}); }]),
1640*0fca6ea1SDimitry Andric   (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>;
1641*0fca6ea1SDimitry Andric
1642*0fca6ea1SDimitry Andricdef expand_const_fpowi : GICombineRule<
1643*0fca6ea1SDimitry Andric   (defs root:$root),
1644*0fca6ea1SDimitry Andric   (match (G_CONSTANT $int, $imm),
1645*0fca6ea1SDimitry Andric          (G_FPOWI $dst, $float, $int):$root,
1646*0fca6ea1SDimitry Andric          [{ return Helper.matchFPowIExpansion(*${root}, ${imm}.getCImm()->getSExtValue()); }]),
1647*0fca6ea1SDimitry Andric   (apply [{ Helper.applyExpandFPowI(*${root}, ${imm}.getCImm()->getSExtValue()); }])>;
1648*0fca6ea1SDimitry Andric
1649*0fca6ea1SDimitry Andric// match_extract_of_element and insert_vector_elt_oob must be the first!
1650*0fca6ea1SDimitry Andricdef vector_ops_combines: GICombineGroup<[
1651*0fca6ea1SDimitry Andricmatch_extract_of_element_undef_vector,
1652*0fca6ea1SDimitry Andricmatch_extract_of_element_undef_index,
1653*0fca6ea1SDimitry Andricinsert_vector_element_idx_undef,
1654*0fca6ea1SDimitry Andricinsert_vector_element_elt_undef,
1655*0fca6ea1SDimitry Andricmatch_extract_of_element,
1656*0fca6ea1SDimitry Andricinsert_vector_elt_oob,
1657*0fca6ea1SDimitry Andricextract_vector_element_not_const,
1658*0fca6ea1SDimitry Andricextract_vector_element_different_indices,
1659*0fca6ea1SDimitry Andricextract_vector_element_build_vector2,
1660*0fca6ea1SDimitry Andricextract_vector_element_build_vector3,
1661*0fca6ea1SDimitry Andricextract_vector_element_build_vector4,
1662*0fca6ea1SDimitry Andricextract_vector_element_build_vector5,
1663*0fca6ea1SDimitry Andricextract_vector_element_build_vector7,
1664*0fca6ea1SDimitry Andricextract_vector_element_build_vector8,
1665*0fca6ea1SDimitry Andricextract_vector_element_build_vector9,
1666*0fca6ea1SDimitry Andricextract_vector_element_build_vector10,
1667*0fca6ea1SDimitry Andricextract_vector_element_build_vector11,
1668*0fca6ea1SDimitry Andricextract_vector_element_build_vector12,
1669*0fca6ea1SDimitry Andricextract_vector_element_build_vector13,
1670*0fca6ea1SDimitry Andricextract_vector_element_build_vector14,
1671*0fca6ea1SDimitry Andricextract_vector_element_build_vector15,
1672*0fca6ea1SDimitry Andricextract_vector_element_build_vector16,
1673*0fca6ea1SDimitry Andricextract_vector_element_build_vector_trunc2,
1674*0fca6ea1SDimitry Andricextract_vector_element_build_vector_trunc3,
1675*0fca6ea1SDimitry Andricextract_vector_element_build_vector_trunc4,
1676*0fca6ea1SDimitry Andricextract_vector_element_build_vector_trunc5,
1677*0fca6ea1SDimitry Andricextract_vector_element_build_vector_trunc6,
1678*0fca6ea1SDimitry Andricextract_vector_element_build_vector_trunc7,
1679*0fca6ea1SDimitry Andricextract_vector_element_build_vector_trunc8,
1680*0fca6ea1SDimitry Andricextract_vector_element_shuffle_vector,
1681*0fca6ea1SDimitry Andricinsert_vector_element_extract_vector_element,
1682*0fca6ea1SDimitry Andricadd_of_vscale,
1683*0fca6ea1SDimitry Andricmul_of_vscale,
1684*0fca6ea1SDimitry Andricshl_of_vscale,
1685*0fca6ea1SDimitry Andricsub_of_vscale,
1686*0fca6ea1SDimitry Andric]>;
1687*0fca6ea1SDimitry Andric
1688*0fca6ea1SDimitry Andric
1689*0fca6ea1SDimitry Andric// fold ((0-A) + B) -> B-A
1690*0fca6ea1SDimitry Andricdef ZeroMinusAPlusB : GICombineRule<
1691*0fca6ea1SDimitry Andric   (defs root:$root),
1692*0fca6ea1SDimitry Andric   (match (G_SUB $sub, 0, $A),
1693*0fca6ea1SDimitry Andric          (G_ADD $root, $sub, $B)),
1694*0fca6ea1SDimitry Andric   (apply (G_SUB $root, $B, $A))>;
1695*0fca6ea1SDimitry Andric
1696*0fca6ea1SDimitry Andric// fold (A + (0-B)) -> A-B
1697*0fca6ea1SDimitry Andricdef APlusZeroMinusB : GICombineRule<
1698*0fca6ea1SDimitry Andric   (defs root:$root),
1699*0fca6ea1SDimitry Andric   (match (G_SUB $sub, 0, $B),
1700*0fca6ea1SDimitry Andric          (G_ADD $root, $A, $sub)),
1701*0fca6ea1SDimitry Andric   (apply (G_SUB $root, $A, $B))>;
1702*0fca6ea1SDimitry Andric
1703*0fca6ea1SDimitry Andric // fold (A+(B-A)) -> B
1704*0fca6ea1SDimitry Andric def APlusBMinusB : GICombineRule<
1705*0fca6ea1SDimitry Andric   (defs root:$root),
1706*0fca6ea1SDimitry Andric   (match (G_SUB $sub, $B, $A),
1707*0fca6ea1SDimitry Andric          (G_ADD $root, $A, $sub)),
1708*0fca6ea1SDimitry Andric   (apply (GIReplaceReg $root, $B))>;
1709*0fca6ea1SDimitry Andric
1710*0fca6ea1SDimitry Andric// fold ((B-A)+A) -> B
1711*0fca6ea1SDimitry Andric def BMinusAPlusA : GICombineRule<
1712*0fca6ea1SDimitry Andric   (defs root:$root),
1713*0fca6ea1SDimitry Andric   (match (G_SUB $sub, $B, $A),
1714*0fca6ea1SDimitry Andric          (G_ADD $root, $sub, $A)),
1715*0fca6ea1SDimitry Andric   (apply (GIReplaceReg $root, $B))>;
1716*0fca6ea1SDimitry Andric
1717*0fca6ea1SDimitry Andric// fold ((A-B)+(C-A)) -> (C-B)
1718*0fca6ea1SDimitry Andricdef AMinusBPlusCMinusA : GICombineRule<
1719*0fca6ea1SDimitry Andric   (defs root:$root),
1720*0fca6ea1SDimitry Andric   (match (G_SUB $sub1, $A, $B),
1721*0fca6ea1SDimitry Andric          (G_SUB $sub2, $C, $A),
1722*0fca6ea1SDimitry Andric          (G_ADD $root, $sub1, $sub2)),
1723*0fca6ea1SDimitry Andric   (apply (G_SUB $root, $C, $B))>;
1724*0fca6ea1SDimitry Andric
1725*0fca6ea1SDimitry Andric// fold ((A-B)+(B-C)) -> (A-C)
1726*0fca6ea1SDimitry Andricdef AMinusBPlusBMinusC : GICombineRule<
1727*0fca6ea1SDimitry Andric   (defs root:$root),
1728*0fca6ea1SDimitry Andric   (match (G_SUB $sub1, $A, $B),
1729*0fca6ea1SDimitry Andric          (G_SUB $sub2, $B, $C),
1730*0fca6ea1SDimitry Andric          (G_ADD $root, $sub1, $sub2)),
1731*0fca6ea1SDimitry Andric   (apply (G_SUB $root, $A, $C))>;
1732*0fca6ea1SDimitry Andric
1733*0fca6ea1SDimitry Andric// fold (A+(B-(A+C))) to (B-C)
1734*0fca6ea1SDimitry Andricdef APlusBMinusAplusC : GICombineRule<
1735*0fca6ea1SDimitry Andric   (defs root:$root),
1736*0fca6ea1SDimitry Andric   (match (G_ADD $add1, $A, $C),
1737*0fca6ea1SDimitry Andric          (G_SUB $sub1, $B, $add1),
1738*0fca6ea1SDimitry Andric          (G_ADD $root, $A, $sub1)),
1739*0fca6ea1SDimitry Andric   (apply (G_SUB $root, $B, $C))>;
1740*0fca6ea1SDimitry Andric
1741*0fca6ea1SDimitry Andric// fold (A+(B-(C+A))) to (B-C)
1742*0fca6ea1SDimitry Andricdef APlusBMinusCPlusA : GICombineRule<
1743*0fca6ea1SDimitry Andric   (defs root:$root),
1744*0fca6ea1SDimitry Andric   (match (G_ADD $add1, $C, $A),
1745*0fca6ea1SDimitry Andric          (G_SUB $sub1, $B, $add1),
1746*0fca6ea1SDimitry Andric          (G_ADD $root, $A, $sub1)),
1747*0fca6ea1SDimitry Andric   (apply (G_SUB $root, $B, $C))>;
1748*0fca6ea1SDimitry Andric
1749*0fca6ea1SDimitry Andricdef integer_reassoc_combines: GICombineGroup<[
1750*0fca6ea1SDimitry Andric  ZeroMinusAPlusB,
1751*0fca6ea1SDimitry Andric  APlusZeroMinusB,
1752*0fca6ea1SDimitry Andric  APlusBMinusB,
1753*0fca6ea1SDimitry Andric  BMinusAPlusA,
1754*0fca6ea1SDimitry Andric  AMinusBPlusCMinusA,
1755*0fca6ea1SDimitry Andric  AMinusBPlusBMinusC,
1756*0fca6ea1SDimitry Andric  APlusBMinusAplusC,
1757*0fca6ea1SDimitry Andric  APlusBMinusCPlusA
1758*0fca6ea1SDimitry Andric]>;
1759*0fca6ea1SDimitry Andric
1760*0fca6ea1SDimitry Andricdef freeze_of_non_undef_non_poison : GICombineRule<
1761*0fca6ea1SDimitry Andric   (defs root:$root),
1762*0fca6ea1SDimitry Andric   (match (G_FREEZE $root, $src),
1763*0fca6ea1SDimitry Andric          [{ return isGuaranteedNotToBeUndefOrPoison(${src}.getReg(), MRI); }]),
1764*0fca6ea1SDimitry Andric   (apply (GIReplaceReg $root, $src))>;
1765*0fca6ea1SDimitry Andric
1766*0fca6ea1SDimitry Andricdef freeze_combines: GICombineGroup<[
1767*0fca6ea1SDimitry Andric  freeze_of_non_undef_non_poison,
1768*0fca6ea1SDimitry Andric  push_freeze_to_prevent_poison_from_propagating
1769*0fca6ea1SDimitry Andric]>;
1770*0fca6ea1SDimitry Andric
17715ffd83dbSDimitry Andric// FIXME: These should use the custom predicate feature once it lands.
17725ffd83dbSDimitry Andricdef undef_combines : GICombineGroup<[undef_to_fp_zero, undef_to_int_zero,
17735ffd83dbSDimitry Andric                                     undef_to_negative_one,
1774e8d8bef9SDimitry Andric                                     binop_left_undef_to_zero,
177581ad6265SDimitry Andric                                     binop_right_undef_to_undef,
1776bdd1243dSDimitry Andric                                     unary_undef_to_zero,
17775ffd83dbSDimitry Andric                                     propagate_undef_any_op,
17785ffd83dbSDimitry Andric                                     propagate_undef_all_ops,
17795ffd83dbSDimitry Andric                                     propagate_undef_shuffle_mask,
178004eeddc0SDimitry Andric                                     erase_undef_store,
1781bdd1243dSDimitry Andric                                     unmerge_undef,
1782bdd1243dSDimitry Andric                                     insert_extract_vec_elt_out_of_bounds]>;
17835ffd83dbSDimitry Andric
17845ffd83dbSDimitry Andricdef identity_combines : GICombineGroup<[select_same_val, right_identity_zero,
17855ffd83dbSDimitry Andric                                        binop_same_val, binop_left_to_zero,
1786e8d8bef9SDimitry Andric                                        binop_right_to_zero, p2i_to_i2p,
1787e8d8bef9SDimitry Andric                                        i2p_to_p2i, anyext_trunc_fold,
178881ad6265SDimitry Andric                                        fneg_fneg_fold, right_identity_one,
1789bdd1243dSDimitry Andric                                        add_sub_reg, buildvector_identity_fold,
1790bdd1243dSDimitry Andric                                        trunc_buildvector_fold,
1791bdd1243dSDimitry Andric                                        trunc_lshr_buildvector_fold,
17925f757f3fSDimitry Andric                                        bitcast_bitcast_fold, fptrunc_fpext_fold,
1793*0fca6ea1SDimitry Andric                                        right_identity_neg_zero_fp,
1794*0fca6ea1SDimitry Andric                                        right_identity_neg_one_fp]>;
17955ffd83dbSDimitry Andric
179606c3fb27SDimitry Andricdef const_combines : GICombineGroup<[constant_fold_fp_ops, const_ptradd_to_i2p,
179781ad6265SDimitry Andric                                     overlapping_and, mulo_by_2, mulo_by_0,
1798*0fca6ea1SDimitry Andric                                     adde_to_addo,
1799*0fca6ea1SDimitry Andric                                     combine_minmax_nan, expand_const_fpowi]>;
1800e8d8bef9SDimitry Andric
1801e8d8bef9SDimitry Andricdef known_bits_simplifications : GICombineGroup<[
1802fe6060f1SDimitry Andric  redundant_and, redundant_sext_inreg, redundant_or, urem_pow2_to_mask,
1803bdd1243dSDimitry Andric  zext_trunc_fold, icmp_to_true_false_known_bits, icmp_to_lhs_known_bits,
1804bdd1243dSDimitry Andric  sext_inreg_to_zext_inreg]>;
1805e8d8bef9SDimitry Andric
1806349cc55cSDimitry Andricdef width_reduction_combines : GICombineGroup<[reduce_shl_of_extend,
1807349cc55cSDimitry Andric                                               narrow_binop_feeding_and]>;
1808e8d8bef9SDimitry Andric
1809fe6060f1SDimitry Andricdef phi_combines : GICombineGroup<[extend_through_phis]>;
1810fe6060f1SDimitry Andric
1811*0fca6ea1SDimitry Andricdef bitreverse_shift : GICombineGroup<[bitreverse_shl, bitreverse_lshr]>;
1812*0fca6ea1SDimitry Andric
181381ad6265SDimitry Andricdef select_combines : GICombineGroup<[select_undef_cmp, select_constant_cmp,
1814*0fca6ea1SDimitry Andric                                      select_to_iminmax, match_selects]>;
1815e8d8bef9SDimitry Andric
1816e8d8bef9SDimitry Andricdef trivial_combines : GICombineGroup<[copy_prop, mul_to_shl, add_p2i_to_ptradd,
1817bdd1243dSDimitry Andric                                       mul_by_neg_one, idempotent_prop]>;
1818e8d8bef9SDimitry Andric
18194824e7fdSDimitry Andricdef fma_combines : GICombineGroup<[combine_fadd_fmul_to_fmad_or_fma,
18204824e7fdSDimitry Andric  combine_fadd_fpext_fmul_to_fmad_or_fma, combine_fadd_fma_fmul_to_fmad_or_fma,
18214824e7fdSDimitry Andric  combine_fadd_fpext_fma_fmul_to_fmad_or_fma, combine_fsub_fmul_to_fmad_or_fma,
18224824e7fdSDimitry Andric  combine_fsub_fneg_fmul_to_fmad_or_fma, combine_fsub_fpext_fmul_to_fmad_or_fma,
18234824e7fdSDimitry Andric  combine_fsub_fpext_fneg_fmul_to_fmad_or_fma]>;
18244824e7fdSDimitry Andric
18255f757f3fSDimitry Andricdef constant_fold_binops : GICombineGroup<[constant_fold_binop,
18265f757f3fSDimitry Andric                                           constant_fold_fp_binop]>;
18275f757f3fSDimitry Andric
1828*0fca6ea1SDimitry Andricdef prefer_sign_combines : GICombineGroup<[nneg_zext]>;
1829*0fca6ea1SDimitry Andric
1830*0fca6ea1SDimitry Andricdef all_combines : GICombineGroup<[integer_reassoc_combines, trivial_combines,
1831*0fca6ea1SDimitry Andric    vector_ops_combines, freeze_combines,
1832*0fca6ea1SDimitry Andric    insert_vec_elt_combines, extract_vec_elt_combines, combines_for_extload,
1833*0fca6ea1SDimitry Andric    combine_extracted_vector_load,
18345f757f3fSDimitry Andric    undef_combines, identity_combines, phi_combines,
183506c3fb27SDimitry Andric    simplify_add_to_sub, hoist_logic_op_with_same_opcode_hands, shifts_too_big,
1836fe6060f1SDimitry Andric    reassocs, ptr_add_immed_chain,
1837e8d8bef9SDimitry Andric    shl_ashr_to_sext_inreg, sext_inreg_of_load,
1838e8d8bef9SDimitry Andric    width_reduction_combines, select_combines,
1839e8d8bef9SDimitry Andric    known_bits_simplifications, ext_ext_fold,
1840e8d8bef9SDimitry Andric    not_cmp_fold, opt_brcond_by_inverting_cond,
1841bdd1243dSDimitry Andric    unmerge_merge, unmerge_cst, unmerge_dead_to_trunc,
1842bdd1243dSDimitry Andric    unmerge_zext_to_zext, merge_unmerge, trunc_ext_fold, trunc_shift,
1843e8d8bef9SDimitry Andric    const_combines, xor_of_and_with_same_reg, ptr_add_with_zero,
1844fe6060f1SDimitry Andric    shift_immed_chain, shift_of_shifted_logic_chain, load_or_combine,
1845*0fca6ea1SDimitry Andric    div_rem_to_divrem, funnel_shift_combines, bitreverse_shift, commute_shift,
18465f757f3fSDimitry Andric    form_bitfield_extract, constant_fold_binops, constant_fold_fma,
18475f757f3fSDimitry Andric    constant_fold_cast_op, fabs_fneg_fold,
1848349cc55cSDimitry Andric    intdiv_combines, mulh_combines, redundant_neg_operands,
1849bdd1243dSDimitry Andric    and_or_disjoint_mask, fma_combines, fold_binop_into_select,
1850bdd1243dSDimitry Andric    sub_add_reg, select_to_minmax, redundant_binop_in_equality,
1851*0fca6ea1SDimitry Andric    fsub_to_fneg, commute_constant_to_rhs, match_ands, match_ors,
1852*0fca6ea1SDimitry Andric    combine_concat_vector, double_icmp_zero_and_or_combine, match_addos,
1853*0fca6ea1SDimitry Andric    sext_trunc, zext_trunc, prefer_sign_combines, combine_shuffle_concat]>;
1854fe6060f1SDimitry Andric
1855fe6060f1SDimitry Andric// A combine group used to for prelegalizer combiners at -O0. The combines in
1856fe6060f1SDimitry Andric// this group have been selected based on experiments to balance code size and
1857fe6060f1SDimitry Andric// compile time performance.
1858fe6060f1SDimitry Andricdef optnone_combines : GICombineGroup<[trivial_combines,
1859fe6060f1SDimitry Andric    ptr_add_immed_chain, combines_for_extload,
1860*0fca6ea1SDimitry Andric    not_cmp_fold, opt_brcond_by_inverting_cond, combine_concat_vector]>;
1861