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